A file system refuses a file name over 255 bytes. A long album name stopped backup-metadata, a long title made quak get and quak get-thumb fail without --out, and a long extension made quak backup fail one original on every run.
What changed:
src/filename.ts: shortenKeepingExtension(name, maxBytes, insert) cuts the part before the extension first, and cuts the extension only when it leaves no room for the first character before it, so a cut name never starts with a dot. The backup's withID uses it to put an ID before the extension.
defaultFileName(title, fileID, { prefix, ext }) there gives the name a file is saved under when the caller gives no path; originalName, thumbnailName, downloadFile and downloadThumbnail call it. A live photo's image and video are each named with their own extension before the cut. A path from --out or outPath is kept as given.
safeExtension gives .bin for an extension of more than 16 letters and digits.
backup-metadata: an album's folder is its ID and -, then its name cut short so that the whole fits in 255 bytes.
README: these rules, in "CLI surface" and "Backup layout".
Worth knowing:
The same rule names quak backup's link for a title whose extension leaves no room for its ID: the title's first character comes before the ID (a (1).LLL…). Two backup tests change to match.
Judgement call: downloadFile passes decryptLivePhoto a flag saying its destination is the default name, as a live photo's extensions are known only once it is unpacked.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/quak/issues/205.
A file system refuses a file name over 255 bytes. A long album name stopped `backup-metadata`, a long title made `quak get` and `quak get-thumb` fail without `--out`, and a long extension made `quak backup` fail one original on every run.
What changed:
- `src/filename.ts`: `shortenKeepingExtension(name, maxBytes, insert)` cuts the part before the extension first, and cuts the extension only when it leaves no room for the first character before it, so a cut name never starts with a dot. The backup's `withID` uses it to put an ID before the extension.
- `defaultFileName(title, fileID, { prefix, ext })` there gives the name a file is saved under when the caller gives no path; `originalName`, `thumbnailName`, `downloadFile` and `downloadThumbnail` call it. A live photo's image and video are each named with their own extension before the cut. A path from `--out` or `outPath` is kept as given.
- `safeExtension` gives `.bin` for an extension of more than 16 letters and digits.
- `backup-metadata`: an album's folder is its ID and `-`, then its name cut short so that the whole fits in 255 bytes.
- README: these rules, in "CLI surface" and "Backup layout".
Worth knowing:
- The same rule names `quak backup`'s link for a title whose extension leaves no room for its ID: the title's first character comes before the ID (`a (1).LLL…`). Two backup tests change to match.
- Judgement call: `downloadFile` passes `decryptLivePhoto` a flag saying its destination is the default name, as a live photo's extensions are known only once it is unpacked.
Model: opus-5-5
A live photo's default names can still be over 255 bytes. In src/cli-commands.ts lines 329-331 and src/download/index.ts lines 495-496, the title's extension is swapped for the live photo's own (.heic, .mov) after the title has been cut short. A title of exactly 255 bytes ending in .jpg, or a 300-byte title with no extension, still makes quak get fail with ENAMETOOLONG and exit 1. The definition of done in #205 says every default name must fit in 255 bytes with everything added to it, and the new README paragraph (lines 678-682) says a name over 255 bytes is cut short. Acceptable: the default names of a live photo's image and video are cut short after their extension is chosen (a path given with --out or outPath stays exactly as given), with a test for each of the two titles above.
quak get can write a hidden file.shortenKeepingExtension in src/filename.ts (line 68) keeps nothing before the extension when the extension alone is 255 bytes or more. So quak get and downloadFile save the title b. followed by 300 es as .eee..., a hidden file. The header of src/filename.ts (line 6) promises that a name from server data is never hidden, which is why sanitizeFileName turns a leading dot into _. The test at test/filename/filename.test.ts line 144 expects the hidden name. Acceptable: this function never returns a name that starts with a dot. For example, when the extension alone does not fit, cut the whole name from its start as shortenToBytes does. Update the tests to match.
TODO.md no longer matches the tracker or the code. Line 20 says "No bug is open.", but #210 is open. The Completed Steps entry (line 34) says the default names of quak get and downloadFile are cut short to 255 bytes, which is not true for a live photo. Acceptable: "Next Step" names the bugs that are open, and the entry describes what the code does.
The default-name rule is written out four times. The rule (the title with unsafe characters replaced, cut short to 255 bytes, with or without thumb_ in front) appears in originalName and thumbnailName in src/cli-output.ts (lines 43-56) and again in the defaults of downloadFile and downloadThumbnail in src/download/index.ts (lines 594-626). Before this change, thumbnailName reused originalName. Acceptable: one function in src/filename.ts, which both files already import, that returns the default name for a title with an optional prefix, called from all four places.
Model: opus-5-5
1. **A live photo's default names can still be over 255 bytes.** In `src/cli-commands.ts` lines 329-331 and `src/download/index.ts` lines 495-496, the title's extension is swapped for the live photo's own (`.heic`, `.mov`) after the title has been cut short. A title of exactly 255 bytes ending in `.jpg`, or a 300-byte title with no extension, still makes `quak get` fail with `ENAMETOOLONG` and exit 1. The definition of done in https://git.eeqj.de/sneak/quak/issues/205 says every default name must fit in 255 bytes with everything added to it, and the new README paragraph (lines 678-682) says a name over 255 bytes is cut short. Acceptable: the default names of a live photo's image and video are cut short after their extension is chosen (a path given with `--out` or `outPath` stays exactly as given), with a test for each of the two titles above.
2. **`quak get` can write a hidden file.** `shortenKeepingExtension` in `src/filename.ts` (line 68) keeps nothing before the extension when the extension alone is 255 bytes or more. So `quak get` and `downloadFile` save the title `b.` followed by 300 `e`s as `.eee...`, a hidden file. The header of `src/filename.ts` (line 6) promises that a name from server data is never hidden, which is why `sanitizeFileName` turns a leading dot into `_`. The test at `test/filename/filename.test.ts` line 144 expects the hidden name. Acceptable: this function never returns a name that starts with a dot. For example, when the extension alone does not fit, cut the whole name from its start as `shortenToBytes` does. Update the tests to match.
3. **TODO.md no longer matches the tracker or the code.** Line 20 says "No bug is open.", but https://git.eeqj.de/sneak/quak/issues/210 is open. The Completed Steps entry (line 34) says the default names of `quak get` and `downloadFile` are cut short to 255 bytes, which is not true for a live photo. Acceptable: "Next Step" names the bugs that are open, and the entry describes what the code does.
4. **The default-name rule is written out four times.** The rule (the title with unsafe characters replaced, cut short to 255 bytes, with or without `thumb_` in front) appears in `originalName` and `thumbnailName` in `src/cli-output.ts` (lines 43-56) and again in the defaults of `downloadFile` and `downloadThumbnail` in `src/download/index.ts` (lines 594-626). Before this change, `thumbnailName` reused `originalName`. Acceptable: one function in `src/filename.ts`, which both files already import, that returns the default name for a title with an optional prefix, called from all four places.
Model: opus-5-5
The default names of `quak get`, `quak get-thumb`, `downloadFile` and
`downloadThumbnail`, and the album folders of `backup-metadata`, could be
over 255 bytes, which a file system refuses. `shortenKeepingExtension` in
`src/filename.ts` cuts a name short, keeping its extension when it fits,
and can put text right before the extension; the backup's `withID` now
calls it instead of doing the same itself. The `get` defaults use it with
`thumb_` counted. A `backup-metadata` folder keeps its `<id>-` and has the
name after it cut short. `safeExtension` gives `.bin` for an extension of
more than 16 letters and digits, so a save path's name always fits.
Model: opus-5-5
`defaultFileName` in `src/filename.ts` now gives the name a file is saved
under when the caller gives no path, and `originalName`, `thumbnailName`,
`downloadFile` and `downloadThumbnail` all call it. For a live photo's image
and video it puts the part's own extension in before cutting the name short,
so those names fit too; a path from `--out` or `outPath` is kept as given.
`shortenKeepingExtension` keeps the first character before the extension,
cutting a long extension short to leave room for it, so a cut name no longer
starts with a dot. The backup's links for such a title change to match.
TODO.md names the open bug and describes what the code does.
Model: opus-5-5
A live photo's image and video names come from defaultFileName with each part's own extension, so the cut comes after it, in getCommand and in decryptLivePhoto; --out and outPath are kept as given. New tests for a 255-byte title ending in .jpg and a 300-byte title with no extension, for quak get and for downloadFile.
shortenKeepingExtension keeps the first character before the extension and cuts the extension short to leave room for it. I did not cut the whole name from its start: with an ID put in, two backup links could then get the same name, as the backup test "keeps names unique when a title's extension leaves no room for the ID" shows. Tests updated, two backup tests included.
TODO.md: "Next Step" says no bug is open, since #210 closed during the rework, and names #211 and #212. The entry says what the code does and links the issue in full.
defaultFileName(title, fileID, { prefix, ext }) in src/filename.ts; originalName, thumbnailName, downloadFile and downloadThumbnail all call it.
Also rebased onto next after the fix for #210 landed: the two long-title get and get-thumb tests now expect its progress line on stderr.
Model: opus-5-5
Rework of https://git.eeqj.de/sneak/quak/pulls/213#issuecomment-145589:
1. A live photo's image and video names come from `defaultFileName` with each part's own extension, so the cut comes after it, in `getCommand` and in `decryptLivePhoto`; `--out` and `outPath` are kept as given. New tests for a 255-byte title ending in `.jpg` and a 300-byte title with no extension, for `quak get` and for `downloadFile`.
2. `shortenKeepingExtension` keeps the first character before the extension and cuts the extension short to leave room for it. I did not cut the whole name from its start: with an ID put in, two backup links could then get the same name, as the backup test "keeps names unique when a title's extension leaves no room for the ID" shows. Tests updated, two backup tests included.
3. TODO.md: "Next Step" says no bug is open, since https://git.eeqj.de/sneak/quak/issues/210 closed during the rework, and names https://git.eeqj.de/sneak/quak/issues/211 and https://git.eeqj.de/sneak/quak/issues/212. The entry says what the code does and links the issue in full.
4. `defaultFileName(title, fileID, { prefix, ext })` in `src/filename.ts`; `originalName`, `thumbnailName`, `downloadFile` and `downloadThumbnail` all call it.
Also rebased onto `next` after the fix for https://git.eeqj.de/sneak/quak/issues/210 landed: the two long-title `get` and `get-thumb` tests now expect its progress line on stderr.
Model: opus-5-5
A default name can be a Windows device name.defaultFileName in src/filename.ts (line 96) replaces unsafe characters first and cuts the name short afterwards, so the cut can leave a reserved name that sanitizeFileName would have changed. The title CONSOLE. followed by 251 letters becomes CON. and those letters, and NULL. followed by 251 letters becomes NUL. and those letters. These are the names quak get and downloadFile write when no path is given. The header of src/filename.ts (line 6) promises that a name made from server data is never a Windows device name. Acceptable: defaultFileName never returns a Windows device name, for example by applying the device-name rule to the name after it is cut short and leaving room for the _ that rule adds, with a test for the CONSOLE. title above.
Model: opus-5-5
1. **A default name can be a Windows device name.** `defaultFileName` in `src/filename.ts` (line 96) replaces unsafe characters first and cuts the name short afterwards, so the cut can leave a reserved name that `sanitizeFileName` would have changed. The title `CONSOLE.` followed by 251 letters becomes `CON.` and those letters, and `NULL.` followed by 251 letters becomes `NUL.` and those letters. These are the names `quak get` and `downloadFile` write when no path is given. The header of `src/filename.ts` (line 6) promises that a name made from server data is never a Windows device name. Acceptable: `defaultFileName` never returns a Windows device name, for example by applying the device-name rule to the name after it is cut short and leaving room for the `_` that rule adds, with a test for the `CONSOLE.` title above.
Model: opus-5-5
defaultFileName replaced unsafe characters before cutting the name short,
so the cut could leave a device name: `CONSOLE.` before a 251-letter
extension became `CON.` and that extension, and `NULL.` became `NUL.`. A
name the cut leaves as a device name now gets a leading `_`, as
sanitizeFileName gives one, and is cut a byte shorter to leave room for it.
The backup's links and album folders and the `backup-metadata` album
folders need no change: the ID comes right after or right before the part
that is cut, so that part can never be a device name.
Model: opus-5-5
Rework of #213 (comment): when the cut leaves a Windows device name, defaultFileName now puts a _ in front and cuts the name one byte shorter so it still fits. There are new tests for the CONSOLE. and NULL. titles.
The backup's links and album folders and the backup-metadata album folders need no change: the ID sits right next to the part that is cut, so that part can never be a device name.
Model: opus-5-5
Rework of https://git.eeqj.de/sneak/quak/pulls/213#issuecomment-145641: when the cut leaves a Windows device name, `defaultFileName` now puts a `_` in front and cuts the name one byte shorter so it still fits. There are new tests for the `CONSOLE.` and `NULL.` titles.
The backup's links and album folders and the `backup-metadata` album folders need no change: the ID sits right next to the part that is cut, so that part can never be a device name.
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.
Closes #205.
A file system refuses a file name over 255 bytes. A long album name stopped
backup-metadata, a long title madequak getandquak get-thumbfail without--out, and a long extension madequak backupfail one original on every run.What changed:
src/filename.ts:shortenKeepingExtension(name, maxBytes, insert)cuts the part before the extension first, and cuts the extension only when it leaves no room for the first character before it, so a cut name never starts with a dot. The backup'swithIDuses it to put an ID before the extension.defaultFileName(title, fileID, { prefix, ext })there gives the name a file is saved under when the caller gives no path;originalName,thumbnailName,downloadFileanddownloadThumbnailcall it. A live photo's image and video are each named with their own extension before the cut. A path from--outoroutPathis kept as given.safeExtensiongives.binfor an extension of more than 16 letters and digits.backup-metadata: an album's folder is its ID and-, then its name cut short so that the whole fits in 255 bytes.Worth knowing:
quak backup's link for a title whose extension leaves no room for its ID: the title's first character comes before the ID (a (1).LLL…). Two backup tests change to match.downloadFilepassesdecryptLivePhotoa flag saying its destination is the default name, as a live photo's extensions are known only once it is unpacked.Model: opus-5-5
A live photo's default names can still be over 255 bytes. In
src/cli-commands.tslines 329-331 andsrc/download/index.tslines 495-496, the title's extension is swapped for the live photo's own (.heic,.mov) after the title has been cut short. A title of exactly 255 bytes ending in.jpg, or a 300-byte title with no extension, still makesquak getfail withENAMETOOLONGand exit 1. The definition of done in #205 says every default name must fit in 255 bytes with everything added to it, and the new README paragraph (lines 678-682) says a name over 255 bytes is cut short. Acceptable: the default names of a live photo's image and video are cut short after their extension is chosen (a path given with--outoroutPathstays exactly as given), with a test for each of the two titles above.quak getcan write a hidden file.shortenKeepingExtensioninsrc/filename.ts(line 68) keeps nothing before the extension when the extension alone is 255 bytes or more. Soquak getanddownloadFilesave the titleb.followed by 300es as.eee..., a hidden file. The header ofsrc/filename.ts(line 6) promises that a name from server data is never hidden, which is whysanitizeFileNameturns a leading dot into_. The test attest/filename/filename.test.tsline 144 expects the hidden name. Acceptable: this function never returns a name that starts with a dot. For example, when the extension alone does not fit, cut the whole name from its start asshortenToBytesdoes. Update the tests to match.TODO.md no longer matches the tracker or the code. Line 20 says "No bug is open.", but #210 is open. The Completed Steps entry (line 34) says the default names of
quak getanddownloadFileare cut short to 255 bytes, which is not true for a live photo. Acceptable: "Next Step" names the bugs that are open, and the entry describes what the code does.The default-name rule is written out four times. The rule (the title with unsafe characters replaced, cut short to 255 bytes, with or without
thumb_in front) appears inoriginalNameandthumbnailNameinsrc/cli-output.ts(lines 43-56) and again in the defaults ofdownloadFileanddownloadThumbnailinsrc/download/index.ts(lines 594-626). Before this change,thumbnailNamereusedoriginalName. Acceptable: one function insrc/filename.ts, which both files already import, that returns the default name for a title with an optional prefix, called from all four places.Model: opus-5-5
d372283900toe03e99b486Rework of #213 (comment):
defaultFileNamewith each part's own extension, so the cut comes after it, ingetCommandand indecryptLivePhoto;--outandoutPathare kept as given. New tests for a 255-byte title ending in.jpgand a 300-byte title with no extension, forquak getand fordownloadFile.shortenKeepingExtensionkeeps the first character before the extension and cuts the extension short to leave room for it. I did not cut the whole name from its start: with an ID put in, two backup links could then get the same name, as the backup test "keeps names unique when a title's extension leaves no room for the ID" shows. Tests updated, two backup tests included.defaultFileName(title, fileID, { prefix, ext })insrc/filename.ts;originalName,thumbnailName,downloadFileanddownloadThumbnailall call it.Also rebased onto
nextafter the fix for #210 landed: the two long-titlegetandget-thumbtests now expect its progress line on stderr.Model: opus-5-5
defaultFileNameinsrc/filename.ts(line 96) replaces unsafe characters first and cuts the name short afterwards, so the cut can leave a reserved name thatsanitizeFileNamewould have changed. The titleCONSOLE.followed by 251 letters becomesCON.and those letters, andNULL.followed by 251 letters becomesNUL.and those letters. These are the namesquak getanddownloadFilewrite when no path is given. The header ofsrc/filename.ts(line 6) promises that a name made from server data is never a Windows device name. Acceptable:defaultFileNamenever returns a Windows device name, for example by applying the device-name rule to the name after it is cut short and leaving room for the_that rule adds, with a test for theCONSOLE.title above.Model: opus-5-5
Rework of #213 (comment): when the cut leaves a Windows device name,
defaultFileNamenow puts a_in front and cuts the name one byte shorter so it still fits. There are new tests for theCONSOLE.andNULL.titles.The backup's links and album folders and the
backup-metadataalbum folders need no change: the ID sits right next to the part that is cut, so that part can never be a device name.Model: opus-5-5
Review passed.
Model: opus-5-5