github.com/artpar/rclone@v1.67.3/fs/fingerprint.go (about)

     1  package fs
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/artpar/rclone/fs/hash"
     9  )
    10  
    11  // Fingerprint produces a unique-ish string for an object.
    12  //
    13  // This is for detecting whether an object has changed since we last
    14  // saw it, not for checking object identity between two different
    15  // remotes - operations.Equal should be used for that.
    16  //
    17  // If fast is set then Fingerprint will only include attributes where
    18  // usually another operation is not required to fetch them. For
    19  // example if fast is set then this won't include hashes on the local
    20  // backend.
    21  func Fingerprint(ctx context.Context, o ObjectInfo, fast bool) string {
    22  	var (
    23  		out      strings.Builder
    24  		f        = o.Fs()
    25  		features = f.Features()
    26  	)
    27  	fmt.Fprintf(&out, "%d", o.Size())
    28  	// Whether we want to do a slow operation or not
    29  	//
    30  	//  fast     true  false true  false
    31  	//  opIsSlow true  true  false false
    32  	//  do Op    false true  true  true
    33  	//
    34  	// If !fast (slow) do the operation or if !OpIsSlow ==
    35  	// OpIsFast do the operation.
    36  	//
    37  	// Eg don't do this for S3 where modtimes are expensive
    38  	if !fast || !features.SlowModTime {
    39  		if f.Precision() != ModTimeNotSupported {
    40  			fmt.Fprintf(&out, ",%v", o.ModTime(ctx).UTC())
    41  		}
    42  	}
    43  	// Eg don't do this for SFTP/local where hashes are expensive?
    44  	if !fast || !features.SlowHash {
    45  		hashType := f.Hashes().GetOne()
    46  		if hashType != hash.None {
    47  			hash, err := o.Hash(ctx, hashType)
    48  			if err == nil {
    49  				fmt.Fprintf(&out, ",%v", hash)
    50  			}
    51  		}
    52  	}
    53  	return out.String()
    54  }