mirror of
https://github.com/rclone/rclone.git
synced 2025-01-11 08:49:37 +01:00
Implement -u/--update so creation times can be used on all remotes - #226
This commit is contained in:
parent
88cca8a6eb
commit
280ac26464
@ -457,6 +457,25 @@ of timeouts or bigger if you have lots of bandwidth and a fast remote.
|
||||
|
||||
The default is to run 4 file transfers in parallel.
|
||||
|
||||
### -u, --update ###
|
||||
|
||||
This forces rclone to skip any files which exist on the destination
|
||||
and have a modified time that is newer than the source file.
|
||||
|
||||
If an existing destination file has a modification time equal (within
|
||||
the computed modify window precision) to the source file's, it will be
|
||||
updated if the sizes are different.
|
||||
|
||||
On remotes which don't support mod time directly the time checked will
|
||||
be the uploaded time. This means that if uploading to one of these
|
||||
remoes, rclone will skip any files which exist on the destination and
|
||||
have an uploaded time that is newer than the modification time of the
|
||||
source file.
|
||||
|
||||
This can be useful when transferring to a remote which doesn't support
|
||||
mod times directly as it is more accurate than a `--size-only` check
|
||||
and faster than using `--checksum`.
|
||||
|
||||
### -v, --verbose ###
|
||||
|
||||
If you set this flag, rclone will become very verbose telling you
|
||||
|
@ -81,6 +81,7 @@ var (
|
||||
deleteDuring = pflag.BoolP("delete-during", "", false, "When synchronizing, delete files during transfer (default)")
|
||||
deleteAfter = pflag.BoolP("delete-after", "", false, "When synchronizing, delete files on destination after transfering")
|
||||
lowLevelRetries = pflag.IntP("low-level-retries", "", 10, "Number of low level retries to do.")
|
||||
updateOlder = pflag.BoolP("update", "u", false, "Skip files that are newer on the destination.")
|
||||
bwLimit SizeSuffix
|
||||
|
||||
// Key to use for password en/decryption.
|
||||
@ -199,6 +200,7 @@ type ConfigInfo struct {
|
||||
DeleteDuring bool // Delete during checking/transfer
|
||||
DeleteAfter bool // Delete after successful transfer.
|
||||
LowLevelRetries int
|
||||
UpdateOlder bool // Skip files that are newer on the destination
|
||||
}
|
||||
|
||||
// Transport returns an http.RoundTripper with the correct timeouts
|
||||
@ -288,6 +290,7 @@ func LoadConfig() {
|
||||
Config.DumpBodies = *dumpBodies
|
||||
Config.InsecureSkipVerify = *skipVerify
|
||||
Config.LowLevelRetries = *lowLevelRetries
|
||||
Config.UpdateOlder = *updateOlder
|
||||
|
||||
ConfigPath = *configFile
|
||||
|
||||
|
@ -306,10 +306,38 @@ func checkOne(pair ObjectPair, out ObjectPairChan) {
|
||||
Debug(src, "Destination exists, skipping")
|
||||
return
|
||||
}
|
||||
// Check to see if changed or not
|
||||
if Equal(src, dst) {
|
||||
Debug(src, "Unchanged skipping")
|
||||
return
|
||||
// If UpdateOlder is in effect, skip if dst is newer than src
|
||||
if Config.UpdateOlder {
|
||||
srcModTime := src.ModTime()
|
||||
dstModTime := dst.ModTime()
|
||||
dt := dstModTime.Sub(srcModTime)
|
||||
// If have a mutually agreed precision then use that
|
||||
modifyWindow := Config.ModifyWindow
|
||||
if modifyWindow == ModTimeNotSupported {
|
||||
// Otherwise use 1 second as a safe default as
|
||||
// the resolution of the time a file was
|
||||
// uploaded.
|
||||
modifyWindow = time.Second
|
||||
}
|
||||
switch {
|
||||
case dt >= modifyWindow:
|
||||
Debug(src, "Destination is newer than source, skipping")
|
||||
return
|
||||
case dt <= -modifyWindow:
|
||||
Debug(src, "Destination is older than source, transferring")
|
||||
default:
|
||||
if src.Size() == dst.Size() {
|
||||
Debug(src, "Destination mod time is within %v of source and sizes identical, skipping", modifyWindow)
|
||||
return
|
||||
}
|
||||
Debug(src, "Destination mod time is within %v of source but sizes differ, transferring", modifyWindow)
|
||||
}
|
||||
} else {
|
||||
// Check to see if changed or not
|
||||
if Equal(src, dst) {
|
||||
Debug(src, "Unchanged skipping")
|
||||
return
|
||||
}
|
||||
}
|
||||
out <- pair
|
||||
}
|
||||
|
@ -692,6 +692,40 @@ func TestSyncWithExcludeAndDeleteExcluded(t *testing.T) {
|
||||
fstest.CheckItems(t, r.flocal, file2)
|
||||
}
|
||||
|
||||
// Test with UpdateOlder set
|
||||
func TestSyncWithUpdateOlder(t *testing.T) {
|
||||
r := NewRun(t)
|
||||
defer r.Finalise()
|
||||
t2plus := t2.Add(time.Second / 2)
|
||||
t2minus := t2.Add(time.Second / 2)
|
||||
oneF := r.WriteFile("one", "one", t1)
|
||||
twoF := r.WriteFile("two", "two", t3)
|
||||
threeF := r.WriteFile("three", "three", t2)
|
||||
fourF := r.WriteFile("four", "four", t2)
|
||||
fiveF := r.WriteFile("five", "five", t2)
|
||||
fstest.CheckItems(t, r.flocal, oneF, twoF, threeF, fourF, fiveF)
|
||||
oneO := r.WriteObject("one", "ONE", t2)
|
||||
twoO := r.WriteObject("two", "TWO", t2)
|
||||
threeO := r.WriteObject("three", "THREE", t2plus)
|
||||
fourO := r.WriteObject("four", "FOURFOUR", t2minus)
|
||||
fstest.CheckItems(t, r.fremote, oneO, twoO, threeO, fourO)
|
||||
|
||||
fs.Config.UpdateOlder = true
|
||||
oldModifyWindow := fs.Config.ModifyWindow
|
||||
fs.Config.ModifyWindow = fs.ModTimeNotSupported
|
||||
defer func() {
|
||||
fs.Config.UpdateOlder = false
|
||||
fs.Config.ModifyWindow = oldModifyWindow
|
||||
}()
|
||||
|
||||
fs.Stats.ResetCounters()
|
||||
err := fs.Sync(r.fremote, r.flocal)
|
||||
if err != nil {
|
||||
t.Fatalf("Sync failed: %v", err)
|
||||
}
|
||||
fstest.CheckItems(t, r.fremote, oneO, twoF, threeO, fourF, fiveF)
|
||||
}
|
||||
|
||||
// Test a server side move if possible, or the backup path if not
|
||||
func TestServerSideMove(t *testing.T) {
|
||||
r := NewRun(t)
|
||||
|
Loading…
Reference in New Issue
Block a user