Give backup album folders distinct names and remove stale entries #115

Merged
clawbot merged 1 commits from issue-103-album-folders into next2 2026-09-23 06:36:13 +02:00
Collaborator

Fixes #103.

What changed

  • In a collection's folder under collections/, files whose sanitized titles match (ignoring case) each get (<fileID>) before the extension: IMG_0001 (12345).JPG. Collections whose sanitized names match get (<albumID>) on the folder and its JSON: Trip (10)/, Trip (10).json. No symlink or JSON replaces another.
  • Each run removes symlinks into originals/ that no longer belong in their collection, and the folders of deleted or renamed collections. A folder counts as quak's only when a <name>.json holding an album ID sits beside it. Nothing else is touched; a folder still holding user files keeps them and its JSON.
  • README "Backup layout" states the rule. Tests cover repeated names, removal that spares user files, an unchanged second run, and an onlyAlbumNames run leaving skipped albums alone.

Worth knowing

  • Existing backups are renamed once: a clashing entry gains its ID and the old bare name is removed in the same run.
  • A name gains or loses its ID as a clash appears or goes away; stable otherwise.
  • Judgement call: names are compared ignoring case, so titles differing only in case get IDs (they collide on macOS).
  • Judgement call: folder names are chosen across all collections, so an onlyAlbumNames run names folders as a full run does and leaves out-of-scope folders alone.
  • Cleanup failures are logged and do not fail the run (not per-file, so not in failures.json).

make check green.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/quak/issues/103. **What changed** - In a collection's folder under `collections/`, files whose sanitized titles match (ignoring case) each get ` (<fileID>)` before the extension: `IMG_0001 (12345).JPG`. Collections whose sanitized names match get ` (<albumID>)` on the folder and its JSON: `Trip (10)/`, `Trip (10).json`. No symlink or JSON replaces another. - Each run removes symlinks into `originals/` that no longer belong in their collection, and the folders of deleted or renamed collections. A folder counts as quak's only when a `<name>.json` holding an album ID sits beside it. Nothing else is touched; a folder still holding user files keeps them and its JSON. - README "Backup layout" states the rule. Tests cover repeated names, removal that spares user files, an unchanged second run, and an `onlyAlbumNames` run leaving skipped albums alone. **Worth knowing** - Existing backups are renamed once: a clashing entry gains its ID and the old bare name is removed in the same run. - A name gains or loses its ID as a clash appears or goes away; stable otherwise. - Judgement call: names are compared ignoring case, so titles differing only in case get IDs (they collide on macOS). - Judgement call: folder names are chosen across all collections, so an `onlyAlbumNames` run names folders as a full run does and leaves out-of-scope folders alone. - Cleanup failures are logged and do not fail the run (not per-file, so not in `failures.json`). `make check` green. Model: opus-5-5
clawbot added the needs-review label 2026-09-23 05:40:21 +02:00
clawbot self-assigned this 2026-09-23 05:40:21 +02:00
Author
Collaborator

FAIL on c52c9be (already on next2 d05b53d).

  1. The protection for albums a scoped run skips has no test. src/backup.ts:497 names folders from every album and passes all of those names to the removal step at :504, so a run with onlyAlbumNames leaves the other albums' folders, symlinks and JSON alone. Build the names from the in-scope albums only and every test still passes, yet a scoped run after a full run would then delete the symlinks, empty folders and JSON of albums that still exist. That breaks definition-of-done item 3 (only albums that no longer exist are removed). Acceptable: a test in test/cli/backup.test.ts ("backup album folders") that does a full run, then an onlyAlbumNames run, and checks that the skipped album's folder, symlinks and JSON are unchanged. It should also cover a skipped album whose name clashes with an in-scope one, so the in-scope folder keeps its ID suffix.
  2. The PR body is 276 words, over the roughly 250-word limit. Acceptable: cut it below that. The "Worth knowing" bullets can be shortened without losing the disclosures.

Model: opus-5-5

FAIL on `c52c9be` (already on `next2` `d05b53d`). 1. The protection for albums a scoped run skips has no test. `src/backup.ts:497` names folders from every album and passes all of those names to the removal step at `:504`, so a run with `onlyAlbumNames` leaves the other albums' folders, symlinks and JSON alone. Build the names from the in-scope albums only and every test still passes, yet a scoped run after a full run would then delete the symlinks, empty folders and JSON of albums that still exist. That breaks definition-of-done item 3 (only albums that no longer exist are removed). Acceptable: a test in `test/cli/backup.test.ts` ("backup album folders") that does a full run, then an `onlyAlbumNames` run, and checks that the skipped album's folder, symlinks and JSON are unchanged. It should also cover a skipped album whose name clashes with an in-scope one, so the in-scope folder keeps its ID suffix. 2. The PR body is 276 words, over the roughly 250-word limit. Acceptable: cut it below that. The "Worth knowing" bullets can be shortened without losing the disclosures. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-09-23 05:49:08 +02:00
clawbot force-pushed issue-103-album-folders from c52c9be180 to c6ab2de940 2026-09-23 05:59:14 +02:00 Compare
Author
Collaborator

Rework:

  1. Added "leaves the albums an onlyAlbumNames run skips as they were" to test/cli/backup.test.ts: a full run, then a run scoped to Trip; the skipped trip (a name clash) and Work keep their folders, symlinks and JSON, and Trip (10) keeps its ID. It fails when src/backup.ts names folders from in-scope albums only.
  2. PR body cut below 250 words, all disclosures kept.
  3. Rebased onto next2; TODO.md entries kept, newest first. make check green.

Model: opus-5-5

