LRC-LIB-KEYWORDS: keyword actions count the photos they change

Rename, merge and delete answered `changed` with every change they
made, so with the keyword list it no longer meant photos (renaming a
keyword no photo has said 2). `changed` is photos again, and `listed`
counts the keyword list's changes (what Purge reports).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nathaniel Ledford
2026-10-09 14:51:26 -04:00
co-authored by Claude Opus 5.5
parent 9e1abe5a97
commit c80318667d
2 changed files with 25 additions and 8 deletions
+12 -8
View File
@@ -15,20 +15,24 @@ fn strs(p: &Value, key: &str) -> Vec<String> {
}
}
/// Commit a keyword batch; returns how many changes it made. The keyword filter follows a renamed
/// keyword and is cleared when its keyword is deleted.
/// Commit a keyword batch; returns `{changed: photos changed, listed: keyword list changes}`. The
/// keyword filter follows a renamed keyword and is cleared when its keyword is deleted.
fn commit_keywords(s: &mut Session, label: &str, op: lightcraft_catalog::Op, follow: impl Fn(&str) -> Option<String>) -> Result<Value> {
let n = match &op {
lightcraft_catalog::Op::Batch { ops } => ops.len(),
_ => 1,
use lightcraft_catalog::Op;
let (photos, listed) = match &op {
Op::Batch { ops } => {
(ops.iter().filter(|o| matches!(o, Op::SetMeta { .. })).count(), ops.iter().filter(|o| matches!(o, Op::SetKeyword { .. })).count())
}
Op::SetMeta { .. } => (1, 0),
_ => (0, 1),
};
if n > 0 {
if photos + listed > 0 {
s.commit(label, op)?;
}
if let Some(k) = s.filter.keyword.clone() {
s.filter.keyword = follow(&k);
}
Ok(json!({"changed": n}))
Ok(json!({"changed": photos, "listed": listed}))
}
/// A keyword's attributes from command params over `base`: those not given keep their value.
@@ -324,7 +328,7 @@ pub fn specs() -> Vec<CommandSpec> {
|s, _| {
let op = s.catalog.purge_unused_keywords_ops();
let r = commit_keywords(s, "Purge Unused Keywords", op, |k| Some(k.to_string()))?;
Ok(json!({"purged": r["changed"]}))
Ok(json!({"purged": r["listed"]}))
}
),
cmd!(
+13
View File
@@ -157,3 +157,16 @@ fn keywords_given_to_photos_are_stored_cleaned() {
assert_eq!(keywords_of(&s, id), ["beach", "Ärzte", "sea"]);
assert!(s.execute("keyword.info", &json!({"keyword": "beach"})).is_ok());
}
/// Rename, merge and delete say how many photos they changed, as before the keyword list: the
/// list's own changes aren't photos.
#[test]
fn keyword_actions_count_the_photos_they_change() {
let mut s = Session::with_demo();
let id = s.visible_cloned()[0].0;
s.execute("keyword.create", &json!({"name": "Weddings", "synonyms": ["marriage"]})).unwrap();
assert_eq!(s.execute("keyword.rename", &json!({"from": "Weddings", "to": "Marriages"})).unwrap()["changed"], 0);
s.execute("photo.setMeta", &json!({"ids": [id], "addKeywords": ["Marriages"]})).unwrap();
assert_eq!(s.execute("keyword.rename", &json!({"from": "Marriages", "to": "Weddings"})).unwrap()["changed"], 1);
assert_eq!(s.execute("keyword.delete", &json!({"keyword": "weddings"})).unwrap()["changed"], 1);
}