Files
Michilis 498d7d8a7d Add photo content-hash dedup and local↔S3 library sync.
Uploads skip per-gallery duplicates, checksums can be backfilled, and STORAGE_BACKEND plus sync tooling make switching storage backends safe.
2026-08-05 05:41:12 +00:00

32 lines
1022 B
Go

// Package checksum defines the content hash used to spot duplicate photos and
// the backfill that fills it in for photos uploaded before it existed.
//
// The hash is sha256 over the untouched original bytes, hex encoded, stored in
// photos_photos.checksum. Duplicate scope is one gallery — the unique index is
// on (gallery_id, checksum) — so the same image may still live in several
// galleries, each with its own row and its own stored object.
package checksum
import (
"crypto/sha256"
"encoding/hex"
"hash"
"io"
)
// New returns a fresh hasher. Upload hashes as it spools the body, so it needs
// the writer rather than a finished reader.
func New() hash.Hash { return sha256.New() }
// Format renders a hasher's digest the way it is stored.
func Format(h hash.Hash) string { return hex.EncodeToString(h.Sum(nil)) }
// Sum reads r to EOF and returns its digest.
func Sum(r io.Reader) (string, error) {
h := New()
if _, err := io.Copy(h, r); err != nil {
return "", err
}
return Format(h), nil
}