Skip to content

Commit

Permalink
Improve the fs options and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidtw committed Oct 4, 2023
1 parent ddcdda7 commit 69f0027
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 53 deletions.
99 changes: 84 additions & 15 deletions internal/fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var (
errUnknown = errors.New("unknown error")
)

func TestMakeDir(t *testing.T) {
func TestWithDirOrSimiar(t *testing.T) {
tests := []struct {
description string
opt xafs.Option
Expand All @@ -29,40 +29,104 @@ func TestMakeDir(t *testing.T) {
}{
{
description: "simple path",
opt: xafs.MakeDir("foo", 0755),
opt: xafs.WithDir("foo", 0755),
expect: mem.New(mem.WithDir("foo", 0755)),
}, {
description: "simple existing path",
opt: xafs.MakeDir("foo", 0755),
opt: xafs.WithDir("foo", 0755),
start: mem.New(mem.WithDir("foo", 0755)),
expect: mem.New(mem.WithDir("foo", 0755)),
}, {
description: "not a directory",
opt: xafs.MakeDir("foo", 0755),
opt: xafs.WithDir("foo", 0755),
start: mem.New(mem.WithFile("foo", "data", 0755)),
expectErr: xafs.ErrNotDirectory,
}, {
description: "not able to read",
opt: xafs.MakeDir("foo", 0755),
start: mem.New(mem.WithDir("foo", 0111)),
expectErr: fs.ErrPermission,
}, {
description: "error opening the file",
opt: xafs.MakeDir("foo", 0755),
opt: xafs.WithDir("foo", 0755),
start: mem.New(mem.WithError("foo", errUnknown)),
expectErr: errUnknown,
}, {
description: "two directory path",
description: "three directory path",
opts: []xafs.Option{
xafs.MakeDir("foo", 0700),
xafs.MakeDir("foo/bar", 0750),
xafs.MakeDir("foo/bar/car", 0755),
xafs.WithDir("foo", 0700),
xafs.WithDir("foo/bar", 0750),
xafs.WithDir("foo/bar/car", 0755),
},
expect: mem.New(
mem.WithDir("foo", 0700),
mem.WithDir("foo/bar", 0750),
mem.WithDir("foo/bar/car", 0755),
),
}, {
description: "abs directory path",
start: mem.New(mem.WithDir("/", 0755)),
opts: []xafs.Option{
xafs.WithDir("/foo", 0700),
xafs.WithDir("/foo/bar", 0750),
xafs.WithDir("/foo/bar/car", 0755),
},
expect: mem.New(
mem.WithDir("/", 0755),
mem.WithDir("/foo", 0700),
mem.WithDir("/foo/bar", 0750),
mem.WithDir("/foo/bar/car", 0755),
),
}, {
description: "WithDirs three directory path",
start: mem.New(),
opts: []xafs.Option{
xafs.WithDirs("foo/bar/car", 0755),
},
expect: mem.New(
mem.WithDir("foo", 0755),
mem.WithDir("foo/bar", 0755),
mem.WithDir("foo/bar/car", 0755),
),
}, {
description: "WithDirs three directory path one exists",
start: mem.New(mem.WithDir("foo", 0711)),
opts: []xafs.Option{
xafs.WithDirs("foo/bar/car", 0755),
},
expect: mem.New(
mem.WithDir("foo", 0711),
mem.WithDir("foo/bar", 0755),
mem.WithDir("foo/bar/car", 0755),
),
}, {
description: "abs three directory path",
start: mem.New(mem.WithDir("/", 0700)),
opts: []xafs.Option{
xafs.WithDirs("/boo/egg/cat", 0755),
},
expect: mem.New(
mem.WithDir("/", 0700),
mem.WithDir("/boo", 0755),
mem.WithDir("/boo/egg", 0755),
mem.WithDir("/boo/egg/cat", 0755),
),
}, {
description: "WithPath two directory path one exists, and a filename",
start: mem.New(mem.WithDir("foo", 0711)),
opts: []xafs.Option{
xafs.WithPath("foo/bar/car.json", 0755),
},
expect: mem.New(
mem.WithDir("foo", 0711),
mem.WithDir("foo/bar", 0755),
),
}, {
description: "Ensure Operate can handle nil options",
start: mem.New(mem.WithDir("foo", 0711)),
opts: []xafs.Option{
nil,
xafs.WithPath("foo/bar/car.json", 0755),
},
expect: mem.New(
mem.WithDir("foo", 0711),
mem.WithDir("foo/bar", 0755),
),
},
}

Expand All @@ -71,7 +135,12 @@ func TestMakeDir(t *testing.T) {
require := require.New(t)
assert := assert.New(t)

opts := append(tc.opts, tc.opt)
opts := make([]xafs.Option, 0, len(tc.opts)+1)
if tc.opt != nil {
opts = append(tc.opts, tc.opt)
}
opts = append(opts, tc.opts...)

fs := tc.start
if fs == nil {
fs = mem.New()
Expand Down
28 changes: 4 additions & 24 deletions internal/fs/mem/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ func (fs *FS) Open(name string) (iofs.File, error) {
}

func (fs *FS) Mkdir(path string, perm iofs.FileMode) error {
if err := fs.hasPerms(path, iofs.FileMode(0111)); err != nil {
return err
if path != separator {
if err := fs.hasPerms(path, iofs.FileMode(0111)); err != nil {
return err
}
}

if fs.Dirs == nil {
Expand Down Expand Up @@ -201,25 +203,3 @@ func (fs *FS) hasPerms(name string, perm iofs.FileMode) error {

return nil
}

// Remove this in favor of pp ... except I can't download pp right now.
/*
func (fs *FS) String() string {
buf := strings.Builder{}
buf.WriteString("Files:\n")
for k, v := range fs.Files {
fmt.Fprintf(&buf, " '%s': '%s'\n", k, string(v.Bytes))
}
buf.WriteString("Dirs:\n")
for k, v := range fs.Dirs {
fmt.Fprintf(&buf, " '%s': %v\n", k, v)
}
buf.WriteString("Errs:\n")
for k, v := range fs.Errs {
fmt.Fprintf(&buf, " '%s': %v\n", k, v)
}
return buf.String()
}
*/
61 changes: 47 additions & 14 deletions internal/fs/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ var (
ErrInvalidSHA = errors.New("invalid SHA for file")
)

// MakeDir is an option that ensures the specified directory exists with the
// specified permissions.
func MakeDir(dir string, perm fs.FileMode) Option {
// Options provides a way to group multiple options together.
func Options(opts ...Option) Option {
return OptionFunc(
func(f FS) error {
return Operate(f, opts...)
})
}

// WithDir is an option that ensures the specified directory exists. If it
// does not, create it with the specified permissions.
func WithDir(dir string, perm fs.FileMode) Option {
return OptionFunc(
func(f FS) error {
file, err := f.Open(dir)
Expand All @@ -33,21 +41,46 @@ func MakeDir(dir string, perm fs.FileMode) Option {
defer file.Close()

stat, err := file.Stat()
if err != nil {
return err
if err == nil {
if !stat.IsDir() {
return ErrNotDirectory
}
}

if !stat.IsDir() {
return ErrNotDirectory
}
return err
})
}

mode := stat.Mode()
if (mode & fs.ModePerm & perm) != (fs.ModePerm & perm) {
return fs.ErrPermission
}
// WithDirs is an option that ensures the specified directory path exists with
// the specified permissions. The path is split on the path separator and
// each directory is created in order if needed.
//
// Notes:
// - The path should not contain the filename or that will be created as a directory.
// - The same permissions are applied to all directories that are created.
func WithDirs(path string, perm fs.FileMode) Option {
dirs := strings.Split(path, string(filepath.Separator))
if filepath.IsAbs(path) {
dirs[0] = string(filepath.Separator)
}

var full string
opts := make([]Option, 0, len(dirs))
for _, dir := range dirs {
full = filepath.Join(full, dir)
opts = append(opts, WithDir(full, perm))
}
return Options(opts...)
}

return nil
})
// WithPath is an option that ensures the set of directories for the specified
// file exists. The directory is determined by calling filepath.Dir on the name.
//
// Notes:
// - The name should contain the filename and any path to ensure is present.
// - The same permissions are applied to all directories that are created.
func WithPath(name string, perm fs.FileMode) Option {
return WithDirs(filepath.Dir(name), perm)
}

// WriteFileWithSHA256 calculates and writes both the file and a checksum file.
Expand Down

0 comments on commit 69f0027

Please sign in to comment.