mirror of
https://github.com/rclone/rclone.git
synced 2026-01-04 17:43:50 +00:00
Add support for multiple hash types.
Add support for multiple hash types with negotiation of common hash types for comparison. Manually rebased version of #277 (see discussion there)
This commit is contained in:
67
b2/b2.go
67
b2/b2.go
@@ -74,6 +74,7 @@ type Object struct {
|
||||
remote string // The remote path
|
||||
info api.File // Info from the b2 object if known
|
||||
modTime time.Time // The modified time of the object if known
|
||||
sha1 string // SHA-1 hash if known
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
@@ -580,6 +581,11 @@ func (f *Fs) Purge() error {
|
||||
return errReturn
|
||||
}
|
||||
|
||||
// Hashes returns the supported hash sets.
|
||||
func (f *Fs) Hashes() fs.HashSet {
|
||||
return fs.HashSet(fs.HashSHA1)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Fs returns the parent Fs
|
||||
@@ -600,9 +606,16 @@ func (o *Object) Remote() string {
|
||||
return o.remote
|
||||
}
|
||||
|
||||
// Md5sum returns the Md5sum of an object returning a lowercase hex string
|
||||
func (o *Object) Md5sum() (string, error) {
|
||||
return "", nil
|
||||
// Hash returns the Sha-1 of an object returning a lowercase hex string
|
||||
// Hash returns the Md5sum of an object returning a lowercase hex string
|
||||
func (o *Object) Hash(t fs.HashType) (string, error) {
|
||||
if t != fs.HashSHA1 {
|
||||
return "", fs.ErrHashUnsupported
|
||||
}
|
||||
|
||||
// Error is logged in readFileMetadata
|
||||
_ = o.readFileMetadata()
|
||||
return o.sha1, nil
|
||||
}
|
||||
|
||||
// Size returns the size of an object in bytes
|
||||
@@ -652,23 +665,40 @@ func parseTimeString(timeString string) (result time.Time, err error) {
|
||||
//
|
||||
// It attempts to read the objects mtime and if that isn't present the
|
||||
// LastModified returned in the http headers
|
||||
//
|
||||
// SHA-1 will also be updated once the request has completed.
|
||||
func (o *Object) ModTime() (result time.Time) {
|
||||
if !o.modTime.IsZero() {
|
||||
return o.modTime
|
||||
// The error is logged in readFileMetadata
|
||||
_ = o.readFileMetadata()
|
||||
return o.modTime
|
||||
}
|
||||
|
||||
// readFileMetadata attempts to read the modified time and
|
||||
// SHA-1 hash of the remote object.
|
||||
//
|
||||
// If the objects mtime and if that isn't present the
|
||||
// LastModified returned in the http headers.
|
||||
//
|
||||
// It is safe to call this function multiple times, and the
|
||||
// result is cached between calls.
|
||||
func (o *Object) readFileMetadata() error {
|
||||
// Return if already know it
|
||||
if !o.modTime.IsZero() && o.sha1 != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return the current time if can't read metadata
|
||||
result = time.Now()
|
||||
// Set modtime to now, as default value.
|
||||
o.modTime = time.Now()
|
||||
|
||||
// Read metadata (need ID)
|
||||
// Read metadata (we need the ID)
|
||||
err := o.readMetaData()
|
||||
if err != nil {
|
||||
fs.Debug(o, "Failed to read metadata: %v", err)
|
||||
return result
|
||||
fs.Debug(o, "Failed to get file metadata: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Return the UploadTimestamp if can't get file info
|
||||
result = time.Time(o.info.UploadTimestamp)
|
||||
// Use the UploadTimestamp if can't get file info
|
||||
o.modTime = time.Time(o.info.UploadTimestamp)
|
||||
|
||||
// Now read the metadata for the modified time
|
||||
opts := rest.Opts{
|
||||
@@ -682,17 +712,20 @@ func (o *Object) ModTime() (result time.Time) {
|
||||
_, err = o.fs.srv.CallJSON(&opts, &request, &response)
|
||||
if err != nil {
|
||||
fs.Debug(o, "Failed to get file info: %v", err)
|
||||
return result
|
||||
return err
|
||||
}
|
||||
o.sha1 = response.SHA1
|
||||
|
||||
// Parse the result
|
||||
timeString := response.Info[timeKey]
|
||||
parsed, err := parseTimeString(timeString)
|
||||
if err != nil {
|
||||
fs.Debug(o, "Failed to parse mod time string %q: %v", timeString, err)
|
||||
return result
|
||||
return err
|
||||
}
|
||||
return parsed
|
||||
o.modTime = parsed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetModTime sets the modification time of the local fs object
|
||||
@@ -785,6 +818,9 @@ func (o *Object) Open() (in io.ReadCloser, err error) {
|
||||
} else {
|
||||
o.modTime = parsed
|
||||
}
|
||||
if o.sha1 == "" {
|
||||
o.sha1 = resp.Header.Get(sha1Header)
|
||||
}
|
||||
return newOpenFile(o, resp), nil
|
||||
}
|
||||
|
||||
@@ -939,6 +975,7 @@ func (o *Object) Update(in io.Reader, modTime time.Time, size int64) (err error)
|
||||
o.info.Action = "upload"
|
||||
o.info.Size = response.Size
|
||||
o.info.UploadTimestamp = api.Timestamp(time.Now()) // FIXME not quite right
|
||||
o.sha1 = response.SHA1
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user