84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
package dbm
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// FingerprintForGroups calculates a stable fingerprint for the provided file groups.
|
|
// It inspects the current file list managed by DBManager, collects their size and
|
|
// modification timestamp, and hashes the aggregated metadata. If none of the
|
|
// requested groups contain files, an empty string is returned without error.
|
|
func (d *DBManager) FingerprintForGroups(names ...string) (string, error) {
|
|
if len(names) == 0 {
|
|
return "", nil
|
|
}
|
|
|
|
type fileFingerprint struct {
|
|
group string
|
|
rel string
|
|
size int64
|
|
mod int64
|
|
}
|
|
|
|
entries := make([]fileFingerprint, 0)
|
|
|
|
for _, name := range names {
|
|
paths, err := d.GetDBPath(name)
|
|
if err != nil {
|
|
// When the underlying error indicates the files are simply missing,
|
|
// treat it as an empty group rather than a hard failure.
|
|
if strings.Contains(err.Error(), "db file not found") {
|
|
continue
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
for _, p := range paths {
|
|
info, statErr := os.Stat(p)
|
|
if statErr != nil {
|
|
if os.IsNotExist(statErr) {
|
|
continue
|
|
}
|
|
return "", statErr
|
|
}
|
|
|
|
rel := p
|
|
if relPath, relErr := filepath.Rel(d.path, p); relErr == nil {
|
|
rel = relPath
|
|
}
|
|
rel = filepath.ToSlash(rel)
|
|
|
|
entries = append(entries, fileFingerprint{
|
|
group: name,
|
|
rel: rel,
|
|
size: info.Size(),
|
|
mod: info.ModTime().UnixNano(),
|
|
})
|
|
}
|
|
}
|
|
|
|
if len(entries) == 0 {
|
|
return "", nil
|
|
}
|
|
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
if entries[i].group == entries[j].group {
|
|
return entries[i].rel < entries[j].rel
|
|
}
|
|
return entries[i].group < entries[j].group
|
|
})
|
|
|
|
hasher := sha256.New()
|
|
for _, e := range entries {
|
|
fmt.Fprintf(hasher, "%s|%s|%d|%d;", e.group, e.rel, e.size, e.mod)
|
|
}
|
|
|
|
return hex.EncodeToString(hasher.Sum(nil)), nil
|
|
}
|