vfs: stop empty dirs disappearing when renamed on bucket based remotes

Before this change when we renamed a directory this cleared the
directory cache for the parent directory too.

If the directory was remaining in the same parent this wasn't
necessary and caused the empty directory to fall out of the cache.

Fixes #3597
s3-about
Nick Craig-Wood 2019-10-08 07:45:02 +01:00
parent b63e9befe8
commit 1fe1a19339
2 changed files with 36 additions and 9 deletions

View File

@ -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)
}
}

View File

@ -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)