hasher: look for cached hash if passed hash unexpectedly blank

Before this change, Hasher did not check whether a "passed hash" (hashtype
natively supported by the wrapped backend) returned from a backend was blank,
and would sometimes return a blank hash to the caller even when a non-blank hash
was already stored in the db. This caused issues with, for example, Google
Drive, which has SHA1 / SHA256 hashes for some files but not others
(https://rclone.org/drive/#sha1-or-sha256-hashes-may-be-missing) and sometimes also
does not have hashes for very recently modified files.

After this change, Hasher will check if the received "passed hash" is
unexpectedly blank, and if so, it will continue to try other enabled methods,
such as retrieving a value from the database, or possibly regenerating it.

https://forum.rclone.org/t/hasher-with-gdrive-backend-does-not-return-sha1-sha256-for-old-files/44680/9?u=nielash
This commit is contained in:
nielash 2024-02-20 18:09:56 -05:00 committed by Nick Craig-Wood
parent ff0acfb568
commit 9b650d3517

View File

@ -71,7 +71,14 @@ func (o *Object) Hash(ctx context.Context, hashType hash.Type) (hashVal string,
f := o.f f := o.f
if f.passHashes.Contains(hashType) { if f.passHashes.Contains(hashType) {
fs.Debugf(o, "pass %s", hashType) fs.Debugf(o, "pass %s", hashType)
return o.Object.Hash(ctx, hashType) hashVal, err = o.Object.Hash(ctx, hashType)
if hashVal != "" {
return hashVal, err
}
if err != nil {
fs.Debugf(o, "error passing %s: %v", hashType, err)
}
fs.Debugf(o, "passed %s is blank -- trying other methods", hashType)
} }
if !f.suppHashes.Contains(hashType) { if !f.suppHashes.Contains(hashType) {
fs.Debugf(o, "unsupp %s", hashType) fs.Debugf(o, "unsupp %s", hashType)