31 lines
1.9 KiB
Python
31 lines
1.9 KiB
Python
from __future__ import annotations
|
|
import argparse,hashlib,json
|
|
from pathlib import Path
|
|
|
|
REQUIRED=["VERSION","versions/V2R1C7.json","release-manifests/V2R1C7.json","deploy/aios-v2/systemd/aios-v2r1c7-production.service","active-runtime/app/deployment_state.py","active-runtime/app/v2r1c6_privacy_tools.py","active-runtime/app/v2r1c7_health_service.py","scripts/build_v2r1c7_release_artifact.py","scripts/verify_v2r1c7_release.py","scripts/probe_v2r1c7_health.py","scripts/rollback_v2r1c7_release.sh"]
|
|
|
|
def digest(p:Path)->str: return hashlib.sha256(p.read_bytes()).hexdigest()
|
|
|
|
def generate(root:Path)->dict[str,object]:
|
|
missing=[p for p in REQUIRED if not (root/p).is_file()]
|
|
entries=[]
|
|
for p in REQUIRED:
|
|
q=root/p
|
|
if q.is_file(): entries.append({"path":p,"sha256":digest(q),"size":q.stat().st_size})
|
|
manifest={"schema":"aios.v2r1c7.source-manifest.v1","version":"V2R1C7","required_files":REQUIRED,"files":entries,"missing":len(missing),"mismatched":0,"unexpected":0,"duplicates":0,"missing_paths":missing}
|
|
out=root/"artifacts/v2r1c7/SOURCE-MANIFEST.json"; out.parent.mkdir(parents=True,exist_ok=True); out.write_text(json.dumps(manifest,indent=2,sort_keys=True)+"\n",encoding="utf-8")
|
|
existing={}
|
|
root_manifest=root/"MANIFEST.sha256"
|
|
if root_manifest.is_file():
|
|
for line in root_manifest.read_text(encoding="utf-8").splitlines():
|
|
parts=line.split(maxsplit=1)
|
|
if len(parts)==2: existing[parts[1].lstrip("*")]=parts[0]
|
|
for rel in REQUIRED:
|
|
q=root/rel
|
|
if q.is_file(): existing[rel]=digest(q)
|
|
root_manifest.write_text("\n".join(f"{value} {key}" for key,value in sorted(existing.items()))+"\n",encoding="utf-8")
|
|
return manifest
|
|
|
|
if __name__=="__main__":
|
|
p=argparse.ArgumentParser(); p.add_argument("--root",type=Path,default=Path(".")); a=p.parse_args(); print(json.dumps(generate(a.root.resolve()),sort_keys=True))
|