71 lines
3.7 KiB
Python
71 lines
3.7 KiB
Python
"""Package the fixed, closed capture-1 pixels using an existing checks package."""
|
|
from pathlib import Path
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
import zipfile
|
|
from verify import COMMIT, MEMBERS, SOURCES, OUTER, need, pin, checks_data, verify_data, verify_package
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--root", type=Path, required=True)
|
|
parser.add_argument("--checks", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path)
|
|
parser.add_argument("--check-only", action="store_true")
|
|
args = parser.parse_args()
|
|
need(args.check_only or args.output is not None, "--output or --check-only required")
|
|
if args.output:
|
|
need(not args.output.exists(), "fresh nonexistent output directory required")
|
|
checks = checks_data(args.checks)
|
|
gate, source = checks
|
|
# Compare every captured source byte to the named commit, not current worktree.
|
|
paths = sorted(source)
|
|
result = subprocess.run(["git", "cat-file", "--batch"], cwd=args.root,
|
|
input="".join(COMMIT + ":" + name + "\n" for name in paths).encode(), capture_output=True, check=True)
|
|
offset = 0
|
|
for name in paths:
|
|
end = result.stdout.index(b"\n", offset)
|
|
header = result.stdout[offset:end].split()
|
|
need(len(header) == 3 and header[1] == b"blob", "missing commit blob: " + name)
|
|
size = int(header[2])
|
|
data = result.stdout[end + 1:end + 1 + size]
|
|
need(data == source[name], "captured input differs from b153: " + name)
|
|
offset = end + 2 + size
|
|
need(offset == len(result.stdout), "exact Git batch readback")
|
|
folder = args.root / ".local/process-feedback-review"
|
|
need({p.relative_to(folder).as_posix() for p in (folder / "capture-1").rglob("*") if p.is_file()} == {name for name in MEMBERS if name.startswith("capture-1/")}, "exact captured file inventory")
|
|
payload = {}
|
|
for name in sorted(MEMBERS):
|
|
path = folder / name
|
|
need(not path.is_symlink() and not getattr(path, "is_junction", lambda: False)(), "linked input")
|
|
payload[name] = path.read_bytes()
|
|
manifest = {"schema": 1, "kind": "process-render-feedback", "sourceCommit": COMMIT,
|
|
"checksRun": "feedback-1", "checksPins": {name: pin(data) for name, data in gate.items()},
|
|
"capturingSources": {name: pin(source[name]) for name in SOURCES},
|
|
"members": {name: pin(data) for name, data in payload.items()}}
|
|
summary = verify_data(manifest, payload.__getitem__, checks)
|
|
if args.check_only:
|
|
print("PASS raw pixels, metadata and all 742 b153 source blobs:", summary)
|
|
return
|
|
out = args.output.resolve()
|
|
out.mkdir(parents=True, exist_ok=False)
|
|
for name in ("prepare.py", "verify.py", "README.md"):
|
|
(out / name).write_bytes((HERE / name).read_bytes())
|
|
with zipfile.ZipFile(out / "evidence.zip", "x", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
|
|
for name, data in payload.items():
|
|
info = zipfile.ZipInfo(name, date_time=(2026, 9, 23, 0, 0, 0))
|
|
info.compress_type = zipfile.ZIP_DEFLATED
|
|
info.external_attr = 0o100644 << 16
|
|
archive.writestr(info, data)
|
|
(out / "manifest.json").write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
|
(out / "files.json").write_text(json.dumps({name: pin((out / name).read_bytes()) for name in sorted(OUTER)}, indent=2) + "\n", encoding="utf-8")
|
|
need(verify_package(out, checks) == summary, "written archive readback")
|
|
print("PASS package readback and all 742 b153 source blobs:", out, summary)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|