"""Phase 6: verify every archive and write CHECKSUMS.sha256 and checkpoints/verification.json.""" import glob import hashlib import json import os import re import subprocess import sys import tempfile import zipfile sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from nlr_common import ROOT, log, now, sha256_file, write_json HTMLISH = re.compile(rb"^\s*( 22) out["archives"][bn] = rec lines.append(f"{rec['sha256']} zips/{bn}") log(f"verify {bn}: {'PASS' if rec['passed'] else 'FAIL'} ({rec['bytes']} bytes)", echo=False) # Recovered individual files (from manifests; recomputed only for the content store spot check below). for mp in sorted(glob.glob(os.path.join(ROOT, "sites", "*", "manifests", "deploy_*_recovery.json"))): m = json.load(open(mp)) site_rel = os.path.relpath(os.path.dirname(os.path.dirname(mp)), ROOT) for e in m["files"]: if e.get("sha256"): lines.append(f"{e['sha256']} {site_rel}/originals/deploy_{m['deploy']['id']}/{e['local_path']}") with open(os.path.join(ROOT, "CHECKSUMS.sha256.tmp"), "w") as f: f.write("\n".join(lines) + "\n") os.replace(os.path.join(ROOT, "CHECKSUMS.sha256.tmp"), os.path.join(ROOT, "CHECKSUMS.sha256")) # Re-hash every recovered original on disk against the checksum list. bad = 0 for ln in lines: h, rel = ln.split(" ", 1) if not rel.startswith("zips/") and sha256_file(os.path.join(ROOT, rel)) != h: bad += 1 out["original_files_checked"] = sum(1 for ln in lines if not ln.split(" ", 1)[1].startswith("zips/")) out["original_files_hash_mismatch"] = bad out["archives_total"] = len(out["archives"]) out["archives_passed"] = sum(1 for r in out["archives"].values() if r["passed"]) write_json(os.path.join(ROOT, "checkpoints", "verification.json"), out) log(f"verification: {out['archives_passed']}/{out['archives_total']} archives passed; " f"{out['original_files_checked']} original files rechecked, {bad} mismatches; on Desktop={out['root_is_on_users_desktop']}") if __name__ == "__main__": main()