Skip to content

Commit 94b84fc

Browse files
committed
Add support for Chmod on billy.Filesystem
The billy package contains a `Change` interface type, which seems to have gone unused for several years now, presumably due to the difficulty of implementing most of the required methods for all supported platforms. This commit splits out a `Chmod` interface from it, which is supported on all platforms. The interface is implemented in all applicable abstractions. Supporting `chmod` in billy would help with issues such as go-git/go-git#588 This is a backport of commit 601c531 on main (#157). Signed-off-by: Conrad Hoffmann <[email protected]>
1 parent 9f8b16d commit 94b84fc

File tree

6 files changed

+51
-3
lines changed

6 files changed

+51
-3
lines changed

fs.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,18 @@ type Symlink interface {
128128
Readlink(link string) (string, error)
129129
}
130130

131-
// Change abstract the FileInfo change related operations in a storage-agnostic
132-
// interface as an extension to the Basic interface
133-
type Change interface {
131+
// Chmod abstracts the logic around changing file modes.
132+
type Chmod interface {
134133
// Chmod changes the mode of the named file to mode. If the file is a
135134
// symbolic link, it changes the mode of the link's target.
136135
Chmod(name string, mode os.FileMode) error
136+
}
137+
138+
// Change abstract the FileInfo change related operations in a storage-agnostic
139+
// interface as an extension to the Basic interface
140+
type Change interface {
141+
Chmod
142+
137143
// Lchown changes the numeric uid and gid of the named file. If the file is
138144
// a symbolic link, it changes the uid and gid of the link itself.
139145
Lchown(name string, uid, gid int) error

helper/chroot/chroot.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package chroot
22

33
import (
4+
"errors"
45
"os"
56
"path/filepath"
67
"strings"
@@ -200,6 +201,19 @@ func (fs *ChrootHelper) Readlink(link string) (string, error) {
200201
return string(os.PathSeparator) + target, nil
201202
}
202203

204+
func (fs *ChrootHelper) Chmod(path string, mode os.FileMode) error {
205+
fullpath, err := fs.underlyingPath(path)
206+
if err != nil {
207+
return err
208+
}
209+
210+
c, ok := fs.underlying.(billy.Chmod)
211+
if !ok {
212+
return errors.New("underlying fs does not implement billy.Chmod")
213+
}
214+
return c.Chmod(fullpath, mode)
215+
}
216+
203217
func (fs *ChrootHelper) Chroot(path string) (billy.Filesystem, error) {
204218
fullpath, err := fs.underlyingPath(path)
205219
if err != nil {

memfs/memory.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ func (fs *Memory) Remove(filename string) error {
177177
return fs.s.Remove(filename)
178178
}
179179

180+
func (fs *Memory) Chmod(path string, mode os.FileMode) error {
181+
return fs.s.Chmod(path, mode)
182+
}
183+
180184
// Falls back to Go's filepath.Join, which works differently depending on the
181185
// OS where the code is being executed.
182186
func (fs *Memory) Join(elem ...string) string {

memfs/storage.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ func (s *storage) Remove(path string) error {
169169
return nil
170170
}
171171

172+
func (s *storage) Chmod(path string, mode os.FileMode) error {
173+
path = clean(path)
174+
175+
f, has := s.Get(path)
176+
if !has {
177+
return os.ErrNotExist
178+
}
179+
180+
f.mode = mode
181+
return nil
182+
}
183+
172184
func clean(path string) string {
173185
return filepath.Clean(filepath.FromSlash(path))
174186
}

osfs/os_bound.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ func (fs *BoundOS) Readlink(link string) (string, error) {
176176
return os.Readlink(link)
177177
}
178178

179+
func (fs *BoundOS) Chmod(path string, mode os.FileMode) error {
180+
abspath, err := fs.abs(path)
181+
if err != nil {
182+
return err
183+
}
184+
return os.Chmod(abspath, mode)
185+
}
186+
179187
// Chroot returns a new OS filesystem, with the base dir set to the
180188
// result of joining the provided path with the underlying base dir.
181189
func (fs *BoundOS) Chroot(path string) (billy.Filesystem, error) {

osfs/os_chroot.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ func (fs *ChrootOS) Remove(filename string) error {
7474
return os.Remove(filename)
7575
}
7676

77+
func (fs *ChrootOS) Chmod(path string, mode os.FileMode) error {
78+
return os.Chmod(path, mode)
79+
}
80+
7781
func (fs *ChrootOS) TempFile(dir, prefix string) (billy.File, error) {
7882
if err := fs.createDir(dir + string(os.PathSeparator)); err != nil {
7983
return nil, err

0 commit comments

Comments
 (0)