From 137f7f62fbc4161b67360a45cb761a3bf255aa2c Mon Sep 17 00:00:00 2001 From: nielash Date: Fri, 9 Feb 2024 10:37:14 -0500 Subject: [PATCH] sync: use operations.DirMove instead of sync.MoveDir for --fix-case - #7591 This should be more efficient for the purposes of --fix-case, as operations.DirMove accepts `srcRemote` and `dstRemote` arguments, while sync.MoveDir does not. This also factors the two-step-move logic to operations.DirMoveCaseInsensitive, so that it is reusable by other commands. --- fs/operations/operations.go | 11 +++++++++++ fs/sync/sync.go | 23 ++++------------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/fs/operations/operations.go b/fs/operations/operations.go index c68f468ff..95d987d05 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -2288,6 +2288,17 @@ func DirMove(ctx context.Context, f fs.Fs, srcRemote, dstRemote string) (err err return nil } +// DirMoveCaseInsensitive does DirMove in two steps (to temp name, then real name) +// which is necessary for some case-insensitive backends +func DirMoveCaseInsensitive(ctx context.Context, f fs.Fs, srcRemote, dstRemote string) (err error) { + tmpDstRemote := dstRemote + "-rclone-move-" + random.String(8) + err = DirMove(ctx, f, srcRemote, tmpDstRemote) + if err != nil { + return err + } + return DirMove(ctx, f, tmpDstRemote, dstRemote) +} + // FsInfo provides information about a remote type FsInfo struct { // Name of the remote (as passed into NewFs) diff --git a/fs/sync/sync.go b/fs/sync/sync.go index ddbe03a07..c464235c0 100644 --- a/fs/sync/sync.go +++ b/fs/sync/sync.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "path" - "path/filepath" "sort" "strings" "sync" @@ -19,7 +18,6 @@ import ( "github.com/rclone/rclone/fs/hash" "github.com/rclone/rclone/fs/march" "github.com/rclone/rclone/fs/operations" - "github.com/rclone/rclone/lib/random" ) // ErrorMaxDurationReached defines error when transfer duration is reached @@ -1151,25 +1149,12 @@ func (s *syncCopyMove) Match(ctx context.Context, dst, src fs.DirEntry) (recurse if s.ci.FixCase && !s.ci.Immutable && src.Remote() != dst.Remote() { // Fix case for case insensitive filesystems // Fix each dir before recursing into subdirs and files - oldDirFs, err := fs.NewFs(s.ctx, filepath.Join(fs.ConfigStringFull(s.fdst), dst.Remote())) - s.processError(err) - newDirPath := filepath.Join(fs.ConfigStringFull(s.fdst), filepath.Dir(dst.Remote()), filepath.Base(src.Remote())) - newDirFs, err := fs.NewFs(s.ctx, newDirPath) - s.processError(err) - // Create random name to temporarily move dir to - tmpDirName := newDirPath + "-rclone-move-" + random.String(8) - tmpDirFs, err := fs.NewFs(s.ctx, tmpDirName) - s.processError(err) - if err = MoveDir(s.ctx, tmpDirFs, oldDirFs, s.deleteEmptySrcDirs, s.copyEmptySrcDirs); err != nil { - fs.Errorf(dst, "Error while attempting to move dir to temporary location %s: %v", tmpDirName, err) + err := operations.DirMoveCaseInsensitive(s.ctx, s.fdst, dst.Remote(), src.Remote()) + if err != nil { + fs.Errorf(dst, "Error while attempting to rename to %s: %v", src.Remote(), err) s.processError(err) } else { - if err = MoveDir(s.ctx, newDirFs, tmpDirFs, s.deleteEmptySrcDirs, s.copyEmptySrcDirs); err != nil { - fs.Errorf(dst, "Error while attempting to rename to %s: %v", src.Remote(), err) - s.processError(err) - } else { - fs.Infof(dst, "Fixed case by renaming to: %s", src.Remote()) - } + fs.Infof(dst, "Fixed case by renaming to: %s", src.Remote()) } }