Show VERSIONS.md reason extracts in dwarf status
Parses the gen/schema log lines apply_bump() writes to VERSIONS.md and prints a truncated reason under each gen/schemaN row, so `dwarf status` answers "why does this version exist" without opening the changelog. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,17 @@ from pathlib import Path
|
||||
GEN_RE = re.compile(r"^gen(\d+)$")
|
||||
SCHEMA_RE = re.compile(r"^schema(\d+)$")
|
||||
|
||||
# Match the log lines written by apply_bump()/plan_bump_gen()/plan_bump_schema():
|
||||
# - `gen2` (kind=steps) — 2026-01-01 — reason text (by)
|
||||
# - `gen2`/`schema2` (kind=steps) — 2026-01-01 — reason text (by)
|
||||
VERSIONS_SCHEMA_LINE_RE = re.compile(
|
||||
r"^- `(?P<gen>gen\d+)`/`(?P<schema>schema\d+)` \(kind=(?P<kind>[\w-]+)\)"
|
||||
r" — \d{4}-\d{2}-\d{2} — (?P<reason>.+)$"
|
||||
)
|
||||
VERSIONS_GEN_LINE_RE = re.compile(
|
||||
r"^- `(?P<gen>gen\d+)` \(kind=(?P<kind>[\w-]+)\) — \d{4}-\d{2}-\d{2} — (?P<reason>.+)$"
|
||||
)
|
||||
|
||||
# One color per tree level in `dwarf status` output, so the eye can jump
|
||||
# straight to e.g. "all the schema rows" or "all the totals".
|
||||
_LEVEL_COLORS = {
|
||||
@@ -34,6 +45,7 @@ _LEVEL_COLORS = {
|
||||
"bucket": "\033[34m", # blue — raw/processed subtotals
|
||||
"schema": "\033[32m", # green — schemaN rows
|
||||
"root": "\033[1;35m", # bold magenta — derived/, pools/, grand total
|
||||
"reason": "\033[2m", # dim — VERSIONS.md reason extract under gen/schema rows
|
||||
}
|
||||
_RESET = "\033[0m"
|
||||
|
||||
@@ -232,6 +244,35 @@ def _referenced_parquet_count(
|
||||
return total, referenced
|
||||
|
||||
|
||||
def _parse_versions(
|
||||
versions_path: Path,
|
||||
) -> tuple[dict[tuple[str, str], str], dict[tuple[str, str, str], str]]:
|
||||
"""Read VERSIONS.md and return (gen_reasons, schema_reasons) keyed by
|
||||
(kind, gen_tag) and (kind, gen_tag, schema_tag) respectively. Later entries
|
||||
for the same key win, since VERSIONS.md is append-only and chronological."""
|
||||
gen_reasons: dict[tuple[str, str], str] = {}
|
||||
schema_reasons: dict[tuple[str, str, str], str] = {}
|
||||
if not versions_path.is_file():
|
||||
return gen_reasons, schema_reasons
|
||||
for line in versions_path.read_text().splitlines():
|
||||
line = line.strip()
|
||||
m = VERSIONS_SCHEMA_LINE_RE.match(line)
|
||||
if m:
|
||||
schema_reasons[(m["kind"], m["gen"], m["schema"])] = m["reason"]
|
||||
continue
|
||||
m = VERSIONS_GEN_LINE_RE.match(line)
|
||||
if m:
|
||||
gen_reasons[(m["kind"], m["gen"])] = m["reason"]
|
||||
return gen_reasons, schema_reasons
|
||||
|
||||
|
||||
def _truncate(text: str, width: int = 72) -> str:
|
||||
text = text.strip()
|
||||
if len(text) <= width:
|
||||
return text
|
||||
return text[: width - 1].rstrip() + "…"
|
||||
|
||||
|
||||
def _human_size(n: int) -> str:
|
||||
size = float(n)
|
||||
for unit in ("B", "KB", "MB", "GB", "TB"):
|
||||
@@ -268,12 +309,17 @@ def _row(
|
||||
return _colorize(row, level) if level else row
|
||||
|
||||
|
||||
def _reason_line(reason: str, indent: int) -> str:
|
||||
return _colorize(" " * indent + "↳ " + _truncate(reason), "reason")
|
||||
|
||||
|
||||
def print_status(root: Path) -> None:
|
||||
raw_root = root / "raw"
|
||||
if not raw_root.is_dir():
|
||||
print(f"no raw/ tree found under {root}")
|
||||
return
|
||||
manifest_referenced = _manifest_referenced_files(root / "pools")
|
||||
gen_reasons, schema_reasons = _parse_versions(root / "VERSIONS.md")
|
||||
grand_total = 0
|
||||
grand_files = 0
|
||||
for kind_dir in sorted(p for p in raw_root.iterdir() if p.is_dir()):
|
||||
@@ -316,6 +362,9 @@ def print_status(root: Path) -> None:
|
||||
kind_files += gen_files
|
||||
|
||||
print(_row(gen_tag, gen_total, indent=1, level="gen", count=gen_files))
|
||||
gen_reason = gen_reasons.get((kind, gen_tag))
|
||||
if gen_reason:
|
||||
print(_reason_line(gen_reason, indent=2))
|
||||
print(
|
||||
_row(
|
||||
"raw", raw_size, indent=2, level="bucket",
|
||||
@@ -337,6 +386,9 @@ def print_status(root: Path) -> None:
|
||||
count=s_total, referenced=s_referenced,
|
||||
)
|
||||
)
|
||||
schema_reason = schema_reasons.get((kind, gen_tag, f"schema{s}"))
|
||||
if schema_reason:
|
||||
print(_reason_line(schema_reason, indent=4))
|
||||
else:
|
||||
print(_colorize(" (none)", "schema"))
|
||||
print(_row(f"{kind} total", kind_total, indent=1, level="gen", count=kind_files))
|
||||
|
||||
Reference in New Issue
Block a user