From 2121c0fa233733781af5ea7a1e6356ba3360971c Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 12 May 2020 11:39:30 +0100 Subject: [PATCH] dircache: factor DirMove code out of backends into dircache Before this change there was lots of duplicated code in all the dircache using backends to support DirMove. This change factors this code into the dircache library. --- backend/box/box.go | 29 +------------ backend/drive/drive.go | 36 ++-------------- backend/onedrive/onedrive.go | 30 ++----------- backend/opendrive/opendrive.go | 31 ++------------ backend/pcloud/pcloud.go | 31 ++------------ backend/premiumizeme/premiumizeme.go | 35 +-------------- backend/putio/fs.go | 28 +----------- backend/sharefile/sharefile.go | 35 +-------------- backend/sugarsync/sugarsync.go | 29 +------------ lib/dircache/dircache.go | 64 ++++++++++++++++++++++++++++ 10 files changed, 87 insertions(+), 261 deletions(-) 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 +}