One album or file quak cannot decrypt no longer stops a refresh or a backup (closes #181) #188
@@ -136,11 +136,12 @@ matters.
|
||||
|
||||
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
|
||||
could not decrypt keeps the exit code at `1` until the server's copy changes
|
||||
(see "Backup layout"). An original that a `--verify` run could not read, or put
|
||||
back with bytes that still do not match, stays at its save path. Only a later
|
||||
`--verify` run checks it again: a run without `--verify` leaves it as it is and
|
||||
takes the file out of `failures.json`, so that run can exit 0.
|
||||
could not decrypt keeps the exit code at `1` until the server sends a copy that
|
||||
decrypts, or deletes it (see "Backup layout"). An original that a `--verify` run
|
||||
could not read, or put back with bytes that still do not match, stays at its
|
||||
save path. Only a later `--verify` run checks it again: a run without `--verify`
|
||||
leaves it as it is and takes the file out of `failures.json`, so that run can
|
||||
exit 0.
|
||||
|
||||
## 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
|
||||
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
|
||||
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
|
||||
`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
|
||||
|
||||
+15
-13
@@ -609,9 +609,9 @@ const runLockedBackup = async (
|
||||
|
||||
// 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
|
||||
// file in an album in scope is recorded as failed, with an empty title as
|
||||
// its metadata is not known, unless a copy of it in another album
|
||||
// decrypted.
|
||||
// file in an album in scope is backed up from a copy of it in another
|
||||
// album that decrypted, even an album out of scope. With no such copy it
|
||||
// is recorded as failed, with an empty title as its metadata is not known.
|
||||
const scope = new Set(collections.map((c) => c.id));
|
||||
const undecryptableAlbums: number[] = [];
|
||||
for (const record of lib.undecryptable()) {
|
||||
@@ -619,16 +619,18 @@ const runLockedBackup = async (
|
||||
if (record.fileID === undefined) {
|
||||
log(`FAILED album ${record.collectionID}: ${error}`);
|
||||
undecryptableAlbums.push(record.collectionID);
|
||||
} else if (
|
||||
scope.has(record.collectionID) &&
|
||||
!memberships.has(record.fileID)
|
||||
) {
|
||||
recordFailure(
|
||||
record.fileID,
|
||||
"",
|
||||
collectionName.get(record.collectionID) ?? "",
|
||||
new Error(error),
|
||||
);
|
||||
} else if (scope.has(record.collectionID)) {
|
||||
const copies = memberships.get(record.fileID);
|
||||
if (copies) {
|
||||
distinct.set(record.fileID, representative(copies));
|
||||
} else {
|
||||
recordFailure(
|
||||
record.fileID,
|
||||
"",
|
||||
collectionName.get(record.collectionID) ?? "",
|
||||
new Error(error),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ interface StoredMetadata {
|
||||
collectionsSinceTime: Microseconds;
|
||||
collections: StoredCollection[];
|
||||
files: StoredFile[];
|
||||
undecryptable?: Undecryptable[];
|
||||
undecryptable: Undecryptable[];
|
||||
}
|
||||
|
||||
const encodeKey = (key: Uint8Array): string =>
|
||||
|
||||
Reference in New Issue
Block a user