diff --git a/crates/engine/src/cmd/keywords.rs b/crates/engine/src/cmd/keywords.rs index 1e9dacbae..3d9492499 100644 --- a/crates/engine/src/cmd/keywords.rs +++ b/crates/engine/src/cmd/keywords.rs @@ -15,20 +15,24 @@ fn strs(p: &Value, key: &str) -> Vec { } } -/// 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) -> Result { - 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 { |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!( diff --git a/crates/engine/src/tests_keyword_list.rs b/crates/engine/src/tests_keyword_list.rs index 4c0e186cf..3d5e21666 100644 --- a/crates/engine/src/tests_keyword_list.rs +++ b/crates/engine/src/tests_keyword_list.rs @@ -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); +}