diff --git a/backend/webdav/webdav.go b/backend/webdav/webdav.go index 6aaa9d1dd..587ae0fa5 100644 --- a/backend/webdav/webdav.go +++ b/backend/webdav/webdav.go @@ -759,7 +759,7 @@ func (f *Fs) listAll(ctx context.Context, dir string, directoriesOnly bool, file } return found, fmt.Errorf("couldn't list files: %w", err) } - //fmt.Printf("result = %#v", &result) + // fmt.Printf("result = %#v", &result) baseURL, err := rest.URLJoin(f.endpoint, opts.Path) if err != nil { return false, fmt.Errorf("couldn't join URL: %w", err) @@ -1110,7 +1110,7 @@ func (f *Fs) copyOrMove(ctx context.Context, src fs.Object, remote string, metho if err != nil { return nil, fmt.Errorf("copy NewObject failed: %w", err) } - if f.useOCMtime && resp.Header.Get("X-OC-Mtime") != "accepted" && f.propsetMtime { + if f.useOCMtime && resp.Header.Get("X-OC-Mtime") != "accepted" && f.propsetMtime && !dstObj.ModTime(ctx).Equal(src.ModTime(ctx)) { fs.Debugf(dstObj, "Setting modtime after copy to %v", src.ModTime(ctx)) err = dstObj.SetModTime(ctx, src.ModTime(ctx)) if err != nil { @@ -1364,15 +1364,38 @@ var owncloudPropset = ` ` +var owncloudPropsetWithChecksum = ` + + + + %d + + %s + + + + +` + // SetModTime sets the modification time of the local fs object func (o *Object) SetModTime(ctx context.Context, modTime time.Time) error { if o.fs.propsetMtime { + checksums := "" + if o.fs.hasOCSHA1 && o.sha1 != "" { + checksums = "SHA1:" + o.sha1 + } else if o.fs.hasOCMD5 && o.md5 != "" { + checksums = "MD5:" + o.md5 + } + opts := rest.Opts{ Method: "PROPPATCH", Path: o.filePath(), NoRedirect: true, Body: strings.NewReader(fmt.Sprintf(owncloudPropset, modTime.Unix())), } + if checksums != "" { + opts.Body = strings.NewReader(fmt.Sprintf(owncloudPropsetWithChecksum, modTime.Unix(), checksums)) + } var result api.Multistatus var resp *http.Response var err error @@ -1395,6 +1418,14 @@ func (o *Object) SetModTime(ctx context.Context, modTime time.Time) error { o.modTime = modTime return nil } + // got an error, but it's possible it actually worked, so double-check + newO, err := o.fs.NewObject(ctx, o.remote) + if err != nil { + return err + } + if newO.ModTime(ctx).Equal(modTime) { + return nil + } // fallback return fs.ErrorCantSetModTime } @@ -1521,7 +1552,6 @@ func (o *Object) updateSimple(ctx context.Context, body io.Reader, getBody func( return err } return nil - } // Remove an object diff --git a/cmd/bisync/bisync_test.go b/cmd/bisync/bisync_test.go index a9c1769d6..ec57ec0fa 100644 --- a/cmd/bisync/bisync_test.go +++ b/cmd/bisync/bisync_test.go @@ -90,6 +90,7 @@ var logReplacements = []string{ `^NOTICE: .*?: Forced to upload files to set modification times on this backend.$`, dropMe, `^INFO : .*? Committing uploads - please wait...$`, dropMe, `^INFO : .*?: src and dst identical but can't set mod time without deleting and re-uploading$`, dropMe, + `^INFO : .*?: src and dst identical but can't set mod time without re-uploading$`, dropMe, // ignore crypt info messages `^INFO : .*?: Crypt detected! Using cryptcheck instead of check. \(Use --size-only or --ignore-checksum to disable\)$`, dropMe, // ignore drive info messages