diff --git a/backend/s3/s3.go b/backend/s3/s3.go index 52fa696a3..17fee08c4 100644 --- a/backend/s3/s3.go +++ b/backend/s3/s3.go @@ -945,6 +945,9 @@ func (o *Object) readMetaData() (err error) { // It attempts to read the objects mtime and if that isn't present the // LastModified returned in the http headers func (o *Object) ModTime() time.Time { + if fs.Config.UseServerModTime { + return o.lastModified + } err := o.readMetaData() if err != nil { fs.Logf(o, "Failed to read metadata: %v", err) diff --git a/backend/swift/swift.go b/backend/swift/swift.go index c33d4c5e5..5a5763438 100644 --- a/backend/swift/swift.go +++ b/backend/swift/swift.go @@ -719,6 +719,9 @@ func (o *Object) readMetaData() (err error) { // It attempts to read the objects mtime and if that isn't present the // LastModified returned in the http headers func (o *Object) ModTime() time.Time { + if fs.Config.UseServerModTime { + return o.info.LastModified + } err := o.readMetaData() if err != nil { fs.Debugf(o, "Failed to read metadata: %s", err) diff --git a/docs/content/docs.md b/docs/content/docs.md index 45a8634d8..1f86f798e 100644 --- a/docs/content/docs.md +++ b/docs/content/docs.md @@ -799,6 +799,19 @@ 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`. +### --use-server-modtime ### + +Some object-store backends (e.g, Swift, S3) do not preserve file modification +times (modtime). On these backends, rclone stores the original modtime as +additional metadata on the object. By default it will make an API call to +retrieve the metadata when the modtime is needed by an operation. + +Use this flag to disable the extra API call and rely instead on the server's +modified time. In cases such as a local to remote sync, knowing the local file +is newer than the time it was last uploaded to the remote is sufficient. In +those cases, this flag can speed up the process and reduce the number of API +calls necessary. + ### -v, -vv, --verbose ### With `-v` rclone will tell you about each file that is transferred and diff --git a/docs/content/s3.md b/docs/content/s3.md index 7e1dcf0d1..aae8d584f 100644 --- a/docs/content/s3.md +++ b/docs/content/s3.md @@ -213,6 +213,19 @@ This remote supports `--fast-list` which allows you to use fewer transactions in exchange for more memory. See the [rclone docs](/docs/#fast-list) for more details. +### --update and --use-server-modtime ### + +As noted below, the modified time is stored on metadata on the object. It is +used by default for all operations that require checking the time a file was +last updated. It allows rclone to treat the remote more like a true filesystem, +but it is inefficient because it requires an extra API call to retrieve the +metadata. + +For many operations, the time the object was last uploaded to the remote is +sufficient to determine if it is "dirty". By using `--update` along with +`--use-server-modtime`, you can avoid the extra API call and simply upload +files whose local modtime is newer than the time it was last uploaded. + ### Modified time ### The modified time is stored as metadata on the object as diff --git a/docs/content/swift.md b/docs/content/swift.md index 8d430536d..32cfbb7d3 100644 --- a/docs/content/swift.md +++ b/docs/content/swift.md @@ -248,6 +248,19 @@ This remote supports `--fast-list` which allows you to use fewer transactions in exchange for more memory. See the [rclone docs](/docs/#fast-list) for more details. +### --update and --use-server-modtime ### + +As noted below, the modified time is stored on metadata on the object. It is +used by default for all operations that require checking the time a file was +last updated. It allows rclone to treat the remote more like a true filesystem, +but it is inefficient because it requires an extra API call to retrieve the +metadata. + +For many operations, the time the object was last uploaded to the remote is +sufficient to determine if it is "dirty". By using `--update` along with +`--use-server-modtime`, you can avoid the extra API call and simply upload +files whose local modtime is newer than the time it was last uploaded. + ### Specific options ### Here are the command line options specific to this cloud storage diff --git a/fs/config.go b/fs/config.go index 3617e98cd..4c7b57ddf 100644 --- a/fs/config.go +++ b/fs/config.go @@ -67,6 +67,7 @@ type ConfigInfo struct { StreamingUploadCutoff SizeSuffix StatsFileNameLength int AskPassword bool + UseServerModTime bool } // NewConfig creates a new config with everything set to the default diff --git a/fs/config/configflags/configflags.go b/fs/config/configflags/configflags.go index 623b9c98b..9d22dea85 100644 --- a/fs/config/configflags/configflags.go +++ b/fs/config/configflags/configflags.go @@ -58,6 +58,7 @@ func AddFlags(flagSet *pflag.FlagSet) { flags.BoolVarP(flagSet, &fs.Config.TrackRenames, "track-renames", "", fs.Config.TrackRenames, "When synchronizing, track file renames and do a server side move if possible") flags.IntVarP(flagSet, &fs.Config.LowLevelRetries, "low-level-retries", "", fs.Config.LowLevelRetries, "Number of low level retries to do.") flags.BoolVarP(flagSet, &fs.Config.UpdateOlder, "update", "u", fs.Config.UpdateOlder, "Skip files that are newer on the destination.") + flags.BoolVarP(flagSet, &fs.Config.UseServerModTime, "use-server-modtime", "", fs.Config.UseServerModTime, "Use server modified time instead of object metadata") flags.BoolVarP(flagSet, &fs.Config.NoGzip, "no-gzip-encoding", "", fs.Config.NoGzip, "Don't set Accept-Encoding: gzip.") flags.IntVarP(flagSet, &fs.Config.MaxDepth, "max-depth", "", fs.Config.MaxDepth, "If set limits the recursion depth to this.") flags.BoolVarP(flagSet, &fs.Config.IgnoreSize, "ignore-size", "", false, "Ignore size when skipping use mod-time or checksum.")