sots-re/campaign/rollout/sync_verifier_snapshot.py

64 lines
3 KiB
Python

#!/usr/bin/env python3
"""Populate clean, disposable paired worktrees with the exact uncommitted integration source."""
import argparse
from pathlib import Path
import shutil
import subprocess
import sys
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "tools"))
from campaign import Campaign, ControlError, git_value, source_manifest
def files(root):
return {name for name in git_value(root, "ls-files", "-z", "--cached", "--others", "--exclude-standard").split("\0") if name}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--engine-worktree", required=True, type=Path)
parser.add_argument("--re-worktree", required=True, type=Path)
args = parser.parse_args()
campaign = Campaign(str(ROOT))
contract = campaign.load("controls-bootstrap")
for kind, target in (("engine", args.engine_worktree), ("re", args.re_worktree)):
target = target.resolve()
source = Path(contract["baseline"][kind]["path"])
if target == source or not str(target).startswith("/tmp/opencode/sots-final-"):
raise ControlError("only rollout-owned sots-final-* temporary worktrees may be populated")
if git_value(target, "status", "--porcelain", "--untracked-files=all"):
raise ControlError("snapshot destination must be clean; never overwrite existing work")
if git_value(target, "rev-parse", "--path-format=absolute", "--git-common-dir") != git_value(source, "rev-parse", "--path-format=absolute", "--git-common-dir"):
raise ControlError("destination is not a linked worktree of this repository")
if git_value(target, "rev-parse", "HEAD") != contract["baseline"][kind]["commit"]:
raise ControlError("destination baseline mismatch")
before = source_manifest(source, kind)
names = files(source)
for name in files(target) - names:
path = target / name
if path.is_file():
path.unlink()
for name in names:
if name.startswith(("campaign/runtime/", "campaign/evidence/")):
continue
src, dst = source / name, target / name
if src.is_symlink():
raise ControlError("source symlink unsupported")
if src.is_file():
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
elif dst.is_file():
dst.unlink() # Reproduce tracked source deletions in this disposable tree.
after, actual = source_manifest(source, kind), source_manifest(target, kind)
if after != before or actual["sha256"] != before["sha256"]:
raise ControlError("source changed or copied integration snapshot differs")
print(f"{kind}: exact integration source {actual['sha256']} at {target}")
if __name__ == "__main__":
try:
main()
except (ControlError, OSError, ValueError, subprocess.SubprocessError) as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)