From 68333d34a1f4ffdf238b75e272a699b39c737c58 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 13 Jun 2017 13:58:39 +0100 Subject: [PATCH] dropbox: make setting mod time on existing files work properly This is a fix left over from the v2 conversion. Dropbox ignores the client modification on an incoming file if it was identical to the existing file. This change deletes the existing file first before re-uploading the new one. --- cmd/mountlib/file.go | 2 +- dropbox/dropbox.go | 6 +++--- fs/fs.go | 33 +++++++++++++++++---------------- fs/operations.go | 9 ++++++++- fstest/fstests/fstests.go | 2 +- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/cmd/mountlib/file.go b/cmd/mountlib/file.go index 9a91c9e9b..9881e4d77 100644 --- a/cmd/mountlib/file.go +++ b/cmd/mountlib/file.go @@ -125,7 +125,7 @@ func (f *File) applyPendingModTime() error { switch err { case nil: fs.Debugf(f.o, "File.applyPendingModTime OK") - case fs.ErrorCantSetModTime: + case fs.ErrorCantSetModTime, fs.ErrorCantSetModTimeWithoutDelete: // do nothing, in order to not break "touch somefile" if it exists already default: fs.Errorf(f.o, "File.applyPendingModTime error: %v", err) diff --git a/dropbox/dropbox.go b/dropbox/dropbox.go index ba885c5a7..157cf28ca 100644 --- a/dropbox/dropbox.go +++ b/dropbox/dropbox.go @@ -810,9 +810,9 @@ func (o *Object) ModTime() time.Time { // Commits the datastore func (o *Object) SetModTime(modTime time.Time) error { // Dropbox doesn't have a way of doing this so returning this - // error will cause the file to be re-uploaded to set the - // time. - return fs.ErrorCantSetModTime + // error will cause the file to be deleted first then + // re-uploaded to set the time. + return fs.ErrorCantSetModTimeWithoutDelete } // Storable returns whether this object is storable diff --git a/fs/fs.go b/fs/fs.go index c55309a5e..bf44d1a22 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -29,22 +29,23 @@ var ( // Filesystem registry fsRegistry []*RegInfo // ErrorNotFoundInConfigFile is returned by NewFs if not found in config file - ErrorNotFoundInConfigFile = errors.New("didn't find section in config file") - ErrorCantPurge = errors.New("can't purge directory") - ErrorCantCopy = errors.New("can't copy object - incompatible remotes") - ErrorCantMove = errors.New("can't move object - incompatible remotes") - ErrorCantDirMove = errors.New("can't move directory - incompatible remotes") - ErrorDirExists = errors.New("can't copy directory - destination already exists") - ErrorCantSetModTime = errors.New("can't set modified time") - ErrorDirNotFound = errors.New("directory not found") - ErrorObjectNotFound = errors.New("object not found") - ErrorLevelNotSupported = errors.New("level value not supported") - ErrorListAborted = errors.New("list aborted") - ErrorListOnlyRoot = errors.New("can only list from root") - ErrorIsFile = errors.New("is a file not a directory") - ErrorNotAFile = errors.New("is a not a regular file") - ErrorNotDeleting = errors.New("not deleting files as there were IO errors") - ErrorCantMoveOverlapping = errors.New("can't move files on overlapping remotes") + ErrorNotFoundInConfigFile = errors.New("didn't find section in config file") + ErrorCantPurge = errors.New("can't purge directory") + ErrorCantCopy = errors.New("can't copy object - incompatible remotes") + ErrorCantMove = errors.New("can't move object - incompatible remotes") + ErrorCantDirMove = errors.New("can't move directory - incompatible remotes") + ErrorDirExists = errors.New("can't copy directory - destination already exists") + ErrorCantSetModTime = errors.New("can't set modified time") + ErrorCantSetModTimeWithoutDelete = errors.New("can't set modified time without deleting existing object") + ErrorDirNotFound = errors.New("directory not found") + ErrorObjectNotFound = errors.New("object not found") + ErrorLevelNotSupported = errors.New("level value not supported") + ErrorListAborted = errors.New("list aborted") + ErrorListOnlyRoot = errors.New("can only list from root") + ErrorIsFile = errors.New("is a file not a directory") + ErrorNotAFile = errors.New("is a not a regular file") + ErrorNotDeleting = errors.New("not deleting files as there were IO errors") + ErrorCantMoveOverlapping = errors.New("can't move files on overlapping remotes") ) // RegInfo provides information about a filesystem diff --git a/fs/operations.go b/fs/operations.go index 91db8c0b4..c846bc11f 100644 --- a/fs/operations.go +++ b/fs/operations.go @@ -183,7 +183,14 @@ func equal(src, dst Object, sizeOnly, checkSum bool) bool { // mtime of the dst object here err := dst.SetModTime(srcModTime) if err == ErrorCantSetModTime { - Debugf(src, "src and dst identical but can't set mod time without re-uploading") + Debugf(dst, "src and dst identical but can't set mod time without re-uploading") + return false + } else if err == ErrorCantSetModTimeWithoutDelete { + Debugf(dst, "src and dst identical but can't set mod time without deleting and re-uploading") + err = dst.Remove() + if err != nil { + Errorf(dst, "failed to delete before re-upload: %v", err) + } return false } else if err != nil { Stats.Error() diff --git a/fstest/fstests/fstests.go b/fstest/fstests/fstests.go index fef3c55f6..4b819651a 100644 --- a/fstest/fstests/fstests.go +++ b/fstest/fstests/fstests.go @@ -672,7 +672,7 @@ func TestObjectSetModTime(t *testing.T) { newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z") obj := findObject(t, file1.Path) err := obj.SetModTime(newModTime) - if err == fs.ErrorCantSetModTime { + if err == fs.ErrorCantSetModTime || err == fs.ErrorCantSetModTimeWithoutDelete { t.Log(err) return }