Files
troupe-standup/wizard-work/ledger/extract_checkin_census.py
T

67 lines
1.9 KiB
Python

#!/usr/bin/env python3
"""Extract the dated check-in census for the troupe repo into CSV.
One row per dated check-in file under checkins/ (README.md is repo docs, not a
check-in, and is excluded). Columns: date, wizard, path, size_bytes, blob_sha1.
The re-derivation is from git itself (ls-tree), so the CSV is a faithful
extraction of the committed tree, independent of the working-tree state.
"""
import csv
import os
import subprocess
import sys
def git(repo, *args):
return subprocess.run(
["git", "-C", repo] + list(args), check=True, capture_output=True, text=True
).stdout
def main():
repo = sys.argv[1] if len(sys.argv) > 1 else "/root/troupe-standup"
out_csv = (
sys.argv[2]
if len(sys.argv) > 2
else os.path.join(repo, "wizard-work/ledger/2026-11-05-checkin-census.csv")
)
names = git(repo, "ls-tree", "-r", "--name-only", "HEAD").splitlines()
longs = git(repo, "ls-tree", "-r", "-l", "HEAD").splitlines()
long_by_path = {}
for ln in longs:
tab = ln.find("\t")
head, path = ln[:tab], ln[tab + 1:]
tok = head.split()
sha, size = tok[2], int(tok[3])
long_by_path[path] = (size, sha)
rows = []
for p in names:
if not p.startswith("checkins/") or p == "checkins/README.md":
continue
rel = p[len("checkins/"):]
date = rel[:10]
wizard = rel[11:-3] if rel.endswith(".md") else rel[11:]
size, sha = long_by_path[p]
rows.append([date, wizard, p, size, sha])
rows.sort(key=lambda r: (r[0], r[1], r[2]))
os.makedirs(os.path.dirname(out_csv), exist_ok=True)
with open(out_csv, "w", newline="") as f:
w = csv.writer(f)
w.writerow(["date", "wizard", "path", "size_bytes", "blob_sha1"])
w.writerows(rows)
print("rows=%d" % len(rows))
print("output=%s" % out_csv)
print("sample:")
for r in rows[:3]:
print(" ", r)
if __name__ == "__main__":
main()