46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""insert_row.py <ledger.tsv> '<c>|<path>|<verdict>|<rc>|<secs>|<note>|<blob>|<host>'
|
|
|
|
Insert one already-measured row into a ledger, in path order, replacing any
|
|
existing row for the same path.
|
|
|
|
Why this exists (Q150): a `--merge` run removes the rows it is about to re-take
|
|
BEFORE it takes them, so a run killed mid-flight leaves the ledger without the
|
|
rows it had not rewritten. The reading for that path was taken this tick and is
|
|
in the transcript; dropping it would either lose a measurement or force a
|
|
second 30-minute HTTP pass over the same bytes. The row goes back exactly as
|
|
measured -- fields are '|'-separated so no tab has to survive shell quoting.
|
|
|
|
A row whose rc column is empty (TIMEOUT/ERROR/MISSING) is written with an empty
|
|
fifth... fourth column, which is the format emit() itself writes.
|
|
"""
|
|
import sys
|
|
|
|
ledger, spec = sys.argv[1], sys.argv[2]
|
|
cells = spec.split("|")
|
|
if len(cells) != 8:
|
|
sys.exit("insert_row: need 8 '|'-separated cells, got %d" % len(cells))
|
|
if "\t" in spec:
|
|
sys.exit("insert_row: refusing -- spec contains a literal tab")
|
|
path = cells[1]
|
|
|
|
rows, out = 0, []
|
|
for line in open(ledger, encoding="utf-8"):
|
|
line = line.rstrip("\n")
|
|
if line.startswith("#") or not line:
|
|
out.append(line)
|
|
continue
|
|
rows += 1
|
|
if line.split("\t")[1] == path:
|
|
continue # the row being replaced
|
|
out.append(line)
|
|
|
|
seen = [i for i, l in enumerate(out) if not l.startswith("#") and l]
|
|
keep = [l for l in out if not l.startswith("#")]
|
|
head = [l for l in out if l.startswith("#")]
|
|
keep.append("\t".join(cells))
|
|
keep.sort(key=lambda l: l.split("\t")[1])
|
|
open(ledger, "w", encoding="utf-8").write("\n".join(head + keep) + "\n")
|
|
print("inserted: %s" % path)
|
|
print("rows: %d -> %d" % (rows, len(keep)))
|