diff --git a/vfs/dir.go b/vfs/dir.go index 55ab396fe..9f96b02da 100644 --- a/vfs/dir.go +++ b/vfs/dir.go @@ -96,10 +96,27 @@ func (d *Dir) Node() Node { return d } +// forgetDirPath clears the cache for itself and all subdirectories if +// they match the given path. The path is specified relative from the +// directory it is called from. +// +// It does not invalidate or clear the cache of the parent directory. +func (d *Dir) forgetDirPath(relativePath string) { + if dir := d.cachedDir(relativePath); dir != nil { + dir.walk(func(dir *Dir) { + fs.Debugf(dir.path, "forgetting directory cache") + dir.read = time.Time{} + dir.items = make(map[string]Node) + }) + } +} + // ForgetAll ensures the directory and all its children are purged // from the cache. +// +// It does not invalidate or clear the cache of the parent directory. func (d *Dir) ForgetAll() { - d.ForgetPath("", fs.EntryDirectory) + d.forgetDirPath("") } // ForgetPath clears the cache for itself and all subdirectories if @@ -126,13 +143,7 @@ func (d *Dir) ForgetPath(relativePath string, entryType fs.EntryType) { } if entryType == fs.EntryDirectory { - if dir := d.cachedDir(relativePath); dir != nil { - dir.walk(func(dir *Dir) { - fs.Debugf(dir.path, "forgetting directory cache") - dir.read = time.Time{} - dir.items = make(map[string]Node) - }) - } + d.forgetDirPath(relativePath) } } diff --git a/vfs/dir_test.go b/vfs/dir_test.go index fe0d10e0c..61fe85715 100644 --- a/vfs/dir_test.go +++ b/vfs/dir_test.go @@ -96,7 +96,7 @@ func TestDirForgetAll(t *testing.T) { dir.ForgetAll() assert.Equal(t, 1, len(root.items)) assert.Equal(t, 0, len(dir.items)) - assert.True(t, root.read.IsZero()) + assert.False(t, root.read.IsZero()) assert.True(t, dir.read.IsZero()) root.ForgetAll() @@ -521,6 +521,22 @@ func TestDirRename(t *testing.T) { file1.Path = "dir2/file3" fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, []string{"dir2"}, r.Fremote.Precision()) + // rename an empty directory + _, err = root.Mkdir("empty directory") + assert.NoError(t, err) + checkListing(t, root, []string{ + "dir2,0,true", + "empty directory,0,true", + }) + err = root.Rename("empty directory", "renamed empty directory", root) + assert.NoError(t, err) + checkListing(t, root, []string{ + "dir2,0,true", + "renamed empty directory,0,true", + }) + // ...we don't check the underlying f.Fremote because on + // bucket based remotes the directory won't be there + // read only check vfs.Opt.ReadOnly = true err = dir.Rename("potato", "tuba", dir)