From 3d5106e52b1c707e488df61cfe77ab3942ce939c Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 14 Apr 2018 17:15:00 +0100 Subject: [PATCH] drive: fix DirMove leaving a hardlinked directory behind #2245 This bug was introduced by the v3 API conversion in 07f20dd1fd. The problem was that dircache.FindPath doesn't work for the root directory. This adds an internal error for dircache.FindPath being called with the root directory. This makes a failing test, which the fix to the drive backend fixes. This also improves the DirCache integration test. --- backend/drive/drive.go | 8 +++++++- fstest/fstests/fstests.go | 28 ++++++++++++++++++++++++---- lib/dircache/dircache.go | 6 ++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/backend/drive/drive.go b/backend/drive/drive.go index fb9351fe6..88c8eb601 100644 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -1195,10 +1195,16 @@ func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error { } // Find ID of src parent - _, srcDirectoryID, err := srcFs.dirCache.FindPath(srcRemote, false) + var srcDirectoryID string + if srcRemote == "" { + srcDirectoryID, err = srcFs.dirCache.RootParentID() + } else { + _, srcDirectoryID, err = srcFs.dirCache.FindPath(srcRemote, false) + } if err != nil { return err } + // Find ID of src srcID, err := srcFs.dirCache.FindDir(srcRemote, false) if err != nil { diff --git a/fstest/fstests/fstests.go b/fstest/fstests/fstests.go index bdf9b326a..dc32a80f8 100644 --- a/fstest/fstests/fstests.go +++ b/fstest/fstests/fstests.go @@ -626,6 +626,9 @@ func Run(t *testing.T, opt *Opt) { fstest.CheckListing(t, remote, []fstest.Item{file1, file2}) // 1: file name.txt // 2: hello sausage?/../z.txt + + // Tidy up moveTest directory + require.NoError(t, remote.Rmdir("moveTest")) }) // Move src to this remote using server side move operations. @@ -664,21 +667,38 @@ func Run(t *testing.T, opt *Opt) { // check remotes // FIXME: Prints errors. - fstest.CheckListing(t, remote, []fstest.Item{}) + // remote should not exist here + _, err = remote.List("") + require.Equal(t, fs.ErrorDirNotFound, errors.Cause(err)) + //fstest.CheckListingWithPrecision(t, remote, []fstest.Item{}, []string{}, remote.Precision()) file1Copy := file1 file1Copy.Path = path.Join(newName, file1.Path) file2Copy := file2 file2Copy.Path = path.Join(newName, file2.Path) file2Copy.WinPath = path.Join(newName, file2.WinPath) - fstest.CheckListing(t, newRemote, []fstest.Item{file2Copy, file1Copy}) + fstest.CheckListingWithPrecision(t, newRemote, []fstest.Item{file2Copy, file1Copy}, []string{ + "new_name", + "new_name/sub_new_name", + "new_name/sub_new_name/hello? sausage", + "new_name/sub_new_name/hello? sausage/êé", + "new_name/sub_new_name/hello? sausage/êé/Hello, 世界", + "new_name/sub_new_name/hello? sausage/êé/Hello, 世界/ \" ' @ < > & ? + ≠", + }, newRemote.Precision()) // move it back err = doDirMove(newRemote, newName, "") require.NoError(t, err) // check remotes - fstest.CheckListing(t, remote, []fstest.Item{file2, file1}) - fstest.CheckListing(t, newRemote, []fstest.Item{}) + fstest.CheckListingWithPrecision(t, remote, []fstest.Item{file2, file1}, []string{ + "hello? sausage", + "hello? sausage/êé", + "hello? sausage/êé/Hello, 世界", + "hello? sausage/êé/Hello, 世界/ \" ' @ < > & ? + ≠", + }, remote.Precision()) + fstest.CheckListingWithPrecision(t, newRemote, []fstest.Item{}, []string{ + "new_name", + }, newRemote.Precision()) }) // TestFsRmdirFull tests removing a non empty directory diff --git a/lib/dircache/dircache.go b/lib/dircache/dircache.go index 19fcd171f..62564bc2b 100644 --- a/lib/dircache/dircache.go +++ b/lib/dircache/dircache.go @@ -204,8 +204,14 @@ func (dc *DirCache) _findDir(path string, create bool) (pathID string, err error // FindPath finds the leaf and directoryID from a path // +// Do not call FindPath with the root directory - it will return an error +// // If create is set parent directories will be created if they don't exist func (dc *DirCache) FindPath(path string, create bool) (leaf, directoryID string, err error) { + if path == "" { + err = errors.New("internal error: can't call FindPath with root directory") + return + } dc.mu.Lock() defer dc.mu.Unlock() directory, leaf := SplitPath(path)