From a56cd52025d3b8939c349af5fd41ce5222384c7d Mon Sep 17 00:00:00 2001 From: nielash Date: Sun, 28 Apr 2024 07:47:24 -0400 Subject: [PATCH] vfs: fix renaming a directory Before this change, renaming a directory d failed to rename its key in d.parent.items, which caused trouble later when doing Dir.Stat on a subdirectory. This change fixes the issue. --- vfs/dir.go | 13 +++++++++++++ vfs/dir_test.go | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/vfs/dir.go b/vfs/dir.go index 47ffd8aaa..70252559d 100644 --- a/vfs/dir.go +++ b/vfs/dir.go @@ -371,7 +371,9 @@ func (d *Dir) renameTree(dirPath string) { // Make sure the path is correct for each node if d.path != dirPath { fs.Debugf(d.path, "Renaming to %q", dirPath) + delete(d.parent.items, name(d.path)) d.path = dirPath + d.parent.items[name(d.path)] = d d.entry = fs.NewDirCopy(context.TODO(), d.entry).SetRemote(dirPath) } @@ -404,6 +406,8 @@ func (d *Dir) rename(newParent *Dir, fsDir fs.Directory) { d.entry = fsDir d.path = fsDir.Remote() newPath := d.path + delete(d.parent.items, name(oldPath)) + d.parent.items[name(d.path)] = d d.read = time.Time{} d.mu.Unlock() @@ -418,6 +422,15 @@ func (d *Dir) rename(newParent *Dir, fsDir fs.Directory) { } } +// convert path to name +func name(p string) string { + p = path.Base(p) + if p == "." { + p = "/" + } + return p +} + // addObject adds a new object or directory to the directory // // The name passed in is marked as virtual as it hasn't been read from a remote diff --git a/vfs/dir_test.go b/vfs/dir_test.go index ff70b7408..754a5bf3c 100644 --- a/vfs/dir_test.go +++ b/vfs/dir_test.go @@ -589,6 +589,19 @@ func TestDirRename(t *testing.T) { vfs.Opt.ReadOnly = true err = dir.Rename("potato", "tuba", dir) assert.Equal(t, EROFS, err) + + // Rename a dir, check that key was correctly renamed in dir.parent.items + vfs.Opt.ReadOnly = false + _, ok := dir.parent.items["dir2"] + assert.True(t, ok, "dir.parent.items should have 'dir2' key before rename") + _, ok = dir.parent.items["dir3"] + assert.False(t, ok, "dir.parent.items should not have 'dir3' key before rename") + dir.renameTree("dir3") // rename dir2 to dir3 + _, ok = dir.parent.items["dir2"] + assert.False(t, ok, "dir.parent.items should not have 'dir2' key after rename") + d, ok := dir.parent.items["dir3"] + assert.True(t, ok, fmt.Sprintf("expected to find 'dir3' key in dir.parent.items after rename, got %v", dir.parent.items)) + assert.Equal(t, dir, d, `expected renamed dir to match value of dir.parent.items["dir3"]`) } func TestDirStructSize(t *testing.T) {