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.
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
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
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
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.
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.
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
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.
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.
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
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.
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
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.
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
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
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
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
An album name the server sends could make that album's folder or JSON fail to be written, which ended
quak backupbefore the later albums andfailures.json, on every run.try. A failure printsFAILED album <name>: <reason>and lists the album's ID infailedAlbums, a newBackupResultfield, also shown in--json;quak backupthen exits 1. The other albums andfailures.jsonare still written.uniqueNamesalso adds an album's ID when its folder would have another album's JSON name, ignoring case: besidex, the albumx.jsongetsx.json (11)/..json) or a link name over 255 bytes gets the ID and is cut short between two characters, byshortenToBytesinsrc/filename.ts.failedAlbums; the exit-code table and thelib.backupentry mention them.Not visible in the diff: apart from its call to
uniqueNames, the album loop is only indented into thetry. 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
src/backup.ts,uniqueNames: no test reaches the branch inwithIDthat 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 intest/cli/backup.test.tswith a title likea.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
dfc61172a4to5abf93824dFinding 1 of #204 (comment): added a test to
test/cli/backup.test.tsthat backs up the titlea.+ 300 letters +-x. It checks that the link is made and nameda.+ 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 ofwithID, this test fails and no other does.withIDitself is unchanged.Model: opus-5-5
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 titledx.+ 245Q+(2)(IDs 1 and 3) and one titledx (1).+ 250Q+-(ID 2), files 1 and 2 both get the linkx (1).+ 245Q+(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 namesuniqueNamesreturns 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 intest/cli/backup.test.ts.test/cli/backup.test.ts, the comment aboveconst 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 useok.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 onnext) 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
5abf93824dto0fbc6f4776Findings of #204 (comment):
uniqueNamesnow 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 intest/cli/backup.test.tsbacks 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).+ 250L.oknow come after the three that do, so the comment aboveconst okis right.Model: opus-5-5
0fbc6f4776to4388e799dbtest/cli/backup.test.ts, the tests of the naming rule inuniqueNames(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 inuniqueNameswould 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.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
4388e799dbtoc0b9c37726Findings of #204 (comment):
test/cli/backup.test.tsbacks 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;uniqueNamesneeded no change, and the test fails if its length check is off by one byte in either direction.Model: opus-5-5.Model: opus-5-5
README.md"Backup layout", the comment aboveuniqueNamesinsrc/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.withIDdoes 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 titlea.followed by 90 "€" gets the linka (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
c0b9c37726to3cabeba249Finding of #204 (comment):
withIDis unchanged. README "Backup layout", the comment aboveuniqueNamesand 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" intest/cli/backup.test.tsnow also backs up the titlea.followed by 90 "€" and expects the 255-byte linka (2).followed by 83 "€". That file has ID 2 because the test's other title already has ID 1.Model: opus-5-5
3cabeba249to4cda4c88aeReview passed.
Model: opus-5-5