Keep a Photo's save path after its file leaves; refuse an empty download directory
check / check (push) Successful in 1m31s

A Photo now keeps the file its record was made from (the record
projection holds one membership of each file), so savePath and isLocal
still answer after a refresh removes the file.

Library.open rejects an empty downloadDirectory.

A backup clears leftover temp files in every date folder under its
directory, not only in those of the files in its scope.

placeOriginal no longer deletes what is at the save path before copying
a live photo, and the tests that depended on that are removed.

The TODO.md entry for issue 143 describes only the current layout.

Model: opus-5-5
This commit is contained in:
2026-10-01 18:45:44 +00:00
parent 60c8d5b77b
commit e2d54450e8
8 changed files with 103 additions and 91 deletions
+2 -5
View File
@@ -405,10 +405,8 @@ export const copyAtomic = async (src: string, dest: string): Promise<void> => {
// folders. `get` is given the save path and returns where the original is: a
// fetch writes it there, and a copy the cache holds is copied there. A live
// photo's image and video go beside the save path, each with its own
// extension: when they came from the cache they are copied, after removing
// whatever was at the save path (an earlier version's ZIP of the two). Then
// the JSON file naming them is written, which is what makes the live photo
// count as stored.
// extension: when they came from the cache they are copied. Then the JSON file
// naming them is written, which is what makes the live photo count as stored.
export const placeOriginal = async (
root: string,
file: EnteFile,
@@ -424,7 +422,6 @@ export const placeOriginal = async (
const path = withExtension(dest, extname(got.path));
const videoPath = withExtension(dest, extname(got.videoPath));
if (got.path !== path) {
await rm(dest, { force: true });
await copyAtomic(got.path, path);
await copyAtomic(got.videoPath, videoPath);
}