feat(media): sweep removes the folders a completed run emptied #94

Merged
dank merged 1 commits from feat/media-sweep into main 2026-10-30 20:04:24 -07:00
Owner

What

media-apply.py gains a fourth subcommand, sweep: it removes the release folders an apply emptied. The live relayout moved 8189 files and left 1675 empty husks at the library root — clutter that confuses Jellyfin's folder browser and every human reading the share.

The law it enforces

A sweep deletes only what the journal proves this run emptied:

  • a journalled move went out of the folder, or out of something under it;
  • the folder now holds nothing but empty directories;
  • no journalled destination lives beneath it (never a live target subtree);
  • it is not a folder the run created (rollback already handles those).

A folder nobody moved cannot be selected at all, so a hand-made placeholder survives untouched. Deepest-first: Extras/ is only a candidate if the journal moved files out of it too. A symlink anywhere inside disqualifies the whole subtree — the thing behind a link is not this tool's to delete. A journal whose moves belong to another --root is refused.

Every removal is journalled as rmdir, so rollback recreates the folders a sweep removed: one command undoes the whole change, moves and sweep alike.

Evidence

  • tests/media_relayout.bats — 6 new behaviour tests, written red first (sweep was an unknown subcommand), now green: dry-run writes nothing and reports the count; a content-holding folder stays; rollback restores folders and files; a second sweep says there is nothing to do; symlink guard; cross-library journal guard; idempotence.
  • ./tests/run.sh — 621 tests, all pass.
  • serverAppConfigs-docs/Dankserver/Media Relayout.md — the sweep command shape, the journal's real path (/mnt/entropy/media-relayout.jsonl, never /tmp), the Plex rescan recipe (the API answers only through its own netns), and the new law that an apply breaks Plex playback until the section is rescanned.

A sweep deletes no media file: only directories the journal proves empty.


cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb

## What `media-apply.py` gains a fourth subcommand, `sweep`: it removes the release folders an apply emptied. The live relayout moved 8189 files and left **1675 empty husks** at the library root — clutter that confuses Jellyfin's folder browser and every human reading the share. ## The law it enforces A sweep deletes only what the journal *proves this run emptied*: - a journalled `move` went out of the folder, or out of something under it; - the folder now holds nothing but empty directories; - no journalled destination lives beneath it (never a live target subtree); - it is not a folder the run created (rollback already handles those). A folder nobody moved cannot be selected at all, so a hand-made placeholder survives untouched. Deepest-first: `Extras/` is only a candidate if the journal moved files out of it too. A symlink anywhere inside disqualifies the whole subtree — the thing behind a link is not this tool's to delete. A journal whose moves belong to another `--root` is refused. Every removal is journalled as `rmdir`, so `rollback` recreates the folders a sweep removed: one command undoes the whole change, moves and sweep alike. ## Evidence - `tests/media_relayout.bats` — 6 new behaviour tests, written red first (`sweep` was an unknown subcommand), now green: dry-run writes nothing and reports the count; a content-holding folder stays; rollback restores folders *and* files; a second sweep says there is nothing to do; symlink guard; cross-library journal guard; idempotence. - `./tests/run.sh` — 621 tests, all pass. - `serverAppConfigs-docs/Dankserver/Media Relayout.md` — the sweep command shape, the journal's real path (`/mnt/entropy/media-relayout.jsonl`, never `/tmp`), the Plex rescan recipe (the API answers only through its own netns), and the new law that an apply breaks Plex playback until the section is rescanned. A sweep deletes no media file: only directories the journal proves empty. --- cwd: /home/blank/.omp/wt/wt-20261030-163847-6d1fc1f · session: 01a18f2e-18b1-7573-bcd5-ac99636f8bcb
dank added 1 commit 2026-10-30 20:03:55 -07:00
An apply leaves every release folder it emptied standing where it was: the
live library run left 1675 husks at the root. sweep takes the same journal
and deletes only folders it can prove this run emptied - a journalled move
out of the folder or something under it, nothing but empty directories left,
no journalled destination beneath it, not a folder the run created. A folder
nobody moved cannot be selected at all, so a hand-made placeholder survives,
and a symlink anywhere inside disqualifies the subtree. Every rmdir is
journalled, so rollback recreates what a sweep removed.
dank merged commit dd76fcf5d4 into main 2026-10-30 20:04:24 -07:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dank/serverAppConfigs#94