fs: move with --ignore-existing will not delete skipped files - #5463

This commit is contained in:
Nathan Collins 2021-07-29 12:42:55 -04:00 committed by Nick Craig-Wood
parent 3d9da896d2
commit c32d5dd1f3
5 changed files with 96 additions and 1 deletions

View file

@ -910,6 +910,10 @@ While this isn't a generally recommended option, it can be useful
in cases where your files change due to encryption. However, it cannot in cases where your files change due to encryption. However, it cannot
correct partial transfers in case a transfer was interrupted. correct partial transfers in case a transfer was interrupted.
When performing a `move`/`moveto` command, this flag will leave skipped
files in the source location unchanged when a file with the same name
exists on the destination.
### --ignore-size ### ### --ignore-size ###
Normally rclone will look at modification time and size of files to Normally rclone will look at modification time and size of files to

View file

@ -1811,7 +1811,11 @@ func moveOrCopyFile(ctx context.Context, fdst fs.Fs, fsrc fs.Fs, dstFileName str
} else { } else {
tr := accounting.Stats(ctx).NewCheckingTransfer(srcObj) tr := accounting.Stats(ctx).NewCheckingTransfer(srcObj)
if !cp { if !cp {
err = DeleteFile(ctx, srcObj) if ci.IgnoreExisting {
fs.Debugf(srcObj, "Not removing source file as destination file exists and --ignore-existing is set")
} else {
err = DeleteFile(ctx, srcObj)
}
} }
tr.Done(ctx, err) tr.Done(ctx, err)
} }

View file

@ -811,6 +811,32 @@ func TestMoveFile(t *testing.T) {
fstest.CheckItems(t, r.Fremote, file2) fstest.CheckItems(t, r.Fremote, file2)
} }
func TestMoveFileWithIgnoreExisting(t *testing.T) {
ctx := context.Background()
ctx, ci := fs.AddConfig(ctx)
r := fstest.NewRun(t)
defer r.Finalise()
file1 := r.WriteFile("file1", "file1 contents", t1)
fstest.CheckItems(t, r.Flocal, file1)
ci.IgnoreExisting = true
err := operations.MoveFile(ctx, r.Fremote, r.Flocal, file1.Path, file1.Path)
require.NoError(t, err)
fstest.CheckItems(t, r.Flocal)
fstest.CheckItems(t, r.Fremote, file1)
// Recreate file with updated content
file1b := r.WriteFile("file1", "file1 modified", t2)
fstest.CheckItems(t, r.Flocal, file1b)
// Ensure modified file did not transfer and was not deleted
err = operations.MoveFile(ctx, r.Fremote, r.Flocal, file1.Path, file1b.Path)
require.NoError(t, err)
fstest.CheckItems(t, r.Flocal, file1b)
fstest.CheckItems(t, r.Fremote, file1)
}
func TestCaseInsensitiveMoveFile(t *testing.T) { func TestCaseInsensitiveMoveFile(t *testing.T) {
ctx := context.Background() ctx := context.Background()
r := fstest.NewRun(t) r := fstest.NewRun(t)

View file

@ -354,6 +354,8 @@ func (s *syncCopyMove) pairChecker(in *pipe, out *pipe, fraction int, wg *sync.W
// Delete src if no error on copy // Delete src if no error on copy
if operations.SameObject(src, pair.Dst) { if operations.SameObject(src, pair.Dst) {
fs.Logf(src, "Not removing source file as it is the same file as the destination") fs.Logf(src, "Not removing source file as it is the same file as the destination")
} else if s.ci.IgnoreExisting {
fs.Debugf(src, "Not removing source file as destination file exists and --ignore-existing is set")
} else { } else {
s.processError(operations.DeleteFile(s.ctx, src)) s.processError(operations.DeleteFile(s.ctx, src))
} }

View file

@ -1342,6 +1342,65 @@ func TestMoveWithoutDeleteEmptySrcDirs(t *testing.T) {
fstest.CheckItems(t, r.Fremote, file1, file2) fstest.CheckItems(t, r.Fremote, file1, file2)
} }
func TestMoveWithIgnoreExisting(t *testing.T) {
ctx := context.Background()
ctx, ci := fs.AddConfig(ctx)
r := fstest.NewRun(t)
defer r.Finalise()
file1 := r.WriteFile("existing", "potato", t1)
file2 := r.WriteFile("existing-b", "tomato", t1)
ci.IgnoreExisting = true
accounting.GlobalStats().ResetCounters()
err := MoveDir(ctx, r.Fremote, r.Flocal, false, false)
require.NoError(t, err)
fstest.CheckListingWithPrecision(
t,
r.Flocal,
[]fstest.Item{},
[]string{},
fs.GetModifyWindow(ctx, r.Flocal),
)
fstest.CheckListingWithPrecision(
t,
r.Fremote,
[]fstest.Item{
file1,
file2,
},
[]string{},
fs.GetModifyWindow(ctx, r.Fremote),
)
// Recreate first file with modified content
file1b := r.WriteFile("existing", "newpotatoes", t2)
accounting.GlobalStats().ResetCounters()
err = MoveDir(ctx, r.Fremote, r.Flocal, false, false)
require.NoError(t, err)
// Source items should still exist in modified state
fstest.CheckListingWithPrecision(
t,
r.Flocal,
[]fstest.Item{
file1b,
},
[]string{},
fs.GetModifyWindow(ctx, r.Flocal),
)
// Dest items should not have changed
fstest.CheckListingWithPrecision(
t,
r.Fremote,
[]fstest.Item{
file1,
file2,
},
[]string{},
fs.GetModifyWindow(ctx, r.Fremote),
)
}
// Test a server-side move if possible, or the backup path if not // Test a server-side move if possible, or the backup path if not
func TestServerSideMove(t *testing.T) { func TestServerSideMove(t *testing.T) {
ctx := context.Background() ctx := context.Background()