Add verify command to check blob store integrity.
Verify iterates manifest file entries, confirms each blob exists in the store, and re-hashes the content to detect corruption. Includes unit tests for the ok, hash-mismatch, and blob-missing cases, plus a thin CLI wrapper that exits non-zero on any failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
61
garden/verify.go
Normal file
61
garden/verify.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package garden
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// VerifyResult reports the integrity of a single tracked blob.
|
||||
type VerifyResult struct {
|
||||
Path string // tilde path from manifest
|
||||
OK bool
|
||||
Detail string // e.g. "ok", "hash mismatch", "blob missing"
|
||||
}
|
||||
|
||||
// Verify checks every file entry in the manifest against the blob store.
|
||||
// It confirms that the blob exists and that its content still matches
|
||||
// the recorded hash. Directories and symlinks are skipped because they
|
||||
// have no blobs.
|
||||
func (g *Garden) Verify() ([]VerifyResult, error) {
|
||||
var results []VerifyResult
|
||||
|
||||
for _, entry := range g.manifest.Files {
|
||||
if entry.Type != "file" {
|
||||
continue
|
||||
}
|
||||
|
||||
if !g.store.Exists(entry.Hash) {
|
||||
results = append(results, VerifyResult{
|
||||
Path: entry.Path,
|
||||
OK: false,
|
||||
Detail: "blob missing",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := g.store.Read(entry.Hash)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading blob for %s: %w", entry.Path, err)
|
||||
}
|
||||
|
||||
sum := sha256.Sum256(data)
|
||||
got := hex.EncodeToString(sum[:])
|
||||
|
||||
if got != entry.Hash {
|
||||
results = append(results, VerifyResult{
|
||||
Path: entry.Path,
|
||||
OK: false,
|
||||
Detail: "hash mismatch",
|
||||
})
|
||||
} else {
|
||||
results = append(results, VerifyResult{
|
||||
Path: entry.Path,
|
||||
OK: true,
|
||||
Detail: "ok",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
Reference in New Issue
Block a user