An album whose folder cannot be made no longer stops the backup (closes #197) #204

Merged
clawbot merged 1 commits from issue-197-album-folder-failures into next 2026-10-16 05:23:28 +02:00
Collaborator

An album name the server sends could make that album's folder or JSON fail to be written, which ended quak backup before the later albums and failures.json, on every run.

  • The work for one album (folder, links, JSON) runs inside one try. A failure prints FAILED album <name>: <reason> and lists the album's ID in failedAlbums, a new BackupResult field, also shown in --json; quak backup then exits 1. The other albums and failures.json are still written.
  • uniqueNames also adds an album's ID when its folder would have another album's JSON name, ignoring case: beside x, the album x.json gets x.json (11)/.
  • A folder name over 250 bytes (its JSON adds .json) or a link name over 255 bytes gets the ID and is cut short between two characters, by shortenToBytes in src/filename.ts.
  • README "Backup layout" states both naming rules and failedAlbums; the exit-code table and the lib.backup entry mention them.

Not visible in the diff: apart from its call to uniqueNames, the album loop is only indented into the try. A link's ID always goes right before its extension, so two names with IDs added never match. When a link's extension alone leaves no room for the ID, the extension is cut short and the name before the ID keeps only the bytes that cut leaves over.

Judgement call: only the album whose folder would clash gets its ID, not the album whose JSON it would be, as the plan comment says.

#197

Model: opus-5-5

An album name the server sends could make that album's folder or JSON fail to be written, which ended `quak backup` before the later albums and `failures.json`, on every run. - The work for one album (folder, links, JSON) runs inside one `try`. A failure prints `FAILED album <name>: <reason>` and lists the album's ID in `failedAlbums`, a new `BackupResult` field, also shown in `--json`; `quak backup` then exits 1. The other albums and `failures.json` are still written. - `uniqueNames` also adds an album's ID when its folder would have another album's JSON name, ignoring case: beside `x`, the album `x.json` gets `x.json (11)/`. - A folder name over 250 bytes (its JSON adds `.json`) or a link name over 255 bytes gets the ID and is cut short between two characters, by `shortenToBytes` in `src/filename.ts`. - README "Backup layout" states both naming rules and `failedAlbums`; the exit-code table and the `lib.backup` entry mention them. Not visible in the diff: apart from its call to `uniqueNames`, the album loop is only indented into the `try`. A link's ID always goes right before its extension, so two names with IDs added never match. When a link's extension alone leaves no room for the ID, the extension is cut short and the name before the ID keeps only the bytes that cut leaves over. Judgement call: only the album whose folder would clash gets its ID, not the album whose JSON it would be, as the plan comment says. https://git.eeqj.de/sneak/quak/issues/197 Model: opus-5-5
clawbot added the needs-review label 2026-10-16 01:58:55 +02:00
clawbot self-assigned this 2026-10-16 01:58:59 +02:00
Author
Collaborator
  1. src/backup.ts, uniqueNames: no test reaches the branch in withID that cuts a link name short as a whole when its extension alone leaves no room for (ID). A change that breaks it would go unnoticed, and such a title would again fail its link on every run. Acceptable: a test in test/cli/backup.test.ts with a title like a. followed by 300 letters and -x (an extension that is not only letters and digits, so the original is still stored) that checks the link is made, carries the ID and fits in 255 bytes.

Model: opus-5-5

1. `src/backup.ts`, `uniqueNames`: no test reaches the branch in `withID` that cuts a link name short as a whole when its extension alone leaves no room for ` (ID)`. A change that breaks it would go unnoticed, and such a title would again fail its link on every run. Acceptable: a test in `test/cli/backup.test.ts` with a title like `a.` followed by 300 letters and `-x` (an extension that is not only letters and digits, so the original is still stored) that checks the link is made, carries the ID and fits in 255 bytes. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-16 02:18:05 +02:00
clawbot force-pushed issue-197-album-folder-failures from dfc61172a4 to 5abf93824d 2026-10-16 02:31:24 +02:00 Compare
Author
Collaborator

Finding 1 of #204 (comment): added a test to test/cli/backup.test.ts that backs up the title a. + 300 letters + -x. It checks that the link is made and named a. + 249 letters + (1), which is exactly 255 bytes, that it points at the original saved as .bin, and that nothing failed. With the line that drops the extension taken out of withID, this test fails and no other does. withID itself is unchanged.

Model: opus-5-5

Finding 1 of https://git.eeqj.de/sneak/quak/pulls/204#issuecomment-144335: added a test to `test/cli/backup.test.ts` that backs up the title `a.` + 300 letters + `-x`. It checks that the link is made and named `a.` + 249 letters + ` (1)`, which is exactly 255 bytes, that it points at the original saved as `.bin`, and that nothing failed. With the line that drops the extension taken out of `withID`, this test fails and no other does. `withID` itself is unchanged. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-16 02:31:28 +02:00
Author
Collaborator
  1. src/backup.ts, uniqueNames: two names that both have an ID added can still be the same when one title's extension alone leaves no room for the ID. In an album with two files titled x. + 245 Q + (2) (IDs 1 and 3) and one titled x (1). + 250 Q + - (ID 2), files 1 and 2 both get the link x (1). + 245 Q + (2). The second link replaces the first, so file 1 has no link in the album, nothing is recorded as failed, and every run makes the link twice. The function's comment says the loop repeats until no name is shared. Acceptable: no two names uniqueNames returns are equal, ignoring case, whatever the titles are (for example, keep the ID right before the extension and cut the extension itself short when it leaves no room), with a test for this case in test/cli/backup.test.ts.

  2. test/cli/backup.test.ts, the comment above const ok: it says the next three tests end with the album "ok", but the third test after it ("cuts a title short, extension and all, ...") does not use that album, and the fourth does. Acceptable: the comment matches the tests that follow it, for example by moving that test after the three that use ok.

  3. TODO.md, Next Step: it says three bugs are open and names #196, #198 and #199, but #205 (the follow-on of this change, which starts once it is on next) and #206 are open bugs as well. Acceptable: Next Step names the bugs that are open when the PR is pushed.

Model: opus-5-5

1. `src/backup.ts`, `uniqueNames`: two names that both have an ID added can still be the same when one title's extension alone leaves no room for the ID. In an album with two files titled `x.` + 245 `Q` + ` (2)` (IDs 1 and 3) and one titled `x (1).` + 250 `Q` + `-` (ID 2), files 1 and 2 both get the link `x (1).` + 245 `Q` + ` (2)`. The second link replaces the first, so file 1 has no link in the album, nothing is recorded as failed, and every run makes the link twice. The function's comment says the loop repeats until no name is shared. Acceptable: no two names `uniqueNames` returns are equal, ignoring case, whatever the titles are (for example, keep the ID right before the extension and cut the extension itself short when it leaves no room), with a test for this case in `test/cli/backup.test.ts`. 2. `test/cli/backup.test.ts`, the comment above `const ok`: it says the next three tests end with the album "ok", but the third test after it ("cuts a title short, extension and all, ...") does not use that album, and the fourth does. Acceptable: the comment matches the tests that follow it, for example by moving that test after the three that use `ok`. 3. `TODO.md`, Next Step: it says three bugs are open and names https://git.eeqj.de/sneak/quak/issues/196, https://git.eeqj.de/sneak/quak/issues/198 and https://git.eeqj.de/sneak/quak/issues/199, but https://git.eeqj.de/sneak/quak/issues/205 (the follow-on of this change, which starts once it is on `next`) and https://git.eeqj.de/sneak/quak/issues/206 are open bugs as well. Acceptable: Next Step names the bugs that are open when the PR is pushed. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-16 02:49:45 +02:00
clawbot force-pushed issue-197-album-folder-failures from 5abf93824d to 0fbc6f4776 2026-10-16 03:06:44 +02:00 Compare
Author
Collaborator

Findings of #204 (comment):

  1. uniqueNames now always puts the ID right before the extension. To fit, the name before the ID is cut short first, and once nothing is left of it, so is the extension. Its comment and README "Backup layout" say so. A new test in test/cli/backup.test.ts backs up the three titles from the finding and checks that all three links are made under different names. The test for a title whose extension leaves no room now expects (1). + 250 L.
  2. The two tests that do not use the album ok now come after the three that do, so the comment above const ok is right.
  3. Next Step names #196, #198, #199, #205 and #206, the bugs open at this push, and keeps the line about #187.

Model: opus-5-5

Findings of https://git.eeqj.de/sneak/quak/pulls/204#issuecomment-144389: 1. `uniqueNames` now always puts the ID right before the extension. To fit, the name before the ID is cut short first, and once nothing is left of it, so is the extension. Its comment and README "Backup layout" say so. A new test in `test/cli/backup.test.ts` backs up the three titles from the finding and checks that all three links are made under different names. The test for a title whose extension leaves no room now expects ` (1).` + 250 `L`. 2. The two tests that do not use the album `ok` now come after the three that do, so the comment above `const ok` is right. 3. Next Step names https://git.eeqj.de/sneak/quak/issues/196, https://git.eeqj.de/sneak/quak/issues/198, https://git.eeqj.de/sneak/quak/issues/199, https://git.eeqj.de/sneak/quak/issues/205 and https://git.eeqj.de/sneak/quak/issues/206, the bugs open at this push, and keeps the line about https://git.eeqj.de/sneak/quak/issues/187. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-16 03:07:08 +02:00
clawbot force-pushed issue-197-album-folder-failures from 0fbc6f4776 to 4388e799db 2026-10-16 03:29:55 +02:00 Compare
Author
Collaborator
  1. test/cli/backup.test.ts, the tests of the naming rule in uniqueNames (src/backup.ts): no test has a name at the byte limit. Every long name tested is far over it, so nothing checks that a 255-byte title or a 250-byte album name is kept as it is, or that a 256-byte title or a 251-byte album name gets the ID and fits. An off-by-one in the length check in uniqueNames would go unnoticed and bring back the failure on every run for a name one byte over the limit (for an album, a JSON name of 256 bytes). Acceptable: tests for those four names, at least one of them with a multi-byte character at the cut.

  2. Commit message and PR body: the commit message body is about 135 words and the PR body about 275, over the limits of about 120 and about 250. Acceptable: both cut to within the limits.

Model: opus-5-5

1. `test/cli/backup.test.ts`, the tests of the naming rule in `uniqueNames` (`src/backup.ts`): no test has a name at the byte limit. Every long name tested is far over it, so nothing checks that a 255-byte title or a 250-byte album name is kept as it is, or that a 256-byte title or a 251-byte album name gets the ID and fits. An off-by-one in the length check in `uniqueNames` would go unnoticed and bring back the failure on every run for a name one byte over the limit (for an album, a JSON name of 256 bytes). Acceptable: tests for those four names, at least one of them with a multi-byte character at the cut. 2. Commit message and PR body: the commit message body is about 135 words and the PR body about 275, over the limits of about 120 and about 250. Acceptable: both cut to within the limits. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-16 03:53:30 +02:00
clawbot force-pushed issue-197-album-folder-failures from 4388e799db to c0b9c37726 2026-10-16 04:06:47 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-16 04:06:54 +02:00
Author
Collaborator

Findings of #204 (comment):

  1. A new test in test/cli/backup.test.ts backs up a 255-byte title and a 250-byte album name, kept as they are, and a 256-byte title and a 251-byte album name, which get the ID and fit, with the cut falling inside an "é" in both; uniqueNames needed no change, and the test fails if its length check is off by one byte in either direction.
  2. The commit message body is cut to under 120 words and the PR body to under 250, each ending Model: opus-5-5.

Model: opus-5-5

Findings of https://git.eeqj.de/sneak/quak/pulls/204#issuecomment-144536: 1. A new test in `test/cli/backup.test.ts` backs up a 255-byte title and a 250-byte album name, kept as they are, and a 256-byte title and a 251-byte album name, which get the ID and fit, with the cut falling inside an "é" in both; `uniqueNames` needed no change, and the test fails if its length check is off by one byte in either direction. 2. The commit message body is cut to under 120 words and the PR body to under 250, each ending `Model: opus-5-5`. Model: opus-5-5
Author
Collaborator
  1. README.md "Backup layout", the comment above uniqueNames in src/backup.ts, and the PR body say that a name with its ID added is cut short first before the ID, and its extension only once nothing is left of that. withID does it the other way round when the extension alone leaves no room: it cuts the extension first, then gives the name before the ID whatever bytes that cut leaves over, up to 3 when the cut falls inside a multi-byte character. So with both cut, part of the name before the ID is kept. The title a. followed by 90 "€" gets the link a (1). followed by 83 "€", where those texts promise (1). followed by 83 "€". Acceptable: the code and the three texts agree. Either nothing before the ID is kept once the extension is cut, or the texts say that an extension that alone leaves no room is cut first and the name before the ID gets what is left.

Model: opus-5-5

1. `README.md` "Backup layout", the comment above `uniqueNames` in `src/backup.ts`, and the PR body say that a name with its ID added is cut short first before the ID, and its extension only once nothing is left of that. `withID` does it the other way round when the extension alone leaves no room: it cuts the extension first, then gives the name before the ID whatever bytes that cut leaves over, up to 3 when the cut falls inside a multi-byte character. So with both cut, part of the name before the ID is kept. The title `a.` followed by 90 "€" gets the link `a (1).` followed by 83 "€", where those texts promise ` (1).` followed by 83 "€". Acceptable: the code and the three texts agree. Either nothing before the ID is kept once the extension is cut, or the texts say that an extension that alone leaves no room is cut first and the name before the ID gets what is left. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-16 04:31:13 +02:00
clawbot force-pushed issue-197-album-folder-failures from c0b9c37726 to 3cabeba249 2026-10-16 04:47:09 +02:00 Compare
Author
Collaborator

Finding of #204 (comment):

  1. withID is unchanged. README "Backup layout", the comment above uniqueNames and the PR body now say that when a link's extension alone leaves no room for the ID, the extension is cut short and the part before the ID keeps only the bytes that cut leaves over. The test "cuts the extension of a title short when it leaves no room for the ID" in test/cli/backup.test.ts now also backs up the title a. followed by 90 "€" and expects the 255-byte link a (2). followed by 83 "€". That file has ID 2 because the test's other title already has ID 1.

Model: opus-5-5

Finding of https://git.eeqj.de/sneak/quak/pulls/204#issuecomment-144617: 1. `withID` is unchanged. README "Backup layout", the comment above `uniqueNames` and the PR body now say that when a link's extension alone leaves no room for the ID, the extension is cut short and the part before the ID keeps only the bytes that cut leaves over. The test "cuts the extension of a title short when it leaves no room for the ID" in `test/cli/backup.test.ts` now also backs up the title `a.` followed by 90 "€" and expects the 255-byte link `a (2).` followed by 83 "€". That file has ID 2 because the test's other title already has ID 1. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-16 04:48:18 +02:00
clawbot added 1 commit 2026-10-16 05:03:11 +02:00
Each album's folder, links and JSON are written inside one try. A failure
prints `FAILED album <name>: <reason>`, lists the album's ID in the new
`failedAlbums` of the result and of `--json`, and makes `quak backup` exit 1;
the other albums and `failures.json` are still written.

An album whose folder would have another album's JSON name, ignoring case,
gets its ID. A name over 255 bytes (250 for a folder, which leaves room for
`.json`) gets the ID and is cut short between two characters by
`shortenToBytes` in `src/filename.ts`. A link's ID goes right before its
extension.

Apart from its call to `uniqueNames`, the album loop is only indented into
the try.

Model: opus-5-5
clawbot force-pushed issue-197-album-folder-failures from 3cabeba249 to 4cda4c88ae 2026-10-16 05:03:11 +02:00 Compare
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit 960a7ce8a6 into next 2026-10-16 05:23:28 +02:00
clawbot deleted branch issue-197-album-folder-failures 2026-10-16 05:23:28 +02:00
Sign in to join this conversation.