"""Provision a reviewable launcher candidate. Never sets CODEX_CLI_PATH or restarts apps.""" import argparse import hashlib import json from pathlib import Path import shutil def prepare(source, destination, original, expected_sha256, python, bridge_home, hermes_home): source, destination = Path(source).resolve(), Path(destination).resolve() original, python = Path(original).resolve(), Path(python).resolve() def digest(p): with p.open('rb') as f: return hashlib.file_digest(f,'sha256').hexdigest() if digest(original) != expected_sha256.lower(): raise ValueError('chosen official original hash mismatch') if original == destination/'native-watch.exe': raise ValueError('recursive original') if source == destination: raise ValueError('candidate must use separate destination') destination.mkdir(parents=True,exist_ok=True) for p in source.rglob('*'): if p.is_file() and (p.suffix in ('.py','.pyd') or p.name in ('native-watch.exe','LICENSE')) and not p.name.startswith('test_'): target=destination/p.relative_to(source);target.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(p,target) script=destination/'native_watch_launcher.py' manifest=dict(original=str(original),original_sha256=expected_sha256.lower(),python=str(python),python_sha256=digest(python),script=str(script),script_sha256=digest(script),bridge_home=str(Path(bridge_home).resolve()),hermes_home=str(Path(hermes_home).resolve())) (destination/'native-watch.json').write_text(json.dumps(manifest,indent=2),encoding='utf-8') return destination/'native-watch.exe' if __name__=='__main__': p=argparse.ArgumentParser(description=__doc__) for name in ('source','destination','original','expected-sha256','python','bridge-home','hermes-home'): p.add_argument('--'+name,required=True) args=vars(p.parse_args());print(prepare(**args))