vfs: add MkdirAll function to make a directory and all beneath

This commit is contained in:
Nick Craig-Wood 2023-04-12 11:58:22 +01:00
parent 451f4c2a8f
commit ca403dc90e
2 changed files with 121 additions and 7 deletions

View File

@ -654,18 +654,54 @@ func (vfs *VFS) Chtimes(name string, atime time.Time, mtime time.Time) error {
return nil return nil
} }
// mkdir creates a new directory with the specified name and permission bits
// (before umask) returning the new directory node.
func (vfs *VFS) mkdir(name string, perm os.FileMode) (*Dir, error) {
dir, leaf, err := vfs.StatParent(name)
if err != nil {
return nil, err
}
return dir.Mkdir(leaf)
}
// Mkdir creates a new directory with the specified name and permission bits // Mkdir creates a new directory with the specified name and permission bits
// (before umask). // (before umask).
func (vfs *VFS) Mkdir(name string, perm os.FileMode) error { func (vfs *VFS) Mkdir(name string, perm os.FileMode) error {
dir, leaf, err := vfs.StatParent(name) _, err := vfs.mkdir(name, perm)
if err != nil {
return err return err
}
// mkdirAll creates a new directory with the specified name and
// permission bits (before umask) and all of its parent directories up
// to the root.
func (vfs *VFS) mkdirAll(name string, perm os.FileMode) (dir *Dir, err error) {
name = strings.Trim(name, "/")
// the root directory node already exists even if the directory isn't created yet
if name == "" {
return vfs.root, nil
}
var parent, leaf string
dir, leaf, err = vfs.StatParent(name)
if err == ENOENT {
parent, leaf = path.Split(name)
dir, err = vfs.mkdirAll(parent, perm)
} }
_, err = dir.Mkdir(leaf)
if err != nil { if err != nil {
return err return nil, err
} }
return nil dir, err = dir.Mkdir(leaf)
if err != nil {
return nil, err
}
return dir, nil
}
// MkdirAll creates a new directory with the specified name and
// permission bits (before umask) and all of its parent directories up
// to the root.
func (vfs *VFS) MkdirAll(name string, perm os.FileMode) error {
_, err := vfs.mkdirAll(name, perm)
return err
} }
// ReadDir reads the directory named by dirname and returns // ReadDir reads the directory named by dirname and returns

View File

@ -364,6 +364,84 @@ func TestVFSStatfs(t *testing.T) {
assert.Equal(t, oldTime, vfs.usageTime) assert.Equal(t, oldTime, vfs.usageTime)
} }
func TestVFSMkdir(t *testing.T) {
r, vfs := newTestVFS(t)
if !r.Fremote.Features().CanHaveEmptyDirectories {
return // can't test if can't have empty directories
}
r.CheckRemoteListing(t, nil, []string{})
// Try making the root
err := vfs.Mkdir("", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{})
// Try making a sub directory
err = vfs.Mkdir("a", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a"})
// Try making an existing directory
err = vfs.Mkdir("a", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a"})
// Try making a new directory
err = vfs.Mkdir("b/", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "b"})
// Try making a new directory
err = vfs.Mkdir("/c", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "b", "c"})
// Try making a new directory
err = vfs.Mkdir("/d/", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "b", "c", "d"})
}
func TestVFSMkdirAll(t *testing.T) {
r, vfs := newTestVFS(t)
if !r.Fremote.Features().CanHaveEmptyDirectories {
return // can't test if can't have empty directories
}
r.CheckRemoteListing(t, nil, []string{})
// Try making the root
err := vfs.MkdirAll("", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{})
// Try making a sub directory
err = vfs.MkdirAll("a/b/c/d", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
// Try making an existing directory
err = vfs.MkdirAll("a/b/c", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
// Try making an existing directory
err = vfs.MkdirAll("/a/b/c/", 0777)
require.NoError(t, err)
r.CheckRemoteListing(t, nil, []string{"a", "a/b", "a/b/c", "a/b/c/d"})
}
func TestFillInMissingSizes(t *testing.T) { func TestFillInMissingSizes(t *testing.T) {
const unknownFree = 10 const unknownFree = 10
for _, test := range []struct { for _, test := range []struct {