A live photo's default names fit, and no cut name starts with a dot
check / check (push) Waiting to run

`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
This commit is contained in:
2026-10-18 17:05:49 +00:00
parent fd40714a6d
commit e03e99b486
11 changed files with 284 additions and 107 deletions
+22 -19
View File
@@ -687,24 +687,26 @@ Without `--out`, `get` writes the file to the working directory under its title,
and `get-thumb` writes the thumbnail there under `thumb_` followed by the title,
each with unsafe characters replaced. A name over 255 bytes, which most file
systems refuse, is cut short between two characters before its extension, so the
extension is kept whenever it fits.
extension is kept whenever it fits. An extension too long to leave room for the
name's first character is cut short too, so the name never starts with a dot.
`get` and `get-thumb` resolve the file by ID directly, so `--collection` is
accepted for backward compatibility but ignored. For a live photo, `get` writes
its image and its video, each named after the title with its own extension, as
Ente's clients name them (`IMG_0001.heic` and `IMG_0001.mov`). With
`--out PATH`, the image is written to `PATH` and the video beside it, with
`PATH`'s name and the video's extension; a `PATH` with the video's extension is
refused. `backup-metadata --exif` (alias `--all`) additionally fetches each
file's original through the cache and records, from it or a live photo's image,
its XMP metadata, its EXIF metadata and, for a JPEG, its dimensions. EXIF is
read with [exifreader](https://github.com/mattiasw/ExifReader) from any image
format it reads, JPEG, HEIC/HEIF, AVIF, PNG and WebP among them. The record's
`exif` field is exifreader's EXIF tag output: each tag by name, with its
`value`, `description` and `computed` value. An EXIF block exifreader finds but
reads no tag from is recorded, base64, as `exifRaw`, with the reason in
`exifError`. `collections`, `files`, `backup`, `helper list-missing-thumbnails`
and `helper fix-missing-thumbnails` take `--json` for machine-readable output.
Ente's clients name them (`IMG_0001.heic` and `IMG_0001.mov`), and each name is
cut short as above once its own extension is in it. With `--out PATH`, the image
is written to `PATH` and the video beside it, with `PATH`'s name and the video's
extension; a `PATH` with the video's extension is refused.
`backup-metadata --exif` (alias `--all`) additionally fetches each file's
original through the cache and records, from it or a live photo's image, its XMP
metadata, its EXIF metadata and, for a JPEG, its dimensions. EXIF is read with
[exifreader](https://github.com/mattiasw/ExifReader) from any image format it
reads, JPEG, HEIC/HEIF, AVIF, PNG and WebP among them. The record's `exif` field
is exifreader's EXIF tag output: each tag by name, with its `value`,
`description` and `computed` value. An EXIF block exifreader finds but reads no
tag from is recorded, base64, as `exifRaw`, with the reason in `exifError`.
`collections`, `files`, `backup`, `helper list-missing-thumbnails` and
`helper fix-missing-thumbnails` take `--json` for machine-readable output.
`backup --verify` also hashes the originals already in the backup and replaces
any that do not match the content hash Ente records; one it cannot replace stays
@@ -864,11 +866,12 @@ 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 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.
just far enough that it fits. When a symlink's extension leaves no room for the
ID and the first character of the name, the extension is cut short, and the part
before the ID keeps that character and any bytes the 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