mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 08:46:24 +08:00
webdav: fix SetModTime erasing checksums on owncloud and nextcloud
Before this change, calling SetModTime on owncloud and nextcloud would inadvertently erase the object's stored hashes. This change fixes the issue, which was discovered by the bisync integration tests.
This commit is contained in:
parent
75df38f6ee
commit
71069ed5c1
|
@ -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 = `<?xml version="1.0" encoding="utf-8" ?>
|
|||
</D:propertyupdate>
|
||||
`
|
||||
|
||||
var owncloudPropsetWithChecksum = `<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:propertyupdate xmlns:D="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
<lastmodified xmlns="DAV:">%d</lastmodified>
|
||||
<oc:checksums>
|
||||
<oc:checksum>%s</oc:checksum>
|
||||
</oc:checksums>
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</D:propertyupdate>
|
||||
`
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user