Import: a file gone or changed since the review is probed again

The import reused the review's probes for every file it had seen, even
one deleted (or rewritten) since: such a file was added as a photo of a
file that isn't there. A cached probe is now used only while the file
is there with the same size (checked in prepare_files, on the import's
worker thread; the web's files keep their probes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nathaniel Ledford
2026-10-09 18:38:52 -04:00
co-authored by Claude Opus 5.5
parent f3a3fa6c10
commit 5a21fc9d97
2 changed files with 25 additions and 2 deletions
+11 -2
View File
@@ -850,8 +850,17 @@ impl ImportJob {
}
}
// files a preceding scan already probed are not read again (a network share is slow to read)
let cached: Vec<Option<ProbeInfo>> = todo.iter().map(|f| self.cache.remove(f)).collect();
// files a preceding scan already probed are not read again (a network share is slow to read),
// as long as they are still there, as they were: a file gone or changed since is probed again
let cached: Vec<Option<ProbeInfo>> = todo
.iter()
.map(|f| {
// (the web's files are not std::fs files: kept as probed)
self.cache
.remove(f)
.filter(|info| cfg!(target_arch = "wasm32") || std::fs::metadata(f).is_ok_and(|m| m.is_file() && m.len() == info.file_size))
})
.collect();
let missing: Vec<String> = todo.iter().zip(&cached).filter(|(_, c)| c.is_none()).map(|(f, _)| f.clone()).collect();
let progress = ScanProgress::default();
let mut fresh = probe_all(self.probe.as_ref(), &missing, &progress).into_iter();
+14
View File
@@ -1105,3 +1105,17 @@ fn folder_import_picks_up_undecodable_raw_containers_as_preview_only() {
assert!(s.catalog.photos().all(|p| p.preview_only.is_some() && p.kind == lightcraft_catalog::MediaKind::Raw && (p.width, p.height) == (40, 30)));
let _ = std::fs::remove_dir_all(&src);
}
#[test]
fn a_file_gone_since_the_import_review_is_not_imported() {
let src = temp_dir("gone-since-review");
write_png(&src.join("a.png"), 1);
write_png(&src.join("b.png"), 2);
let mut s = Session::new().with_fs();
s.execute("library.importPreview", &json!({"paths": [src.to_string_lossy()]})).unwrap();
std::fs::remove_file(src.join("b.png")).unwrap();
let r = s.execute("library.import", &json!({"paths": [src.join("a.png").to_string_lossy(), src.join("b.png").to_string_lossy()]})).unwrap();
assert_eq!((ids(&r, "imported"), ids(&r, "failed")), (1, 1), "{r}");
assert_eq!(s.catalog.len(), 1, "no photo for a file that isn't there");
let _ = std::fs::remove_dir_all(&src);
}