sync: don't allow syncs on overlapping remotes - fixes #2932

This commit is contained in:
Nick Craig-Wood 2019-02-14 12:06:26 +00:00
parent c5775cf73d
commit 84c650818e
4 changed files with 28 additions and 11 deletions

View file

@ -61,7 +61,7 @@ var (
ErrorNotAFile = errors.New("is a not a regular file")
ErrorNotDeleting = errors.New("not deleting files as there were IO errors")
ErrorNotDeletingDirs = errors.New("not deleting directories as there were IO errors")
ErrorCantMoveOverlapping = errors.New("can't move files on overlapping remotes")
ErrorOverlapping = errors.New("can't sync or move files on overlapping remotes")
ErrorDirectoryNotEmpty = errors.New("directory not empty")
ErrorImmutableModified = errors.New("immutable file modified")
ErrorPermissionDenied = errors.New("permission denied")

View file

@ -532,7 +532,7 @@ func SameConfig(fdst, fsrc fs.Info) bool {
// Same returns true if fdst and fsrc point to the same underlying Fs
func Same(fdst, fsrc fs.Info) bool {
return SameConfig(fdst, fsrc) && fdst.Root() == fsrc.Root()
return SameConfig(fdst, fsrc) && strings.Trim(fdst.Root(), "/") == strings.Trim(fsrc.Root(), "/")
}
// Overlapping returns true if fdst and fsrc point to the same

View file

@ -64,6 +64,9 @@ type syncCopyMove struct {
}
func newSyncCopyMove(fdst, fsrc fs.Fs, deleteMode fs.DeleteMode, DoMove bool, deleteEmptySrcDirs bool) (*syncCopyMove, error) {
if (deleteMode != fs.DeleteModeOff || DoMove) && operations.Overlapping(fdst, fsrc) {
return nil, fserrors.FatalError(fs.ErrorOverlapping)
}
s := &syncCopyMove{
fdst: fdst,
fsrc: fsrc,
@ -920,13 +923,6 @@ func MoveDir(fdst, fsrc fs.Fs, deleteEmptySrcDirs bool) error {
}
}
// The two remotes mustn't overlap if we didn't do server side move
if operations.Overlapping(fdst, fsrc) {
err := fs.ErrorCantMoveOverlapping
fs.Errorf(fdst, "%v", err)
return err
}
// Otherwise move the files one by one
return moveDir(fdst, fsrc, deleteEmptySrcDirs)
}

View file

@ -11,6 +11,7 @@ import (
"github.com/ncw/rclone/fs"
"github.com/ncw/rclone/fs/accounting"
"github.com/ncw/rclone/fs/filter"
"github.com/ncw/rclone/fs/fserrors"
"github.com/ncw/rclone/fs/hash"
"github.com/ncw/rclone/fs/operations"
"github.com/ncw/rclone/fstest"
@ -1102,7 +1103,7 @@ func TestServerSideMoveOverlap(t *testing.T) {
// Subdir move with no filters should return ErrorCantMoveOverlapping
err = MoveDir(FremoteMove, r.Fremote, false)
assert.EqualError(t, err, fs.ErrorCantMoveOverlapping.Error())
assert.EqualError(t, err, fs.ErrorOverlapping.Error())
// Now try with a filter which should also fail with ErrorCantMoveOverlapping
filter.Active.Opt.MinSize = 40
@ -1110,7 +1111,27 @@ func TestServerSideMoveOverlap(t *testing.T) {
filter.Active.Opt.MinSize = -1
}()
err = MoveDir(FremoteMove, r.Fremote, false)
assert.EqualError(t, err, fs.ErrorCantMoveOverlapping.Error())
assert.Equal(t, err, fs.ErrorOverlapping)
}
// Test a sync with overlap
func TestSyncOverlap(t *testing.T) {
r := fstest.NewRun(t)
defer r.Finalise()
subRemoteName := r.FremoteName + "/rclone-sync-test"
FremoteSync, err := fs.NewFs(subRemoteName)
require.NoError(t, err)
checkErr := func(err error) {
assert.True(t, fserrors.IsFatalError(err))
assert.Equal(t, err.Error(), fs.ErrorOverlapping.Error())
}
checkErr(Sync(FremoteSync, r.Fremote))
checkErr(Sync(r.Fremote, FremoteSync))
checkErr(Sync(r.Fremote, r.Fremote))
checkErr(Sync(FremoteSync, FremoteSync))
}
// Test with BackupDir set