mirror of
https://github.com/rclone/rclone.git
synced 2025-01-31 18:11:44 +08:00
sync: implement --ignore-errors - fixes #642
This commit is contained in:
parent
b52e34ef5e
commit
91b068ad3a
|
@ -33,6 +33,7 @@ type ConfigInfo struct {
|
||||||
SizeOnly bool
|
SizeOnly bool
|
||||||
IgnoreTimes bool
|
IgnoreTimes bool
|
||||||
IgnoreExisting bool
|
IgnoreExisting bool
|
||||||
|
IgnoreErrors bool
|
||||||
ModifyWindow time.Duration
|
ModifyWindow time.Duration
|
||||||
Checkers int
|
Checkers int
|
||||||
Transfers int
|
Transfers int
|
||||||
|
|
|
@ -43,6 +43,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
|
||||||
flags.BoolVarP(flagSet, &fs.Config.SizeOnly, "size-only", "", fs.Config.SizeOnly, "Skip based on size only, not mod-time or checksum")
|
flags.BoolVarP(flagSet, &fs.Config.SizeOnly, "size-only", "", fs.Config.SizeOnly, "Skip based on size only, not mod-time or checksum")
|
||||||
flags.BoolVarP(flagSet, &fs.Config.IgnoreTimes, "ignore-times", "I", fs.Config.IgnoreTimes, "Don't skip files that match size and time - transfer all files")
|
flags.BoolVarP(flagSet, &fs.Config.IgnoreTimes, "ignore-times", "I", fs.Config.IgnoreTimes, "Don't skip files that match size and time - transfer all files")
|
||||||
flags.BoolVarP(flagSet, &fs.Config.IgnoreExisting, "ignore-existing", "", fs.Config.IgnoreExisting, "Skip all files that exist on destination")
|
flags.BoolVarP(flagSet, &fs.Config.IgnoreExisting, "ignore-existing", "", fs.Config.IgnoreExisting, "Skip all files that exist on destination")
|
||||||
|
flags.BoolVarP(flagSet, &fs.Config.IgnoreErrors, "ignore-errors", "", fs.Config.IgnoreErrors, "delete even if there are I/O errors")
|
||||||
flags.BoolVarP(flagSet, &fs.Config.DryRun, "dry-run", "n", fs.Config.DryRun, "Do a trial run with no permanent changes")
|
flags.BoolVarP(flagSet, &fs.Config.DryRun, "dry-run", "n", fs.Config.DryRun, "Do a trial run with no permanent changes")
|
||||||
flags.DurationVarP(flagSet, &fs.Config.ConnectTimeout, "contimeout", "", fs.Config.ConnectTimeout, "Connect timeout")
|
flags.DurationVarP(flagSet, &fs.Config.ConnectTimeout, "contimeout", "", fs.Config.ConnectTimeout, "Connect timeout")
|
||||||
flags.DurationVarP(flagSet, &fs.Config.Timeout, "timeout", "", fs.Config.Timeout, "IO idle timeout")
|
flags.DurationVarP(flagSet, &fs.Config.Timeout, "timeout", "", fs.Config.Timeout, "IO idle timeout")
|
||||||
|
|
|
@ -399,7 +399,7 @@ func (s *syncCopyMove) stopDeleters() {
|
||||||
// checkSrcMap is clear then it assumes that the any source files that
|
// checkSrcMap is clear then it assumes that the any source files that
|
||||||
// have been found have been removed from dstFiles already.
|
// have been found have been removed from dstFiles already.
|
||||||
func (s *syncCopyMove) deleteFiles(checkSrcMap bool) error {
|
func (s *syncCopyMove) deleteFiles(checkSrcMap bool) error {
|
||||||
if accounting.Stats.Errored() {
|
if accounting.Stats.Errored() && !fs.Config.IgnoreErrors {
|
||||||
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeleting)
|
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeleting)
|
||||||
return fs.ErrorNotDeleting
|
return fs.ErrorNotDeleting
|
||||||
}
|
}
|
||||||
|
@ -430,7 +430,7 @@ func deleteEmptyDirectories(f fs.Fs, entries fs.DirEntries) error {
|
||||||
if len(entries) == 0 {
|
if len(entries) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if accounting.Stats.Errored() {
|
if accounting.Stats.Errored() && !fs.Config.IgnoreErrors {
|
||||||
fs.Errorf(f, "%v", fs.ErrorNotDeletingDirs)
|
fs.Errorf(f, "%v", fs.ErrorNotDeletingDirs)
|
||||||
return fs.ErrorNotDeletingDirs
|
return fs.ErrorNotDeletingDirs
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ func (s *syncCopyMove) run() error {
|
||||||
|
|
||||||
// Delete files after
|
// Delete files after
|
||||||
if s.deleteMode == fs.DeleteModeAfter {
|
if s.deleteMode == fs.DeleteModeAfter {
|
||||||
if s.currentError() != nil {
|
if s.currentError() != nil && !fs.Config.IgnoreErrors {
|
||||||
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeleting)
|
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeleting)
|
||||||
} else {
|
} else {
|
||||||
s.processError(s.deleteFiles(false))
|
s.processError(s.deleteFiles(false))
|
||||||
|
@ -633,7 +633,7 @@ func (s *syncCopyMove) run() error {
|
||||||
|
|
||||||
// Prune empty directories
|
// Prune empty directories
|
||||||
if s.deleteMode != fs.DeleteModeOff {
|
if s.deleteMode != fs.DeleteModeOff {
|
||||||
if s.currentError() != nil {
|
if s.currentError() != nil && !fs.Config.IgnoreErrors {
|
||||||
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeletingDirs)
|
fs.Errorf(s.fdst, "%v", fs.ErrorNotDeletingDirs)
|
||||||
} else {
|
} else {
|
||||||
s.processError(deleteEmptyDirectories(s.fdst, s.dstEmptyDirs))
|
s.processError(deleteEmptyDirectories(s.fdst, s.dstEmptyDirs))
|
||||||
|
|
|
@ -283,6 +283,78 @@ func TestSyncIgnoreExisting(t *testing.T) {
|
||||||
fstest.CheckItems(t, r.Fremote, file1)
|
fstest.CheckItems(t, r.Fremote, file1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSyncIgnoreErrors(t *testing.T) {
|
||||||
|
r := fstest.NewRun(t)
|
||||||
|
fs.Config.IgnoreErrors = true
|
||||||
|
defer func() {
|
||||||
|
fs.Config.IgnoreErrors = false
|
||||||
|
r.Finalise()
|
||||||
|
}()
|
||||||
|
file1 := r.WriteFile("a/potato2", "------------------------------------------------------------", t1)
|
||||||
|
file2 := r.WriteObject("b/potato", "SMALLER BUT SAME DATE", t2)
|
||||||
|
file3 := r.WriteBoth("c/non empty space", "AhHa!", t2)
|
||||||
|
require.NoError(t, operations.Mkdir(r.Fremote, "d"))
|
||||||
|
|
||||||
|
fstest.CheckListingWithPrecision(
|
||||||
|
t,
|
||||||
|
r.Flocal,
|
||||||
|
[]fstest.Item{
|
||||||
|
file1,
|
||||||
|
file3,
|
||||||
|
},
|
||||||
|
[]string{
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
},
|
||||||
|
fs.Config.ModifyWindow,
|
||||||
|
)
|
||||||
|
fstest.CheckListingWithPrecision(
|
||||||
|
t,
|
||||||
|
r.Fremote,
|
||||||
|
[]fstest.Item{
|
||||||
|
file2,
|
||||||
|
file3,
|
||||||
|
},
|
||||||
|
[]string{
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"d",
|
||||||
|
},
|
||||||
|
fs.Config.ModifyWindow,
|
||||||
|
)
|
||||||
|
|
||||||
|
accounting.Stats.ResetCounters()
|
||||||
|
fs.CountError(nil)
|
||||||
|
assert.NoError(t, Sync(r.Fremote, r.Flocal))
|
||||||
|
|
||||||
|
fstest.CheckListingWithPrecision(
|
||||||
|
t,
|
||||||
|
r.Flocal,
|
||||||
|
[]fstest.Item{
|
||||||
|
file1,
|
||||||
|
file3,
|
||||||
|
},
|
||||||
|
[]string{
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
},
|
||||||
|
fs.Config.ModifyWindow,
|
||||||
|
)
|
||||||
|
fstest.CheckListingWithPrecision(
|
||||||
|
t,
|
||||||
|
r.Fremote,
|
||||||
|
[]fstest.Item{
|
||||||
|
file1,
|
||||||
|
file3,
|
||||||
|
},
|
||||||
|
[]string{
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
},
|
||||||
|
fs.Config.ModifyWindow,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSyncAfterChangingModtimeOnly(t *testing.T) {
|
func TestSyncAfterChangingModtimeOnly(t *testing.T) {
|
||||||
r := fstest.NewRun(t)
|
r := fstest.NewRun(t)
|
||||||
defer r.Finalise()
|
defer r.Finalise()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user