| #!/usr/bin/env python3 | |
| """Verify final paper-output checksums.""" | |
| from __future__ import annotations | |
| import hashlib | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parents[1] | |
| MANIFEST = ROOT / "artifacts" / "manifests" / "paper_outputs.sha256" | |
| def sha256(path: Path) -> str: | |
| digest = hashlib.sha256() | |
| with path.open("rb") as fh: | |
| for chunk in iter(lambda: fh.read(1024 * 1024), b""): | |
| digest.update(chunk) | |
| return digest.hexdigest() | |
| def main() -> None: | |
| issues: list[str] = [] | |
| for line_no, line in enumerate(MANIFEST.read_text(encoding="utf-8").splitlines(), start=1): | |
| if not line.strip(): | |
| continue | |
| try: | |
| expected, rel = line.split(None, 1) | |
| except ValueError: | |
| issues.append(f"bad checksum line {line_no}: {line!r}") | |
| continue | |
| path = ROOT / rel.strip() | |
| if not path.exists(): | |
| issues.append(f"missing output listed in checksum manifest: {rel}") | |
| continue | |
| actual = sha256(path) | |
| if actual != expected: | |
| issues.append(f"checksum mismatch for {rel}: expected {expected}, got {actual}") | |
| if issues: | |
| print("Paper-output checksum check failed:") | |
| for issue in issues: | |
| print(f"- {issue}") | |
| raise SystemExit(1) | |
| print("Paper-output checksum check passed.") | |
| if __name__ == "__main__": | |
| main() | |