deterministic-engine / build_archive.py
mirdax25-ux's picture
Release portable deterministic core 1.1.0: frozen formats, offline recovery and regression checks
ecad52f verified
Raw History Blame Contribute Delete
1.82 kB
#!/usr/bin/env python3
"""Rebuild the exact source ZIP from a verified extracted release, offline."""
import hashlib
import json
import sys
import zipfile
from pathlib import Path
from safe_json import strict_loads
from verify_release import verify_release
def build_archive(root, target):
root, target = Path(root).resolve(), Path(target).resolve()
if target.is_relative_to(root):
raise ValueError("Write the ZIP outside the extracted release directory")
checked = verify_release(root)
if not checked["verified"]:
raise ValueError("Source integrity check failed")
manifest = strict_loads((root / "RELEASE_MANIFEST.json").read_text(encoding="utf-8"))
names = sorted([*manifest["files"], "RELEASE_MANIFEST.json"])
with target.open("xb") as handle:
with zipfile.ZipFile(handle, "w", compression=zipfile.ZIP_STORED) as archive:
for name in names:
entry = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))
entry.create_system = 3
entry.external_attr = 0o100644 << 16
entry.compress_type = zipfile.ZIP_STORED
archive.writestr(entry, (root / name).read_bytes())
data = target.read_bytes()
return {"built": True, "bytes": len(data), "files": len(names), "sha256": hashlib.sha256(data).hexdigest(), "sha512": hashlib.sha512(data).hexdigest()}
if __name__ == "__main__":
try:
if len(sys.argv) != 2:
raise ValueError("Usage: python -B build_archive.py ../rebuilt.zip")
result = build_archive(Path(__file__).resolve().parent, sys.argv[1])
print(json.dumps(result, sort_keys=True))
except (ValueError, OSError, zipfile.BadZipFile) as exc:
print(json.dumps({"built": False, "error": str(exc)}))
sys.exit(2)