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.
This commit is contained in:
Michilis
2026-08-05 05:41:12 +00:00
parent dafa3711f8
commit 498d7d8a7d
31 changed files with 2216 additions and 64 deletions
+21
View File
@@ -17,6 +17,12 @@ type local struct {
root string
}
// NewLocal builds the local-disk backend explicitly, whichever backend is
// active — `photo-api sync` needs both sides at once.
func NewLocal(root string) (Storage, error) {
return newLocal(root)
}
func newLocal(root string) (*local, error) {
if err := os.MkdirAll(root, 0o755); err != nil {
return nil, fmt.Errorf("create storage dir %s: %w", root, err)
@@ -74,6 +80,21 @@ func (l *local) Open(_ context.Context, key string) (io.ReadCloser, int64, error
return f, info.Size(), nil
}
func (l *local) Stat(_ context.Context, key string) (int64, error) {
p, err := l.path(key)
if err != nil {
return 0, err
}
info, err := os.Stat(p)
if os.IsNotExist(err) {
return 0, ErrNotExist
}
if err != nil {
return 0, err
}
return info.Size(), nil
}
func (l *local) Delete(_ context.Context, key string) error {
p, err := l.path(key)
if err != nil {