Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cabeba249 |
@@ -815,11 +815,12 @@ directory would have the name of another collection's JSON, again ignoring case,
|
||||
gets its ID added as well: beside an album `x`, whose JSON is `x.json`, an album
|
||||
named `x.json` gets the directory `x.json (12)/`. A name too long for a file
|
||||
name, which most file systems limit to 255 bytes, gets its ID added too. A name
|
||||
with its ID added is cut short between two characters, just far enough that it
|
||||
fits: first the part before the ID, and once nothing is left of that, a
|
||||
symlink's extension. A collection's directory name also leaves room for the
|
||||
`.json` its JSON adds. IDs never change, so a name stays the same from run to
|
||||
run until such a clash appears or goes away.
|
||||
with its ID added is cut short between two characters in the part before the ID,
|
||||
just far enough that it fits. When a symlink'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. A collection's directory name also leaves room for
|
||||
the `.json` its JSON adds. IDs never change, so a name stays the same from run
|
||||
to run until such a clash appears or goes away.
|
||||
|
||||
A collection whose directory or JSON cannot be written, such as one whose
|
||||
directory name is taken by a file you put in `collections/`, does not stop the
|
||||
|
||||
+6
-4
@@ -276,10 +276,12 @@ const rebuildSymlink = (linkPath: string, target: string): void => {
|
||||
// case (two names that differ only in case are one entry on a case-insensitive
|
||||
// file system), or it is too long for a file name; then it gets ` (<id>)`,
|
||||
// right before the extension when `beforeExtension` is set. To fit, the part
|
||||
// before the ID is cut short as far as it must be, and once nothing is left of
|
||||
// it, so is the extension. With `withJSON`, each entry also has the JSON file
|
||||
// `<name>.json` beside it, as an album does: a name then leaves room for
|
||||
// `.json`, and one that is another entry's JSON name gets its ID added too.
|
||||
// before the ID is cut short as far as it must be. When the 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. With `withJSON`, each
|
||||
// entry also has the JSON file `<name>.json` beside it, as an album does: a
|
||||
// name then leaves room for `.json`, and one that is another entry's JSON name
|
||||
// gets its ID added too.
|
||||
// Two names with different IDs added never match, but one can match another
|
||||
// entry's own name (`IMG (6).JPG`), so this repeats until no name is shared.
|
||||
// IDs are stable, so the names are too.
|
||||
|
||||
+13
-5
@@ -1737,27 +1737,35 @@ describe("backup album folders", () => {
|
||||
expect(readLedger(outDir).files["5"]).toMatchObject({ attempts: 1 });
|
||||
});
|
||||
|
||||
// The extension of this title is 303 bytes, so it leaves no room for the
|
||||
// ID: nothing is left of the name before the ID, and the extension is cut
|
||||
// short after it. The extension holds a "-", so the original is saved
|
||||
// with `.bin`, a name that fits.
|
||||
// The extensions of these titles leave no room for the ID, so each is cut
|
||||
// short and the name before the ID keeps only the bytes that cut leaves
|
||||
// over. File 1's extension is 303 bytes and is cut to 251, which leaves
|
||||
// none. File 2's is 271 bytes and is cut to 250, since "€" takes three
|
||||
// bytes, which leaves one, for the "a". Neither extension is only letters
|
||||
// and digits, so both originals are saved with `.bin`, a name that fits.
|
||||
it("cuts the extension of a title short when it leaves no room for the ID", async () => {
|
||||
const outDir = join(root, "backup");
|
||||
const lib = libraryOf([
|
||||
{
|
||||
collection: collection(10, "Trip"),
|
||||
files: [file(1, 10, `a.${"L".repeat(300)}-x`)],
|
||||
files: [
|
||||
file(1, 10, `a.${"L".repeat(300)}-x`),
|
||||
file(2, 10, `a.${"€".repeat(90)}`),
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const result = await runBackup(lib, { downloadDirectory: outDir });
|
||||
|
||||
const link = ` (1).${"L".repeat(250)}`;
|
||||
const link2 = `a (2).${"€".repeat(83)}`;
|
||||
expect(Buffer.byteLength(link)).toBe(255);
|
||||
expect(Buffer.byteLength(link2)).toBe(255);
|
||||
expect(result.failed).toBe(0);
|
||||
expect(tree(outDir)).toEqual([
|
||||
"Trip/",
|
||||
`Trip/${link} -> ${linkTo("1.bin")}`,
|
||||
`Trip/${link2} -> ${linkTo("2.bin")}`,
|
||||
"Trip.json",
|
||||
]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user