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.
This commit is contained in:
Nick Craig-Wood 2018-04-14 17:15:00 +01:00
parent 29ce1c2747
commit 3d5106e52b
3 changed files with 37 additions and 5 deletions

View file

@ -1195,10 +1195,16 @@ func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
} }
// Find ID of src parent // 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 { if err != nil {
return err return err
} }
// Find ID of src // Find ID of src
srcID, err := srcFs.dirCache.FindDir(srcRemote, false) srcID, err := srcFs.dirCache.FindDir(srcRemote, false)
if err != nil { if err != nil {

View file

@ -626,6 +626,9 @@ func Run(t *testing.T, opt *Opt) {
fstest.CheckListing(t, remote, []fstest.Item{file1, file2}) fstest.CheckListing(t, remote, []fstest.Item{file1, file2})
// 1: file name.txt // 1: file name.txt
// 2: hello sausage?/../z.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. // Move src to this remote using server side move operations.
@ -664,21 +667,38 @@ func Run(t *testing.T, opt *Opt) {
// check remotes // check remotes
// FIXME: Prints errors. // 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 := file1
file1Copy.Path = path.Join(newName, file1.Path) file1Copy.Path = path.Join(newName, file1.Path)
file2Copy := file2 file2Copy := file2
file2Copy.Path = path.Join(newName, file2.Path) file2Copy.Path = path.Join(newName, file2.Path)
file2Copy.WinPath = path.Join(newName, file2.WinPath) 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 // move it back
err = doDirMove(newRemote, newName, "") err = doDirMove(newRemote, newName, "")
require.NoError(t, err) require.NoError(t, err)
// check remotes // check remotes
fstest.CheckListing(t, remote, []fstest.Item{file2, file1}) fstest.CheckListingWithPrecision(t, remote, []fstest.Item{file2, file1}, []string{
fstest.CheckListing(t, newRemote, []fstest.Item{}) "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 // TestFsRmdirFull tests removing a non empty directory

View file

@ -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 // 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 // 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) { 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() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
directory, leaf := SplitPath(path) directory, leaf := SplitPath(path)