mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-29 20:48:33 -06:00
Synchronize Folder: background face search doesn't make a scan stale (review fix)
A scan was current only while the folder's photo records were the very same; the face search adding regions in the background replaced them, so confirming could keep failing as stale while it worked through the folder. A photo now counts as changed only when something synchronizing depends on changed: its file, its place in the library, or what a sidecar is compared with (regions aside). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
898ecee27c
commit
97e2c7ff51
@@ -238,6 +238,19 @@ pub fn scan_with(input: SyncInput, progress: &SyncProgress) -> FolderChanges {
|
||||
changes
|
||||
}
|
||||
|
||||
/// Whether a photo is the same as far as synchronizing goes: its file, its place in the library
|
||||
/// and what a sidecar is compared with. Face and pet regions found in the background meanwhile
|
||||
/// don't make a scan stale.
|
||||
fn same_for_sync(a: &Arc<Photo>, b: &Arc<Photo>) -> bool {
|
||||
if Arc::ptr_eq(a, b) {
|
||||
return true;
|
||||
}
|
||||
let meta = |p: &Photo| lightcraft_catalog::Meta { regions: Vec::new(), ..p.meta.clone() };
|
||||
(&a.source, a.deleted, a.local, a.copy_of, &a.content_hash, a.file_size, a.rating, a.flag, a.label, &a.captured, &a.edited, &a.develop)
|
||||
== (&b.source, b.deleted, b.local, b.copy_of, &b.content_hash, b.file_size, b.rating, b.flag, b.label, &b.captured, &b.edited, &b.develop)
|
||||
&& meta(a) == meta(b)
|
||||
}
|
||||
|
||||
/// The content a hash stands for: a Duplicate's own hash is the original's plus `:dup<id>`.
|
||||
fn base_hash(h: &str) -> &str {
|
||||
h.split(':').next().unwrap_or(h)
|
||||
@@ -388,7 +401,7 @@ impl Session {
|
||||
let mut then: Vec<PhotoId> = c.seen.iter().map(|p| p.id).collect();
|
||||
now.sort();
|
||||
then.sort();
|
||||
let unchanged = now == then && c.seen.iter().all(|p| self.catalog.photo(p.id).is_some_and(|q| Arc::ptr_eq(p, q)));
|
||||
let unchanged = now == then && c.seen.iter().all(|p| self.catalog.photo(p.id).is_some_and(|q| same_for_sync(p, q)));
|
||||
unchanged.then_some(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,3 +451,18 @@ fn renamed_duplicates_are_each_relinked() {
|
||||
let r = s.execute("folder.synchronize", &json!({"path": dir.path("trip")})).unwrap();
|
||||
assert_eq!(r["relinked"], 2, "{r}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn face_regions_found_meanwhile_leave_the_scan_current() {
|
||||
let dir = Scratch::new("faces");
|
||||
let mut s = library(&dir);
|
||||
write_png(&dir.path("trip/c.png"), 3);
|
||||
scan(&mut s, &dir.path("trip"));
|
||||
// background face search adds a region to a photo of the folder
|
||||
let a = s.catalog.photos().find(|p| p.file_name == "a.png").unwrap().id;
|
||||
let mut meta = s.catalog.photo(a).unwrap().meta.clone();
|
||||
meta.regions.push(lightcraft_meta::Region { rect: Default::default(), kind: lightcraft_meta::RegionKind::Face, name: None, description: None });
|
||||
s.catalog.apply(lightcraft_catalog::Op::SetMeta { id: a, meta: Box::new(meta) }).unwrap();
|
||||
let r = s.execute("folder.synchronize", &json!({"path": dir.path("trip"), "scanned": true})).unwrap();
|
||||
assert_eq!(r["imported"], 1, "{r}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user