#!/usr/bin/env python3 """build_commit_map.py — the public ordinal → new-hash map, and the private old → new map (P33 C7). tools/public_rewrite/build_commit_map.py [--new .run/public_rewrite/repo.git] Writes docs/commit-map.tsv (PUBLIC): one row per commit of the OLD main in order — `ordinal new_hash author_date committer_date subject` — with NO old hash anywhere (asserted: the scrub over the file's own bytes makes 0 replacements). The pruned purge-only commit keeps its row with `new_hash` = 40 zeros so the ordinals stay dense and every `commit:NNNN` token in history has a row. Dates/subjects are read from the NEW commits (already scrubbed by the rewrite); the pruned row's from the old commit, scrubbed here. Writes .run/public_rewrite/old-to-new.tsv (PRIVATE, for probe_github.sh): `ordinal old_hash new_hash`. """ import argparse import sys sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent)) import common as C # noqa: E402 import scrub # noqa: E402 def main(argv): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("--new", default=str(C.CLONE_DIR)) ap.add_argument("--old", default=str(C.REPO)) ap.add_argument("--out", default=str(C.COMMIT_MAP_PUBLIC), help="the public map path (a scratch path for a trial run)") ap.add_argument("--private-out", default=str(C.OLD_TO_NEW_FILE)) a = ap.parse_args(argv) out_pub, out_priv = __import__("pathlib").Path(a.out), __import__("pathlib").Path(a.private_out) new_repo = __import__("pathlib").Path(a.new) import verify_rewrite cmap = verify_rewrite.commit_map(new_repo) d = C.load_dict() old_main = [h for h, e in sorted(d["commits"].items(), key=lambda kv: kv[1].get("ord", 0)) if e["kind"] == "main"] if len(old_main) != d["main_count"]: C.die(f"dictionary main count mismatch ({len(old_main)} vs {d['main_count']})") s = scrub.Scrubber() rows, priv = [], [] for h in old_main: o = d["commits"][h]["ord"] new = cmap.get(h) if new is None: C.die(f"old main commit ordinal {o} ({h[:9]}) is not in the commit-map — the clone did not hold the same main") if new == C.ZEROS: ad, cd, subj = C.git(["log", "-1", "--format=%aI%x00%cI%x00%s", h], a.old).rstrip("\n").split("\0") subj = s.scrub_text(subj.encode()).decode("utf-8", "replace") else: ad, cd, subj = C.git(["log", "-1", "--format=%aI%x00%cI%x00%s", new], new_repo).rstrip("\n").split("\0") rows.append(f"{o:04d}\t{new}\t{ad}\t{cd}\t{subj}") priv.append(f"{o:04d}\t{h}\t{new}") header = ("# docs/commit-map.tsv — the public history's commit map (P33 C7). Generated by tools/public_rewrite/build_commit_map.py; never edit.\n" "# Before the public flip the history was rewritten (ROM-derived paths purged, personal addresses mapped, old commit hashes\n" "# in every historical doc replaced by the inert token commit:NNNN). NNNN is the ordinal of the commit on main in the ORIGINAL\n" "# order (1 = the first commit); this table maps it to the rewritten commit. A row of 40 zeros is the one commit that touched\n" "# only purged paths and was pruned. Documents at the tip cite the new hashes directly (tools/public_rewrite/resolve_tokens.py).\n" "ordinal\tnew_hash\tauthor_date\tcommitter_date\tsubject\n") text = header + "\n".join(rows) + "\n" # a commit the rewrite left byte-identical (old == new: e.g. the noreply-authored "Initial commit", which cites no # hash and touches no purge path) legitimately keeps its hash — exempt those from the old-hash assertion unchanged = {o for o, n in cmap.items() if o == n} d2 = {"commits": {h: e for h, e in d["commits"].items() if h not in unchanged}, "ambiguous": d["ambiguous"], "excluded": d["excluded"]} s2 = scrub.Scrubber(d2) out = s2.scrub_text(text.encode()) if s2.stats["replaced"] or s2.stats["emails"]: C.die(f"the public map would carry {s2.stats['replaced']} old-hash tokens / {s2.stats['emails']} addresses — refusing") (C.SCRATCH / "unchanged_commits.txt").write_text("\n".join(sorted(unchanged)) + ("\n" if unchanged else ""), encoding="utf-8") out_pub.write_text(text, encoding="utf-8") out_priv.write_text("ordinal\told_hash\tnew_hash\n" + "\n".join(priv) + "\n", encoding="utf-8") zeros = sum(1 for r in rows if "\t" + C.ZEROS + "\t" in r) print(f"build_commit_map: {len(rows)} rows -> {out_pub} ({zeros} pruned rows); private old-to-new -> {out_priv}; " f"0 old-hash tokens in the public file (asserted; {len(unchanged)} commits unchanged by the rewrite keep their hash)") return 0 if __name__ == "__main__": sys.exit(main(sys.argv[1:]))