From cb2258321240117ca36aa09b250b5aecffbe1892 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 22 Mar 2016 15:23:37 +0000 Subject: [PATCH] b2: Enable mod time syncing - fixes #348 --- b2/b2.go | 2 +- docs/content/b2.md | 10 ++++------ docs/content/overview.md | 8 +++----- fs/operations.go | 5 ++++- fstest/fstests/fstests.go | 8 +++++++- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/b2/b2.go b/b2/b2.go index c3bd9d74a..e96fcf8b7 100644 --- a/b2/b2.go +++ b/b2/b2.go @@ -615,7 +615,7 @@ func (f *Fs) Rmdir() error { // Precision of the remote func (f *Fs) Precision() time.Duration { - return fs.ModTimeNotSupported + return time.Second } // deleteByID deletes a file version given Name and ID diff --git a/docs/content/b2.md b/docs/content/b2.md index dba65b17f..54629336e 100644 --- a/docs/content/b2.md +++ b/docs/content/b2.md @@ -96,9 +96,10 @@ The modified time is stored as metadata on the object as in the Backblaze standard. Other tools should be able to use this as a modified time. -Modified times are set on upload, read on download and shown in -listings. They are not used in syncing as unfortunately B2 doesn't -have an API method to set them independently of doing an upload. +Modified times are used in syncing and are fully supported except in +the case of updating a modification time on an existing object. In +this case the object will be uploaded again as B2 doesn't have an API +method to set the modification time independent of doing an upload. ### SHA1 checksums ### @@ -124,6 +125,3 @@ the old versions will be deleted. Here are [some notes I made on the backblaze API](https://gist.github.com/ncw/166dabf352b399f1cc1c) while integrating it with rclone which detail the changes I'd like to see. -With a couple of small tweaks Backblaze could enable rclone to not -make a temporary copy of files when doing cloud to cloud copies and -fully support modification times. diff --git a/docs/content/overview.md b/docs/content/overview.md index ea3b78063..270e8304a 100644 --- a/docs/content/overview.md +++ b/docs/content/overview.md @@ -25,7 +25,7 @@ Here is an overview of the major features of each cloud storage system. | Amazon Cloud Drive | MD5 | No | Yes | No | | Microsoft One Drive | SHA1 | Yes | Yes | No | | Hubic | MD5 | Yes | No | No | -| Backblaze B2 | SHA1 | Partial | No | No | +| Backblaze B2 | SHA1 | Yes | No | No | | Yandex Disk | MD5 | Yes | No | No | | The local filesystem | All | Yes | Depends | No | @@ -49,9 +49,6 @@ default, though the MD5SUM can be checked with the `--checksum` flag. All cloud storage systems support some kind of date on the object and these will be set when transferring from the cloud storage system. -Backblaze B2 preserves file modification times on files uploaded and -downloaded, but doesn't use them to decide which objects to sync. - ### Case Insensitive ### If a cloud storage systems is case sensitive then it is possible to @@ -78,4 +75,5 @@ systems. If a cloud storage system allows duplicate files then it can have two objects with the same name. -This confuses rclone greatly when syncing. +This confuses rclone greatly when syncing - use the `rclone dedupe` +command to rename or remove duplicates. diff --git a/fs/operations.go b/fs/operations.go index aaeb2b2c8..5a149eb3a 100644 --- a/fs/operations.go +++ b/fs/operations.go @@ -146,7 +146,10 @@ func Equal(src, dst Object) bool { // Size and hash the same but mtime different so update the // mtime of the dst object here err := dst.SetModTime(srcModTime) - if err != nil { + if err == ErrorCantSetModTime { + Debug(src, "src and dst identical but can't set mod time without re-uploading") + return false + } else if err != nil { Stats.Error() ErrorLog(dst, "Failed to read set modification time: %s", err) } diff --git a/fstest/fstests/fstests.go b/fstest/fstests/fstests.go index dcbd7a527..7b97a92cf 100644 --- a/fstest/fstests/fstests.go +++ b/fstest/fstests/fstests.go @@ -497,7 +497,13 @@ func TestObjectSetModTime(t *testing.T) { skipIfNotOk(t) newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z") obj := findObject(t, file1.Path) - obj.SetModTime(newModTime) + err := obj.SetModTime(newModTime) + if err == fs.ErrorCantSetModTime { + t.Log(err) + return + } else if err != nil { + t.Fatal(err) + } file1.ModTime = newModTime file1.CheckModTime(t, obj, obj.ModTime(), remote.Precision()) // And make a new object and read it from there too