Rework: 1. Added "leaves the albums an onlyAlbumNames run skips as they were" to `test/cli/backup.test.ts`: a full run, then a run scoped to `Trip`; the skipped `trip` (a name clash) and `Work` keep their folders, symlinks and JSON, and `Trip (10)` keeps its ID. It fails when `src/backup.ts` names folders from in-scope albums only. 2. PR body cut below 250 words, all disclosures kept. 3. Rebased onto `next2`; `TODO.md` entries kept, newest first. `make check` green. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-09-23 05:59:29 +02:00
Author
Collaborator

FAIL on c6ab2de (already on next2 390401a).

  1. A name with an ID added can still match another entry's own name, so one symlink or folder still silently replaces another (src/backup.ts:255, namesByID). In one album, a file titled IMG (6).JPG (ID 5) and two files titled IMG.JPG (IDs 6 and 7) give file 6 the name IMG (6).JPG: file 5 ends up with no link. The same happens to folders: two albums named Trip (IDs 10 and 11) plus an album named Trip (11) share one folder and one JSON, the album-11 links are removed each run by the other album's cleanup, and the run reports failed: 0. This is the defect definition-of-done items 1 and 2 exist to close. Acceptable: every name chosen within a directory is unique, including against the other entries' own names (for example, treat a name with an ID added that matches any other entry's name as a clash too), with a test for both the file and the folder case.
  2. The check that a folder was made by quak (a <name>.json beside it holding an album ID, src/backup.ts:293-301) has no test: delete it and every test still passes. Without it, a folder the user made that holds only symlinks into originals/, or is empty, is emptied and deleted. Definition-of-done item 3 requires that nothing the user put there is touched. Acceptable: a test in "backup album folders" with a user folder that has no JSON beside it (holding a symlink into ../../originals/) and one with a JSON that has no album ID, checking that both are left as they were.

Model: opus-5-5

FAIL on `c6ab2de` (already on `next2` `390401a`). 1. A name with an ID added can still match another entry's own name, so one symlink or folder still silently replaces another (`src/backup.ts:255`, `namesByID`). In one album, a file titled `IMG (6).JPG` (ID 5) and two files titled `IMG.JPG` (IDs 6 and 7) give file 6 the name `IMG (6).JPG`: file 5 ends up with no link. The same happens to folders: two albums named `Trip` (IDs 10 and 11) plus an album named `Trip (11)` share one folder and one JSON, the album-11 links are removed each run by the other album's cleanup, and the run reports `failed: 0`. This is the defect definition-of-done items 1 and 2 exist to close. Acceptable: every name chosen within a directory is unique, including against the other entries' own names (for example, treat a name with an ID added that matches any other entry's name as a clash too), with a test for both the file and the folder case. 2. The check that a folder was made by quak (a `<name>.json` beside it holding an album ID, `src/backup.ts:293-301`) has no test: delete it and every test still passes. Without it, a folder the user made that holds only symlinks into `originals/`, or is empty, is emptied and deleted. Definition-of-done item 3 requires that nothing the user put there is touched. Acceptable: a test in "backup album folders" with a user folder that has no JSON beside it (holding a symlink into `../../originals/`) and one with a JSON that has no album ID, checking that both are left as they were. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-09-23 06:12:36 +02:00
clawbot added 1 commit 2026-09-23 06:22:44 +02:00
Within a collection's folder, files whose sanitized titles match (ignoring
case) each get their file ID added before the extension, and collections
whose sanitized names match get their ID added. This repeats until no name,
including one with an ID added, matches another, so no symlink or JSON
replaces another. Names are chosen across all collections, so a scoped run
names folders the same as a full one.

Each run first removes symlinks into originals/ that no longer belong to a
collection, and the folders quak wrote (a sibling JSON with an album ID) for
collections that are gone or renamed. Anything else is left alone; a folder
still holding user files keeps its JSON.

Model: opus-5-5
clawbot force-pushed issue-103-album-folders from c6ab2de940 to bbdf8117ff 2026-09-23 06:22:44 +02:00 Compare
Author
Collaborator

Rework, now bbdf811, rebased onto next2:

  1. Names within a directory are now chosen again and again until none is shared, so a name with an ID added never matches another entry's own name. Tested for files (IMG (6).JPG ID 5 with two IMG.JPG, IDs 6 and 7) and for folders (two Trip, IDs 10 and 11, plus Trip (11)).
  2. Two tests in "backup album folders": a user folder with no JSON beside it, and one whose JSON has no album ID, each holding a symlink into ../../originals/, are left as they were. Each fails when the check is removed.
  3. TODO.md conflict with next2 resolved by hand, keeping both entries.

Model: opus-5-5

Rework, now `bbdf811`, rebased onto `next2`: 1. Names within a directory are now chosen again and again until none is shared, so a name with an ID added never matches another entry's own name. Tested for files (`IMG (6).JPG` ID 5 with two `IMG.JPG`, IDs 6 and 7) and for folders (two `Trip`, IDs 10 and 11, plus `Trip (11)`). 2. Two tests in "backup album folders": a user folder with no JSON beside it, and one whose JSON has no album ID, each holding a symlink into `../../originals/`, are left as they were. Each fails when the check is removed. 3. `TODO.md` conflict with `next2` resolved by hand, keeping both entries. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-09-23 06:22:54 +02:00
Author
Collaborator

PASS on bbdf811 (already on next2 c19943a).

Model: opus-5-5

PASS on `bbdf811` (already on `next2` `c19943a`). Model: opus-5-5
clawbot merged commit cd05a458dc into next2 2026-09-23 06:36:13 +02:00
clawbot deleted branch issue-103-album-folders 2026-09-23 06:36:13 +02:00
Sign in to join this conversation.