Merge pull request #932 from vbasky/fix/894-recovery-snapshots
Keep recovery snapshots when session metadata is unreadable
This commit is contained in:
commit
b2c00d4cac
|
|
@ -572,15 +572,16 @@ pub fn scan_candidates(data_dir: &Path, skip: Option<&Path>) -> Vec<RecoveryCand
|
|||
if !dir.is_dir() || Some(dir.as_path()) == skip || !lock_is_stale(&dir) {
|
||||
continue;
|
||||
}
|
||||
let meta = fs::read(dir.join(META)).ok().and_then(|b| serde_json::from_slice::<JournalMeta>(&b).ok());
|
||||
match meta {
|
||||
Some(meta) if dir.join(SNAPSHOT).is_file() => {
|
||||
out.push(RecoveryCandidate { id: e.file_name().to_string_lossy().into_owned(), dir, meta });
|
||||
}
|
||||
_ => {
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
}
|
||||
let snap = dir.join(SNAPSHOT);
|
||||
if !snap.is_file() {
|
||||
// Empty leftover dirs (clean exit, or a crash before the first snapshot).
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
continue;
|
||||
}
|
||||
// Keep the snapshot even when session.json is missing or unreadable: the project
|
||||
// is still recoverable. Meta fields fall back to defaults.
|
||||
let meta = fs::read(dir.join(META)).ok().and_then(|b| serde_json::from_slice::<JournalMeta>(&b).ok()).unwrap_or_default();
|
||||
out.push(RecoveryCandidate { id: e.file_name().to_string_lossy().into_owned(), dir, meta });
|
||||
}
|
||||
out.sort_by(|a, b| b.meta.saved_unix.cmp(&a.meta.saved_unix).then(b.id.cmp(&a.id)));
|
||||
out
|
||||
|
|
|
|||
|
|
@ -176,6 +176,28 @@ fn auto_save_ring_rotates_and_can_save_the_project() {
|
|||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scan_keeps_snapshot_when_session_metadata_is_unreadable() {
|
||||
// #894: a stale session with a snapshot must not be deleted because session.json is missing
|
||||
// or corrupt — the recovered project would vanish from the list and the file would be gone.
|
||||
let d = temp_dir("recover-nometa");
|
||||
let root = autosave::recovery_root(&d);
|
||||
let sess = root.join("123-1");
|
||||
std::fs::create_dir_all(&sess).unwrap();
|
||||
let snap = filmcraft_format::encode(&filmcraft_project::Project::default(), false);
|
||||
std::fs::write(sess.join("snapshot.fcproj"), snap).unwrap();
|
||||
std::fs::write(sess.join("session.json"), b"not json {").unwrap();
|
||||
let found = autosave::scan_candidates(&d, None);
|
||||
assert_eq!(found.len(), 1);
|
||||
assert_eq!(found[0].id, "123-1");
|
||||
assert!(sess.join("snapshot.fcproj").is_file(), "snapshot must survive the scan");
|
||||
std::fs::remove_file(sess.join("session.json")).unwrap();
|
||||
let found = autosave::scan_candidates(&d, None);
|
||||
assert_eq!(found.len(), 1, "missing metadata still lists the snapshot");
|
||||
assert!(sess.join("snapshot.fcproj").is_file());
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn portable_marker_keeps_data_next_to_the_executable() {
|
||||
// #139: a portable install must not write to %APPDATA%.
|
||||
|
|
|
|||
Loading…
Reference in New Issue