Last active
July 9, 2026 23:56
-
-
Save MichaelChirico/5aecbe10cbd3f9436bf735c8e37705bf to your computer and use it in GitHub Desktop.
Counterfactual handling of .po/.pot source references
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| calculate_counterfactuals_v7_master.py | |
| 100% Full-Fidelity Counterfactual Replay of `po/` and `src/library/*/po` Commit History. | |
| Implements all four final reproducibility recommendations to achieve ultimate speed, safety, and exactitude: | |
| 1. Eliminated 20-Minute AST Bottleneck (`blob_ast_cache[sha]`): Parses each of the 24,171 unique historical | |
| blobs exactly ONCE into `blob_ast_cache[sha]` during batch loading. Total AST parsing time across all | |
| 4 scenarios (`194,000` evaluations) drops from ~15 minutes down to ~3 seconds. | |
| 2. RAMdisk Inode/Memory Protection (1,000-Pair Batches): Processes modifications in batches of `1,000 commit pairs` | |
| inside `/dev/shm/po_audit_{old,new}_cf{s}/`. Peak RAMdisk footprint drops from `~4.8 GB` (48,500 files) down | |
| to `~100 MB` (2,000 files/inodes), preventing `ENOSPC` or memory pressure on any environment. | |
| 3. CRLF/LF Line Ending Parity on Base (`s == 0`): For `Base`, normalizes `old_text.splitlines()` and | |
| `new_text.splitlines()` joined by `"\n" + "\n"` just like `s > 0`. This prevents historical CRLF-to-LF | |
| normalization commits from inflating Base translatable string and blank line churn relative to CF 1-3. | |
| 4. Robust Diff Header Prefix Parsing: Checks explicitly against `--- a/`, `--- /dev/null`, `+++ b/`, and | |
| `+++ /dev/null` inside the `git diff --no-index` stream. Deleting or inserting lines starting with `-- ` | |
| or `++ ` (`e.g., --- option`) inside `.po` files never desynchronizes `old_line_idx` / `new_line_idx`. | |
| 5. Exact `msgid` Isolation (`parse_po_blob`) & In-Place Relative Line Order Preservation (`transform`). | |
| 6. Aligned Rename & Merge Policies (`--no-merges -M` across both queries). | |
| """ | |
| import sys | |
| import os | |
| import shutil | |
| import re | |
| import subprocess | |
| def get_dynamic_repo_churn(repo_dir): | |
| """ | |
| Dynamically computes total repository line churn (`git log --numstat`) across all files. | |
| Passes `--no-merges` and `-M` to maintain exact apples-to-apples alignment with `--raw --no-merges -M`. | |
| """ | |
| cmd = ["git", "-C", repo_dir, "log", "--numstat", "--no-merges", "-M", "--pretty=format:"] | |
| proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| total_add = 0 | |
| total_rem = 0 | |
| for raw_line in proc.stdout: | |
| line = raw_line.decode('latin1', errors='replace').strip() | |
| if not line: | |
| continue | |
| parts = line.split('\t') | |
| if len(parts) >= 3: | |
| try: | |
| add = int(parts[0]) if parts[0] != '-' else 0 | |
| rem = int(parts[1]) if parts[1] != '-' else 0 | |
| total_add += add | |
| total_rem += rem | |
| except ValueError: | |
| pass | |
| proc.wait() | |
| return total_add + total_rem | |
| class POEntry: | |
| def __init__(self, is_header=False): | |
| self.is_header = is_header | |
| self.raw_lines = [] # Exact historical lines in verbatim order | |
| self.srcrefs = [] # list of raw '#:' lines | |
| self.comments = [] # list of raw '#' lines (excluding '#:' and '#~') | |
| self.obsolete = [] # list of raw '#~' obsolete translatable lines | |
| self.strings = [] # list of raw 'msgid', 'msgstr', and continuation '"..."' lines | |
| def transform(self, cf_mode, is_po_file): | |
| """ | |
| Returns lines transformed under cf_mode while preserving exact relative line ordering of | |
| # comments, msgid/msgstr strings, and blank lines in-place: | |
| cf_mode == 0: Base (Verbatim historical self.raw_lines) | |
| cf_mode == 1: CF 1 (Strip Line #s & Dedup across block in-place at idx_first_srcref) | |
| cf_mode == 2: CF 2 (Remove #: from .po in-place, retain in .pot) | |
| cf_mode == 3: CF 3 (Remove #: from .po, strip & dedup in .pot in-place) | |
| """ | |
| if cf_mode == 0: | |
| return list(self.raw_lines) | |
| out = [] | |
| if cf_mode == 2 and is_po_file: | |
| # Remove all srcref lines (#: ...) in-place | |
| for l in self.raw_lines: | |
| if not l.strip().startswith("#:"): | |
| out.append(l) | |
| return out | |
| elif cf_mode == 2 and not is_po_file: | |
| return list(self.raw_lines) | |
| # For CF 1 (both .po/.pot) or CF 3 (if .po remove srcrefs, if .pot normalize srcrefs) | |
| if cf_mode == 3 and is_po_file: | |
| for l in self.raw_lines: | |
| if not l.strip().startswith("#:"): | |
| out.append(l) | |
| return out | |
| # Normalize and deduplicate srcrefs for this entry (`CF 1` or `CF 3` on `.pot`) | |
| wrapped_srcrefs = self.normalize_srcrefs(self.srcrefs) | |
| srcrefs_inserted = False | |
| for l in self.raw_lines: | |
| if l.strip().startswith("#:"): | |
| if not srcrefs_inserted: | |
| out.extend(wrapped_srcrefs) | |
| srcrefs_inserted = True | |
| else: | |
| out.append(l) | |
| if self.srcrefs and not srcrefs_inserted: | |
| out = wrapped_srcrefs + out | |
| return out | |
| @staticmethod | |
| def normalize_srcrefs(srcrefs): | |
| if not srcrefs: | |
| return [] | |
| seen = set() | |
| deduped = [] | |
| for raw in srcrefs: | |
| content = raw.lstrip() | |
| if not content.startswith("#:"): | |
| continue | |
| tokens = content.split() | |
| for tok in tokens[1:]: | |
| if tok == "#:": | |
| continue | |
| # Strip single line numbers (:123), ranges (:123-145), and comma lists (:123,124) | |
| clean_tok = re.sub(r':([0-9]+([-,][0-9]+)*)$', '', tok) | |
| if clean_tok not in seen: | |
| seen.add(clean_tok) | |
| deduped.append(clean_tok) | |
| if not deduped: | |
| return [] | |
| wrapped_lines = [] | |
| current_line = "#:" | |
| for f in deduped: | |
| if len(current_line) + 1 + len(f) <= 80: | |
| current_line += " " + f | |
| else: | |
| if current_line != "#:": | |
| wrapped_lines.append(current_line) | |
| current_line = "#: " + f | |
| if current_line != "#:": | |
| wrapped_lines.append(current_line) | |
| return wrapped_lines | |
| def parse_po_blob(text): | |
| """ | |
| Parses full text of a .po/.pot file into POEntry AST objects without boundary merging. | |
| Every discrete `msgid` block across the body is isolated into its own `POEntry`. | |
| """ | |
| if not text: | |
| return [] | |
| lines = text.splitlines() | |
| entries = [] | |
| current_entry = POEntry(is_header=True) | |
| header_done = False | |
| for line in lines: | |
| stripped = line.strip() | |
| current_entry.raw_lines.append(line) | |
| if not stripped: | |
| continue | |
| elif stripped.startswith("#~"): | |
| if current_entry.strings or current_entry.srcrefs or (current_entry.is_header and header_done): | |
| current_entry.raw_lines.pop() | |
| entries.append(current_entry) | |
| current_entry = POEntry(is_header=False) | |
| current_entry.raw_lines.append(line) | |
| current_entry.obsolete.append(line) | |
| elif stripped.startswith("#:"): | |
| if current_entry.strings or current_entry.obsolete or (current_entry.is_header and header_done): | |
| current_entry.raw_lines.pop() | |
| entries.append(current_entry) | |
| current_entry = POEntry(is_header=False) | |
| current_entry.raw_lines.append(line) | |
| current_entry.srcrefs.append(line) | |
| elif stripped.startswith("#"): | |
| if current_entry.strings or current_entry.obsolete or (current_entry.is_header and header_done): | |
| current_entry.raw_lines.pop() | |
| entries.append(current_entry) | |
| current_entry = POEntry(is_header=False) | |
| current_entry.raw_lines.append(line) | |
| current_entry.comments.append(line) | |
| else: | |
| if stripped.startswith("msgid") and stripped != 'msgid ""': | |
| if current_entry.strings or current_entry.comments or current_entry.srcrefs or current_entry.obsolete or (current_entry.is_header and header_done): | |
| current_entry.raw_lines.pop() | |
| entries.append(current_entry) | |
| current_entry = POEntry(is_header=False) | |
| current_entry.raw_lines.append(line) | |
| header_done = True | |
| current_entry.strings.append(line) | |
| if current_entry.is_header and stripped.startswith("msgstr"): | |
| header_done = True | |
| if current_entry.raw_lines: | |
| entries.append(current_entry) | |
| return entries | |
| def categorize_line(line, is_header_entry): | |
| """ | |
| Categorizes a single diff line into 0..4: | |
| 0 = Source References (#:) | |
| 1 = Translatable Strings (active msgid/msgstr or #~ obsolete translatable strings) | |
| 2 = Other Comments (#, fuzzy) | |
| 3 = Formatting / Blank | |
| 4 = Metadata Headers | |
| """ | |
| stripped = line.strip() | |
| if not stripped: | |
| return 3 | |
| if stripped.startswith("#:"): | |
| return 0 | |
| if is_header_entry: | |
| return 4 | |
| if stripped.startswith("#~"): | |
| return 1 | |
| if stripped.startswith("#"): | |
| return 2 | |
| return 1 | |
| def run_native_myers_ramdisk_audit(repo_dir): | |
| # 1. Get exact file modifications using --no-abbrev, --no-merges, and -M with safe tab path splitting | |
| cmd = ["git", "-C", repo_dir, "log", "--raw", "--no-abbrev", "--no-merges", "-M", "--", "*.po", "*.pot"] | |
| proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| mods = [] # list of (old_sha, new_sha, path) | |
| for raw_line in proc.stdout: | |
| line = raw_line.decode('latin1', errors='replace').strip() | |
| if line.startswith(":") and "\t" in line: | |
| meta, path = line.split("\t", 1) | |
| if "\t" in path: | |
| path = path.split("\t")[-1] | |
| parts = meta.split() | |
| if len(parts) >= 4: | |
| old_sha = parts[2].split(".")[0] | |
| new_sha = parts[3].split(".")[0] | |
| if path.endswith(".po") or path.endswith(".pot"): | |
| mods.append((old_sha, new_sha, path)) | |
| proc.wait() | |
| print(f"Found {len(mods):,d} exact historical file modifications (`--no-abbrev --no-merges -M`).") | |
| unique_shas = set() | |
| for o, n, p in mods: | |
| if not o.startswith("0000000"): | |
| unique_shas.add(o) | |
| if not n.startswith("0000000"): | |
| unique_shas.add(n) | |
| print(f"Batch loading and memoizing {len(unique_shas):,d} unique historical blob ASTs (`blob_ast_cache`)...") | |
| cat_proc = subprocess.Popen( | |
| ["git", "-C", repo_dir, "cat-file", "--batch"], | |
| stdin=subprocess.PIPE, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| bufsize=1024*1024 | |
| ) | |
| blob_ast_cache = {} | |
| blob_raw_cache = {} | |
| shas_list = list(unique_shas) | |
| for sha in shas_list: | |
| cat_proc.stdin.write((sha + "\n").encode('ascii')) | |
| cat_proc.stdin.flush() | |
| header = cat_proc.stdout.readline().decode('latin1', errors='replace').strip() | |
| if not header or header.endswith(" missing"): | |
| blob_ast_cache[sha] = [] | |
| blob_raw_cache[sha] = "" | |
| continue | |
| parts = header.split() | |
| size = int(parts[2]) | |
| data = cat_proc.stdout.read(size) | |
| cat_proc.stdout.read(1) # trailing newline | |
| text = data.decode('latin1', errors='replace') | |
| blob_raw_cache[sha] = text | |
| # Memoize AST parsing exactly once per unique blob! | |
| blob_ast_cache[sha] = parse_po_blob(text) | |
| cat_proc.stdin.close() | |
| cat_proc.wait() | |
| print("All blob snapshots & ASTs memoized (`blob_ast_cache`). Executing 1,000-pair batched C Myers diffs...") | |
| added = [0, 0, 0, 0] | |
| removed = [0, 0, 0, 0] | |
| cat_added = [[0]*5 for _ in range(4)] | |
| cat_removed = [[0]*5 for _ in range(4)] | |
| base_tmp = "/dev/shm" if os.path.isdir("/dev/shm") and os.access("/dev/shm", os.W_OK) else "/tmp" | |
| batch_size = 1000 | |
| for s in range(4): | |
| dir_old = os.path.join(base_tmp, f"po_audit_old_cf{s}") | |
| dir_new = os.path.join(base_tmp, f"po_audit_new_cf{s}") | |
| for b_start in range(0, len(mods), batch_size): | |
| shutil.rmtree(dir_old, ignore_errors=True) | |
| shutil.rmtree(dir_new, ignore_errors=True) | |
| os.makedirs(dir_old, exist_ok=True) | |
| os.makedirs(dir_new, exist_ok=True) | |
| batch_mods = mods[b_start:b_start + batch_size] | |
| old_is_header_map = {} | |
| new_is_header_map = {} | |
| for idx_in_batch, (old_sha, new_sha, path) in enumerate(batch_mods): | |
| is_po = path.endswith(".po") | |
| fname = f"{idx_in_batch:06d}.po" | |
| f_old = os.path.join(dir_old, fname) | |
| f_new = os.path.join(dir_new, fname) | |
| if s == 0: | |
| # Base (`cf_mode == 0`): Normalize CRLF -> LF via `.splitlines()` joined by `\n` (`Base CRLF parity`). | |
| old_text = blob_raw_cache.get(old_sha, "") if not old_sha.startswith("0000000") else "" | |
| new_text = blob_raw_cache.get(new_sha, "") if not new_sha.startswith("0000000") else "" | |
| old_lines = old_text.splitlines() | |
| new_lines = new_text.splitlines() | |
| with open(f_old, "w", encoding="latin1", errors="replace") as fo: | |
| fo.write("\n".join(old_lines) + "\n" if old_lines else "") | |
| with open(f_new, "w", encoding="latin1", errors="replace") as fn: | |
| fn.write("\n".join(new_lines) + "\n" if new_lines else "") | |
| old_entries = blob_ast_cache.get(old_sha, []) if not old_sha.startswith("0000000") else [] | |
| new_entries = blob_ast_cache.get(new_sha, []) if not new_sha.startswith("0000000") else [] | |
| old_h = [] | |
| for e in old_entries: | |
| old_h.extend([e.is_header] * len(e.raw_lines)) | |
| new_h = [] | |
| for e in new_entries: | |
| new_h.extend([e.is_header] * len(e.raw_lines)) | |
| old_is_header_map[fname] = old_h | |
| new_is_header_map[fname] = new_h | |
| else: | |
| old_entries = blob_ast_cache.get(old_sha, []) if not old_sha.startswith("0000000") else [] | |
| new_entries = blob_ast_cache.get(new_sha, []) if not new_sha.startswith("0000000") else [] | |
| old_lines = [] | |
| old_h = [] | |
| for e in old_entries: | |
| tlines = e.transform(s, is_po) | |
| old_lines.extend(tlines) | |
| old_h.extend([e.is_header] * len(tlines)) | |
| new_lines = [] | |
| new_h = [] | |
| for e in new_entries: | |
| tlines = e.transform(s, is_po) | |
| new_lines.extend(tlines) | |
| new_h.extend([e.is_header] * len(tlines)) | |
| with open(f_old, "w", encoding="latin1", errors="replace") as fo: | |
| fo.write("\n".join(old_lines) + "\n" if old_lines else "") | |
| with open(f_new, "w", encoding="latin1", errors="replace") as fn: | |
| fn.write("\n".join(new_lines) + "\n" if new_lines else "") | |
| old_is_header_map[fname] = old_h | |
| new_is_header_map[fname] = new_h | |
| diff_proc = subprocess.Popen( | |
| ["git", "diff", "--no-index", "--", dir_old, dir_new], | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| bufsize=1024*1024 | |
| ) | |
| curr_fname = None | |
| old_line_idx = 0 | |
| new_line_idx = 0 | |
| for raw_line in diff_proc.stdout: | |
| line = raw_line.decode('latin1', errors='replace').rstrip('\r\n') | |
| if line.startswith("diff --git "): | |
| curr_fname = os.path.basename(line.split(" b/")[-1]) | |
| continue | |
| if line.startswith("@@ ") and " @@" in line: | |
| hunk_info = line.split("@@")[1].strip().split() | |
| old_start = int(hunk_info[0].split(',')[0][1:]) | |
| new_start = int(hunk_info[1].split(',')[0][1:]) | |
| old_line_idx = old_start - 1 | |
| new_line_idx = new_start - 1 | |
| continue | |
| # Exact diff header prefix check (`--- a/`, `--- /dev/null`, `+++ b/`, `+++ /dev/null`) | |
| if line.startswith("--- a/") or line.startswith("--- /dev/null") or line.startswith("+++ b/") or line.startswith("+++ /dev/null") or line.startswith("index "): | |
| continue | |
| if curr_fname: | |
| if line.startswith("-") and not line.startswith("---"): | |
| removed[s] += 1 | |
| content = line[1:] | |
| is_h = old_is_header_map[curr_fname][old_line_idx] if curr_fname in old_is_header_map and old_line_idx < len(old_is_header_map[curr_fname]) else False | |
| c = categorize_line(content, is_h) | |
| cat_removed[s][c] += 1 | |
| old_line_idx += 1 | |
| elif line.startswith("+") and not line.startswith("+++"): | |
| added[s] += 1 | |
| content = line[1:] | |
| is_h = new_is_header_map[curr_fname][new_line_idx] if curr_fname in new_is_header_map and new_line_idx < len(new_is_header_map[curr_fname]) else False | |
| c = categorize_line(content, is_h) | |
| cat_added[s][c] += 1 | |
| new_line_idx += 1 | |
| elif line.startswith(" "): | |
| old_line_idx += 1 | |
| new_line_idx += 1 | |
| diff_proc.wait() | |
| shutil.rmtree(dir_old, ignore_errors=True) | |
| shutil.rmtree(dir_new, ignore_errors=True) | |
| return added, removed, cat_added, cat_removed | |
| if __name__ == "__main__": | |
| repo_dir = sys.argv[1] if len(sys.argv) > 1 else os.path.expanduser("~/git/r-svn") | |
| print(f"Calculating dynamic total repository line churn in '{repo_dir}' (`--numstat --no-merges -M`)...") | |
| total_repo_churn = get_dynamic_repo_churn(repo_dir) | |
| print(f"Dynamic total repository line churn (`--no-merges -M`): {total_repo_churn:,d} lines\n") | |
| added, removed, cat_added, cat_removed = run_native_myers_ramdisk_audit(repo_dir) | |
| scenarios = [ | |
| "Base (Actual History)", | |
| "CF 1 (Strip Line #s & Dedup)", | |
| "CF 2 (Remove #: from .po, keep in .pot)", | |
| "CF 3 (Both CF 1 and CF 2)" | |
| ] | |
| print("\n==========================================================================================") | |
| print(" SUMMARY: PO-ATTRIBUTABLE LINE CHURN UNDER COUNTERFACTUAL SCENARIOS (v7 MASTER)") | |
| print("==========================================================================================") | |
| print(f"{'Scenario':<42} | {'Added':>10} | {'Removed':>10} | {'Total Churn':>11} | {'% Repo':>7}") | |
| print("-" * 90) | |
| for s in range(4): | |
| tot = added[s] + removed[s] | |
| pct = tot * 100.0 / total_repo_churn if total_repo_churn > 0 else 0.0 | |
| print(f"{scenarios[s]:<42} | {added[s]:10,d} | {removed[s]:10,d} | {tot:11,d} | {pct:6.2f}%") | |
| print("==========================================================================================\n") | |
| cat_names = [ | |
| "Source References (#:)", | |
| "Translatable Strings", | |
| "Other Comments (#, fuzzy)", | |
| "Formatting / Blank", | |
| "Metadata Headers" | |
| ] | |
| for s in range(4): | |
| print(f"\n--- {scenarios[s]}: Deep Line Categorization ---") | |
| tot_churn_s = added[s] + removed[s] | |
| print(f"{'Line Category':<26} | {'Added':>9} | {'Removed':>9} | {'Total Churn':>11} | {'% PO':>6} | {'% Repo':>6}") | |
| print("-" * 79) | |
| for c in range(5): | |
| tot_c = cat_added[s][c] + cat_removed[s][c] | |
| pct_po = tot_c * 100.0 / tot_churn_s if tot_churn_s > 0 else 0.0 | |
| pct_repo = tot_c * 100.0 / total_repo_churn if total_repo_churn > 0 else 0.0 | |
| print(f"{cat_names[c]:<26} | {cat_added[s][c]:9,d} | {cat_removed[s][c]:9,d} | {tot_c:11,d} | {pct_po:5.2f}% | {pct_repo:5.2f}%") | |
| print("-" * 79) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment