From e7c20e0bce14ae62957febbb32300c354cc9b1da Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 23 May 2019 13:17:16 +0100 Subject: [PATCH] operations: make move and copy individual files obey --backup-dir Before this change, when using rclone copy or move with --backup-dir and the source was a single file, rclone would fail to use the backup directory. This change looks up the backup directory in the Fs cache and uses it as appropriate. This affects any commands which call operations.MoveFile or operations.CopyFile which includes rclone move/moveto/copy/copyto where the source is a single file. Fixes #3219 --- fs/operations/operations.go | 17 ++++++++++++ fs/operations/operations_test.go | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/fs/operations/operations.go b/fs/operations/operations.go index 820737841..a142140a2 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -19,6 +19,7 @@ import ( "github.com/ncw/rclone/fs" "github.com/ncw/rclone/fs/accounting" + "github.com/ncw/rclone/fs/cache" "github.com/ncw/rclone/fs/fserrors" "github.com/ncw/rclone/fs/fshttp" "github.com/ncw/rclone/fs/hash" @@ -1475,6 +1476,22 @@ func moveOrCopyFile(fdst fs.Fs, fsrc fs.Fs, dstFileName string, srcFileName stri } if NeedTransfer(dstObj, srcObj) { + // If destination already exists, then we must move it into --backup-dir if required + if dstObj != nil && fs.Config.BackupDir != "" { + backupDir, err := cache.Get(fs.Config.BackupDir) + if err != nil { + return errors.Wrap(err, "creating Fs for --backup-dir failed") + } + remoteWithSuffix := SuffixName(dstObj.Remote()) + overwritten, _ := backupDir.NewObject(remoteWithSuffix) + _, err = Move(backupDir, overwritten, remoteWithSuffix, dstObj) + if err != nil { + return errors.Wrap(err, "moving to --backup-dir failed") + } + // If successful zero out the dstObj as it is no longer there + dstObj = nil + } + _, err = Op(fdst, dstObj, dstFileName, srcObj) } else { accounting.Stats.Checking(srcFileName) diff --git a/fs/operations/operations_test.go b/fs/operations/operations_test.go index 42cbd8945..09cc60c64 100644 --- a/fs/operations/operations_test.go +++ b/fs/operations/operations_test.go @@ -739,6 +739,29 @@ func TestMoveFile(t *testing.T) { fstest.CheckItems(t, r.Fremote, file2) } +func TestMoveFileBackupDir(t *testing.T) { + r := fstest.NewRun(t) + defer r.Finalise() + + oldBackupDir := fs.Config.BackupDir + fs.Config.BackupDir = r.FremoteName + "/backup" + defer func() { + fs.Config.BackupDir = oldBackupDir + }() + + file1 := r.WriteFile("dst/file1", "file1 contents", t1) + fstest.CheckItems(t, r.Flocal, file1) + + file1old := r.WriteObject("dst/file1", "file1 contents old", t1) + fstest.CheckItems(t, r.Fremote, file1old) + + err := operations.MoveFile(r.Fremote, r.Flocal, file1.Path, file1.Path) + require.NoError(t, err) + fstest.CheckItems(t, r.Flocal) + file1old.Path = "backup/dst/file1" + fstest.CheckItems(t, r.Fremote, file1old, file1) +} + func TestCopyFile(t *testing.T) { r := fstest.NewRun(t) defer r.Finalise() @@ -765,6 +788,29 @@ func TestCopyFile(t *testing.T) { fstest.CheckItems(t, r.Fremote, file2) } +func TestCopyFileBackupDir(t *testing.T) { + r := fstest.NewRun(t) + defer r.Finalise() + + oldBackupDir := fs.Config.BackupDir + fs.Config.BackupDir = r.FremoteName + "/backup" + defer func() { + fs.Config.BackupDir = oldBackupDir + }() + + file1 := r.WriteFile("dst/file1", "file1 contents", t1) + fstest.CheckItems(t, r.Flocal, file1) + + file1old := r.WriteObject("dst/file1", "file1 contents old", t1) + fstest.CheckItems(t, r.Fremote, file1old) + + err := operations.CopyFile(r.Fremote, r.Flocal, file1.Path, file1.Path) + require.NoError(t, err) + fstest.CheckItems(t, r.Flocal, file1) + file1old.Path = "backup/dst/file1" + fstest.CheckItems(t, r.Fremote, file1old, file1) +} + // testFsInfo is for unit testing fs.Info type testFsInfo struct { name string