fix(media-apply): refuse a plan row whose verb the tool does not know

read_plan's if/elif chain had no else, so any row that was not mkdir, keep
or move was dropped in silence. A plan of nothing but typos therefore
applied as a successful no-op: on 2026-11-02 a pass meant to rename two
TVShows series folders reported "applied: 0 moved" and exit 0, and the
journal was never written — nothing told the operator the plan had never
been read. An unread row is a plan bug, and every other plan bug in this
tool refuses before the first rename, so now this one does too, naming the
line and the verb.

cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb
This commit is contained in:
Frank committed 2026-11-02 09:51:53 -08:00
1 parent 4a33898a6c
commit a405c5ed35
3 files changed
+49 -5

No files matched your search

+10 -2
View File
@@ -121,14 +121,14 @@ class Journal:
def read_plan(path, root, force):
"""Plan rows: (mkdirs, keeps, moves), header dropped, all paths under root."""
mkdirs, keeps, moves = [], [], []
mkdirs, keeps, moves, bad = [], [], [], []
with open(path) as fh:
header = fh.readline()
if not header.startswith("action\t"):
raise Refuse(f"{path} is not a plan (first column is "
f"{header.split(chr(9))[0]!r}, expected 'action') —"
" regenerate it with scripts/media-plan.py")
for line in fh:
for n, line in enumerate(fh, 2):
f = line.rstrip("\n").split("\t")
if f[0] == "mkdir":
mkdirs.append(f[2])
@@ -136,6 +136,14 @@ def read_plan(path, root, force):
keeps.append(f[1])
elif f[0] == "move":
moves.append((f[1], f[2], f[3] if len(f) > 3 else ""))
else:
bad.append(f"line {n}: unknown action {f[0]!r} — this tool"
" knows mkdir, keep and move (a rename is a move)")
if bad:
# A row this tool could not read is a plan bug, and a plan bug refuses:
# silently dropping it turns a typo into a no-op run that reports success.
head = "; ".join(bad[:3])
raise Refuse(head + (f" (+{len(bad) - 3} more)" if len(bad) > 3 else ""))
if not force:
for p in mkdirs + keeps + [p for m in moves for p in m[:2]]:
if p and not (p == root or p.startswith(root + os.sep)):