Back up from a copy that decrypted even outside a run's albums; README wording
A file whose copy in an album in scope does not decrypt is now backed up from a copy that decrypted in any album, not only one in scope; with no such copy it is still recorded as failed. The README now says the exit code stays at 1 until the server sends a copy that decrypts or deletes it, and that only a run without --json prints the FAILED album line. StoredMetadata.undecryptable is required, like the other fields. Model: opus-5-5
This commit is contained in:
@@ -136,11 +136,12 @@ matters.
|
|||||||
|
|
||||||
After a `1`, the next run fetches each missing original again, fetches the ML
|
After a `1`, the next run fetches each missing original again, fetches the ML
|
||||||
data that is not cached, and rebuilds the album links. A file or album quak
|
data that is not cached, and rebuilds the album links. A file or album quak
|
||||||
could not decrypt keeps the exit code at `1` until the server's copy changes
|
could not decrypt keeps the exit code at `1` until the server sends a copy that
|
||||||
(see "Backup layout"). An original that a `--verify` run could not read, or put
|
decrypts, or deletes it (see "Backup layout"). An original that a `--verify` run
|
||||||
back with bytes that still do not match, stays at its save path. Only a later
|
could not read, or put back with bytes that still do not match, stays at its
|
||||||
`--verify` run checks it again: a run without `--verify` leaves it as it is and
|
save path. Only a later `--verify` run checks it again: a run without `--verify`
|
||||||
takes the file out of `failures.json`, so that run can exit 0.
|
leaves it as it is and takes the file out of `failures.json`, so that run can
|
||||||
|
exit 0.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -749,7 +750,7 @@ into `failures.json` with an empty title, since its title is encrypted too, and
|
|||||||
an error that starts `could not be decrypted:` and gives the reason. A file in
|
an error that starts `could not be decrypted:` and gives the reason. A file in
|
||||||
two albums is backed up as usual if its copy in the other album decrypted. An
|
two albums is backed up as usual if its copy in the other album decrypted. An
|
||||||
album the library could not decrypt has no name quak can read and no files it
|
album the library could not decrypt has no name quak can read and no files it
|
||||||
can list. Each run prints one line for it,
|
can list. A run without `--json` prints one line for it,
|
||||||
`FAILED album <id>: could not be decrypted: <reason>`, and `--json` and the
|
`FAILED album <id>: could not be decrypted: <reason>`, and `--json` and the
|
||||||
`BackupResult` list its ID in `undecryptableAlbums`. Every other file is backed
|
`BackupResult` list its ID in `undecryptableAlbums`. Every other file is backed
|
||||||
up. Either kind keeps the exit code at 1, run after run, until the server sends
|
up. Either kind keeps the exit code at 1, run after run, until the server sends
|
||||||
|
|||||||
+15
-13
@@ -609,9 +609,9 @@ const runLockedBackup = async (
|
|||||||
|
|
||||||
// What the library could not decrypt. An album is logged by its ID, as
|
// What the library could not decrypt. An album is logged by its ID, as
|
||||||
// its name is not known, so a run limited to some albums logs it too. A
|
// its name is not known, so a run limited to some albums logs it too. A
|
||||||
// file in an album in scope is recorded as failed, with an empty title as
|
// file in an album in scope is backed up from a copy of it in another
|
||||||
// its metadata is not known, unless a copy of it in another album
|
// album that decrypted, even an album out of scope. With no such copy it
|
||||||
// decrypted.
|
// is recorded as failed, with an empty title as its metadata is not known.
|
||||||
const scope = new Set(collections.map((c) => c.id));
|
const scope = new Set(collections.map((c) => c.id));
|
||||||
const undecryptableAlbums: number[] = [];
|
const undecryptableAlbums: number[] = [];
|
||||||
for (const record of lib.undecryptable()) {
|
for (const record of lib.undecryptable()) {
|
||||||
@@ -619,16 +619,18 @@ const runLockedBackup = async (
|
|||||||
if (record.fileID === undefined) {
|
if (record.fileID === undefined) {
|
||||||
log(`FAILED album ${record.collectionID}: ${error}`);
|
log(`FAILED album ${record.collectionID}: ${error}`);
|
||||||
undecryptableAlbums.push(record.collectionID);
|
undecryptableAlbums.push(record.collectionID);
|
||||||
} else if (
|
} else if (scope.has(record.collectionID)) {
|
||||||
scope.has(record.collectionID) &&
|
const copies = memberships.get(record.fileID);
|
||||||
!memberships.has(record.fileID)
|
if (copies) {
|
||||||
) {
|
distinct.set(record.fileID, representative(copies));
|
||||||
recordFailure(
|
} else {
|
||||||
record.fileID,
|
recordFailure(
|
||||||
"",
|
record.fileID,
|
||||||
collectionName.get(record.collectionID) ?? "",
|
"",
|
||||||
new Error(error),
|
collectionName.get(record.collectionID) ?? "",
|
||||||
);
|
new Error(error),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ interface StoredMetadata {
|
|||||||
collectionsSinceTime: Microseconds;
|
collectionsSinceTime: Microseconds;
|
||||||
collections: StoredCollection[];
|
collections: StoredCollection[];
|
||||||
files: StoredFile[];
|
files: StoredFile[];
|
||||||
undecryptable?: Undecryptable[];
|
undecryptable: Undecryptable[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const encodeKey = (key: Uint8Array): string =>
|
const encodeKey = (key: Uint8Array): string =>
|
||||||
|
|||||||
Reference in New Issue
Block a user