diff --git a/backend/box/box.go b/backend/box/box.go index bdb75f465..73b75fa3c 100644 --- a/backend/box/box.go +++ b/backend/box/box.go @@ -944,39 +944,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } // Do the move - _, err = f.move(ctx, "/folders/", srcID, leaf, directoryID) + _, err = f.move(ctx, "/folders/", srcID, dstLeaf, dstDirectoryID) if err != nil { return err } diff --git a/backend/drive/drive.go b/backend/drive/drive.go index 5fb4a62cf..2a55f6f18 100755 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -2542,47 +2542,19 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) + srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } + _ = srcLeaf + dstDirectoryID = actualID(dstDirectoryID) - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src parent - _, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false) - if err != nil { - return err - } srcDirectoryID = actualID(srcDirectoryID) - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) - if err != nil { - return err - } // Do the move patch := drive.File{ - Name: leaf, + Name: dstLeaf, } err = f.pacer.Call(func() (bool, error) { _, err = f.svc.Files.Update(shortcutID(srcID), &patch). diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index d3a030761..7607786ab 100755 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -1159,27 +1159,13 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } + parsedDstDirID, dstDriveID, _ := parseNormalizedID(dstDirectoryID) - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) - if err != nil { - return err - } _, srcDriveID, _ := parseNormalizedID(srcID) if dstDriveID != srcDriveID { @@ -1188,16 +1174,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string return fs.ErrorCantDirMove } - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - // Get timestamps of src so they can be preserved srcInfo, _, err := srcFs.readMetaDataForPathRelativeToID(ctx, srcID, "") if err != nil { @@ -1207,7 +1183,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string // Do the move opts := newOptsCall(srcID, "PATCH", "") move := api.MoveItemRequest{ - Name: f.opt.Enc.FromStandardName(leaf), + Name: f.opt.Enc.FromStandardName(dstLeaf), ParentReference: &api.ItemReference{ DriveID: dstDriveID, ID: parsedDstDirID, diff --git a/backend/opendrive/opendrive.go b/backend/opendrive/opendrive.go index c06b96314..35f01b8be 100644 --- a/backend/opendrive/opendrive.go +++ b/backend/opendrive/opendrive.go @@ -473,33 +473,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } @@ -511,9 +486,9 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string moveFolderData := moveCopyFolder{ SessionID: f.session.SessionID, FolderID: srcID, - DstFolderID: directoryID, + DstFolderID: dstDirectoryID, Move: "true", - NewFolderName: leaf, + NewFolderName: dstLeaf, } opts := rest.Opts{ Method: "POST", diff --git a/backend/pcloud/pcloud.go b/backend/pcloud/pcloud.go index 83524e35a..450f84b70 100644 --- a/backend/pcloud/pcloud.go +++ b/backend/pcloud/pcloud.go @@ -727,33 +727,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } @@ -765,8 +740,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string Parameters: url.Values{}, } opts.Parameters.Set("folderid", dirIDtoNumber(srcID)) - opts.Parameters.Set("toname", f.opt.Enc.FromStandardName(leaf)) - opts.Parameters.Set("tofolderid", dirIDtoNumber(directoryID)) + opts.Parameters.Set("toname", f.opt.Enc.FromStandardName(dstLeaf)) + opts.Parameters.Set("tofolderid", dirIDtoNumber(dstDirectoryID)) var resp *http.Response var result api.ItemResult err = f.pacer.Call(func() (bool, error) { diff --git a/backend/premiumizeme/premiumizeme.go b/backend/premiumizeme/premiumizeme.go index bc31a121a..1d9b580e2 100644 --- a/backend/premiumizeme/premiumizeme.go +++ b/backend/premiumizeme/premiumizeme.go @@ -731,45 +731,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) - if err != nil { - return err - } - - // Find ID of src parent, not creating subdirs - srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false) + srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } // Do the move - err = f.move(ctx, false, srcID, srcLeaf, leaf, srcDirectoryID, directoryID) + err = f.move(ctx, false, srcID, srcLeaf, dstLeaf, srcDirectoryID, dstDirectoryID) if err != nil { return err } diff --git a/backend/putio/fs.go b/backend/putio/fs.go index aa779c10a..42b751ccc 100644 --- a/backend/putio/fs.go +++ b/backend/putio/fs.go @@ -625,32 +625,8 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string if !ok { return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, dstDirectoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } @@ -659,7 +635,7 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string params := url.Values{} params.Set("file_id", srcID) params.Set("parent_id", dstDirectoryID) - params.Set("name", f.opt.Enc.FromStandardName(leaf)) + params.Set("name", f.opt.Enc.FromStandardName(dstLeaf)) req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode())) if err != nil { return false, err diff --git a/backend/sharefile/sharefile.go b/backend/sharefile/sharefile.go index 202211ac3..7741f34eb 100644 --- a/backend/sharefile/sharefile.go +++ b/backend/sharefile/sharefile.go @@ -1019,45 +1019,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) - if err != nil { - return err - } - - // Find ID of src parent, not creating subdirs - srcLeaf, srcDirectoryID, err := srcFs.dirCache.FindPath(ctx, srcRemote, false) + srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } // Do the move - _, err = f.move(ctx, false, srcID, srcLeaf, leaf, srcDirectoryID, directoryID) + _, err = f.move(ctx, false, srcID, srcLeaf, dstLeaf, srcDirectoryID, dstDirectoryID) if err != nil { return err } diff --git a/backend/sugarsync/sugarsync.go b/backend/sugarsync/sugarsync.go index e41a9a23c..235c381c1 100644 --- a/backend/sugarsync/sugarsync.go +++ b/backend/sugarsync/sugarsync.go @@ -1019,39 +1019,14 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } - srcPath := path.Join(srcFs.root, srcRemote) - dstPath := path.Join(f.root, dstRemote) - // Refuse to move to or from the root - if srcPath == "" || dstPath == "" { - fs.Debugf(src, "DirMove error: Can't move root") - return errors.New("can't move root directory") - } - - // Find ID of dst parent, creating subdirs if necessary - leaf, directoryID, err := f.dirCache.FindPath(ctx, dstRemote, true) - if err != nil { - return err - } - - // Check destination does not exist - _, err = f.dirCache.FindDir(ctx, dstRemote, false) - if err == fs.ErrorDirNotFound { - // OK - } else if err != nil { - return err - } else { - return fs.ErrorDirExists - } - - // Find ID of src - srcID, err := srcFs.dirCache.FindDir(ctx, srcRemote, false) + srcID, _, _, dstDirectoryID, dstLeaf, err := f.dirCache.DirMove(ctx, srcFs.dirCache, srcFs.root, srcRemote, f.root, dstRemote) if err != nil { return err } // Do the move - err = f.moveDir(ctx, srcID, leaf, directoryID) + err = f.moveDir(ctx, srcID, dstLeaf, dstDirectoryID) if err != nil { return err } diff --git a/lib/dircache/dircache.go b/lib/dircache/dircache.go index 67a84a0c6..1b77cfdba 100644 --- a/lib/dircache/dircache.go +++ b/lib/dircache/dircache.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "fmt" + "path" "strings" "sync" @@ -368,3 +369,66 @@ func (dc *DirCache) ResetRoot() { // Put the root directory in dc.Put("", dc.rootID) } + +// DirMove prepares to move the directory (srcDC, srcRoot, srcRemote) +// into the directory (dc, dstRoot, dstRemote) +// +// It does all the checking, creates intermediate directories and +// returns leafs and IDs ready for the move. +// +// This returns +// +// - srcID - ID of the source directory +// - srcDirectoryID - ID of the parent of the source directory +// - srcLeaf - leaf name of the source directory +// - dstDirectoryID - ID of the parent of the destination directory +// - dstLeaf - leaf name of the destination directory +// +// These should be used to do the actual move then +// srcDC.FlushDir(srcRemote) should be called. +func (dc *DirCache) DirMove( + ctx context.Context, srcDC *DirCache, srcRoot, srcRemote, dstRoot, dstRemote string) (srcID, srcDirectoryID, srcLeaf, dstDirectoryID, dstLeaf string, err error) { + var ( + dstDC = dc + srcPath = path.Join(srcRoot, srcRemote) + dstPath = path.Join(dstRoot, dstRemote) + ) + + // Refuse to move to or from the root + if srcPath == "" || dstPath == "" { + // fs.Debugf(src, "DirMove error: Can't move root") + err = errors.New("can't move root directory") + return + } + + // Find ID of dst parent, creating subdirs if necessary + dstLeaf, dstDirectoryID, err = dstDC.FindPath(ctx, dstRemote, true) + if err != nil { + return + } + + // Check destination does not exist + _, err = dstDC.FindDir(ctx, dstRemote, false) + if err == fs.ErrorDirNotFound { + // OK + } else if err != nil { + return + } else { + err = fs.ErrorDirExists + return + } + + // Find ID of src parent + srcLeaf, srcDirectoryID, err = srcDC.FindPath(ctx, srcRemote, false) + if err != nil { + return + } + + // Find ID of src + srcID, err = srcDC.FindDir(ctx, srcRemote, false) + if err != nil { + return + } + + return +}