From 9b2987b4a8174931e97433de4086af0bfc4ae8cb Mon Sep 17 00:00:00 2001 From: llama <100429699+iamllama@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:13:30 +0800 Subject: [PATCH] Fix numeric deck and notetype names being treated as ids when importing csv (#3748) * fallback to treating deck and notetype ids as names * add test for metadata --- rslib/src/import_export/text/csv/metadata.rs | 29 ++++++++++++++++++++ rslib/src/import_export/text/import.rs | 23 ++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/rslib/src/import_export/text/csv/metadata.rs b/rslib/src/import_export/text/csv/metadata.rs index 0c624958e..a69acfe9e 100644 --- a/rslib/src/import_export/text/csv/metadata.rs +++ b/rslib/src/import_export/text/csv/metadata.rs @@ -687,6 +687,35 @@ pub(in crate::import_export) mod test { ); } + #[test] + fn should_fallback_to_parsing_deck_ids_as_deck_names() { + let mut col = Collection::new(); + let numeric_deck_id = col.get_or_create_normal_deck("123456789").unwrap().id.0; + let numeric_deck_2_id = col + .get_or_create_normal_deck(&numeric_deck_id.to_string()) + .unwrap() + .id + .0; + + assert_eq!( + metadata!(col, "#deck:123456789\n").unwrap_deck_id(), + numeric_deck_id + ); + // parsed as id first, fallback to name after + assert_eq!( + metadata!(col, format!("#deck:{numeric_deck_id}\n")).unwrap_deck_id(), + numeric_deck_id + ); + assert_eq!( + metadata!(col, format!("#deck:{numeric_deck_2_id}\n")).unwrap_deck_id(), + numeric_deck_2_id + ); + assert_eq!( + metadata!(col, format!("#deck:1234\n")).unwrap_deck_id(), + 1 // default deck + ); + } + #[test] fn should_detect_valid_delimiters() { let mut col = Collection::new(); diff --git a/rslib/src/import_export/text/import.rs b/rslib/src/import_export/text/import.rs index 524a0c239..c16c7ceb4 100644 --- a/rslib/src/import_export/text/import.rs +++ b/rslib/src/import_export/text/import.rs @@ -167,7 +167,12 @@ impl DeckIdsByNameOrId { fn get(&self, name_or_id: &NameOrId) -> Option { match name_or_id { _ if *name_or_id == NameOrId::default() => self.default, - NameOrId::Id(id) => self.ids.get(&DeckId(*id)).copied(), + NameOrId::Id(id) => self + .ids + .get(&DeckId(*id)) + // try treating it as a numeric deck name + .or_else(|| self.names.get(&UniCase::new(id.to_string()))) + .copied(), NameOrId::Name(name) => self.names.get(&UniCase::new(name.to_string())).copied(), } } @@ -504,7 +509,13 @@ impl Note { impl Collection { pub(super) fn deck_id_by_name_or_id(&mut self, deck: &NameOrId) -> Result> { match deck { - NameOrId::Id(id) => Ok(self.get_deck(DeckId(*id))?.map(|_| DeckId(*id))), + NameOrId::Id(id) => Ok({ + match self.get_deck(DeckId(*id))?.map(|d| d.id) { + did @ Some(_) => did, + // try treating it as a numeric deck name + _ => self.get_deck_id(&id.to_string())?, + } + }), NameOrId::Name(name) => self.get_deck_id(name), } } @@ -514,7 +525,13 @@ impl Collection { notetype: &NameOrId, ) -> Result>> { match notetype { - NameOrId::Id(id) => self.get_notetype(NotetypeId(*id)), + NameOrId::Id(id) => Ok({ + match self.get_notetype(NotetypeId(*id))? { + nt @ Some(_) => nt, + // try treating it as a numeric notetype name + _ => self.get_notetype_by_name(&id.to_string())?, + } + }), NameOrId::Name(name) => self.get_notetype_by_name(name), } }