vfs: fix modtimes changing by fractional seconds after upload #4763

Before this change, rclone would return the modification times of the
cache file or the pending modtime which would be more accurate than
the modtime that the backend was capable of.

This meant that the modtime would be change slightly when the item was
actually uploaded.

For example modification times on Google Drive would be rounded to the
nearest millisecond.

This fixes the VFS layer to always return modtimes directly from an
object stored on the remote, or rounded to the precision that the
remote is capable of.
This commit is contained in:
Nick Craig-Wood 2021-03-12 16:52:58 +00:00
parent aea8776a43
commit 8b491f7f3d

View File

@ -289,6 +289,15 @@ func (f *File) activeWriters() int {
return int(atomic.LoadInt32(&f.nwriters)) return int(atomic.LoadInt32(&f.nwriters))
} }
// _roundModTime rounds the time passed in to the Precision of the
// underlying Fs
//
// It should be called with the lock held
func (f *File) _roundModTime(modTime time.Time) time.Time {
precision := f.d.f.Precision()
return modTime.Truncate(precision)
}
// ModTime returns the modified time of the file // ModTime returns the modified time of the file
// //
// if NoModTime is set then it returns the mod time of the directory // if NoModTime is set then it returns the mod time of the directory
@ -307,12 +316,12 @@ func (f *File) ModTime() (modTime time.Time) {
if err != nil { if err != nil {
fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err) fs.Errorf(f._path(), "ModTime: Item GetModTime failed: %v", err)
} else { } else {
return modTime return f._roundModTime(modTime)
} }
} }
} }
if !pendingModTime.IsZero() { if !pendingModTime.IsZero() {
return pendingModTime return f._roundModTime(pendingModTime)
} }
if o == nil { if o == nil {
return time.Now() return time.Now()