v0.9.1: add deep checksum verification
This commit is contained in:
@@ -180,6 +180,7 @@ COMMANDS
|
||||
files are printed as <asset-id><TAB><filename>. Exits 2 on missing files.
|
||||
Add --sidecar to verify expected XMP sidecars too. Add --strict with
|
||||
--sidecar to require photoscli schema/generator and exported filename metadata.
|
||||
Add --deep to verify manifest SHA-256 checksums when present.
|
||||
|
||||
retry-failed --out <dir>
|
||||
Retry assets previously written to failures.jsonl.
|
||||
@@ -2279,6 +2280,7 @@ func cmdVerify(args []string, stdout, stderr io.Writer) int {
|
||||
outDir := flagVal(args, "--out")
|
||||
checkSidecar := hasFlag(args, "--sidecar")
|
||||
strictSidecar := hasFlag(args, "--strict")
|
||||
deep := hasFlag(args, "--deep")
|
||||
if outDir == "" {
|
||||
fmt.Fprintln(stderr, "error: --out is required")
|
||||
return exitErr
|
||||
@@ -2317,6 +2319,16 @@ func cmdVerify(args []string, stdout, stderr io.Writer) int {
|
||||
bad++
|
||||
fmt.Fprintf(stdout, "%s\t%s\tsize-mismatch\tmanifest=%d\tdisk=%d\n", id, checkPath, e.Size, info.Size())
|
||||
}
|
||||
if deep && e.Checksum != "" {
|
||||
checksum, err := fileSHA256(filepath.Join(outDir, checkPath))
|
||||
if err != nil {
|
||||
bad++
|
||||
fmt.Fprintf(stdout, "%s\t%s\tchecksum-unreadable\n", id, checkPath)
|
||||
} else if checksum != e.Checksum {
|
||||
bad++
|
||||
fmt.Fprintf(stdout, "%s\t%s\tchecksum-mismatch\tmanifest=%s\tdisk=%s\n", id, checkPath, e.Checksum, checksum)
|
||||
}
|
||||
}
|
||||
if checkSidecar {
|
||||
bad += verifySidecar(stdout, outDir, id, checkPath, strictSidecar)
|
||||
}
|
||||
|
||||
@@ -4273,6 +4273,39 @@ func TestMoreIntegrityBranches(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyDeepChecksums(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := os.WriteFile(filepath.Join(dir, "good.jpg"), []byte("abc"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "bad.jpg"), []byte("bad"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "nocheck.jpg"), []byte("data"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Mkdir(filepath.Join(dir, "adir"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := manifest.LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.AddEntry(manifest.Entry{ID: "good", Filename: "good.jpg", Path: "good.jpg", Size: 3, Cloud: "local", Checksum: "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "bad", Filename: "bad.jpg", Path: "bad.jpg", Size: 3, Cloud: "local", Checksum: "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "nocheck", Filename: "nocheck.jpg", Path: "nocheck.jpg", Size: 4, Cloud: "local", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "unreadable", Filename: "adir", Path: "adir", Cloud: "local", Checksum: "abc", Exported: time.Now().Unix()})
|
||||
m.Close()
|
||||
out, stderr, rc := runWith([]string{"verify", "--out", dir, "--deep"}, &mockBridge{})
|
||||
if rc != exitPartial || stderr != "" || !strings.Contains(out, "checksum-mismatch") || !strings.Contains(out, "checksum-unreadable") || strings.Contains(out, "good.jpg") || strings.Contains(out, "nocheck") {
|
||||
t.Fatalf("deep verify rc=%d out=%q stderr=%q", rc, out, stderr)
|
||||
}
|
||||
out, stderr, rc = runWith([]string{"verify", "--out", dir}, &mockBridge{})
|
||||
if rc != exitOK || stderr != "" || strings.Contains(out, "checksum") {
|
||||
t.Fatalf("plain verify rc=%d out=%q stderr=%q", rc, out, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySidecarBranches(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
subdir := filepath.Join(dir, "sub")
|
||||
|
||||
Reference in New Issue
Block a user