From 08791e24fc5f0d1aad2fd41c1d77df288d0bf05a Mon Sep 17 00:00:00 2001 From: RumovZ Date: Fri, 8 Apr 2022 18:12:37 +0200 Subject: [PATCH] Add import_cards(), import_revlog() --- .../src/import_export/package/apkg/import.rs | 67 ++++++++++++++++--- rslib/src/storage/card/mod.rs | 7 ++ 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/rslib/src/import_export/package/apkg/import.rs b/rslib/src/import_export/package/apkg/import.rs index 56df56e51..fd8232756 100644 --- a/rslib/src/import_export/package/apkg/import.rs +++ b/rslib/src/import_export/package/apkg/import.rs @@ -5,8 +5,7 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, fs::File, - io::{self}, - mem, + io, mem, sync::Arc, }; @@ -40,6 +39,7 @@ struct Context<'a> { remapped_notes: HashMap, remapped_decks: HashMap, remapped_deck_configs: HashMap, + remapped_cards: HashMap, data: ExchangeData, usn: Usn, /// Map of source media files, that do not already exist in the target. @@ -97,12 +97,7 @@ impl Collection { let archive = ZipArchive::new(file)?; let mut ctx = Context::new(archive, self, search, with_scheduling)?; - ctx.prepare_media()?; - ctx.import_notetypes()?; - ctx.import_notes()?; - ctx.import_deck_configs()?; - ctx.import_decks()?; - ctx.copy_media()?; + ctx.import()?; Ok(()) } @@ -152,11 +147,23 @@ impl<'a> Context<'a> { remapped_notes: HashMap::new(), remapped_decks: HashMap::new(), remapped_deck_configs: HashMap::new(), + remapped_cards: HashMap::new(), used_media_entries: HashMap::new(), normalize_notes, }) } + fn import(&mut self) -> Result<()> { + self.prepare_media()?; + self.import_notetypes()?; + self.import_notes()?; + self.import_deck_configs()?; + self.import_decks()?; + self.import_cards()?; + self.import_revlog()?; + self.copy_media() + } + fn prepare_media(&mut self) -> Result<()> { let existing_sha1s = self.target_col.all_existing_sha1s()?; for mut entry in extract_media_entries(&Meta::new_legacy(), &mut self.archive)? { @@ -392,6 +399,50 @@ impl<'a> Context<'a> { .get_deck_by_name(deck.name.as_native_str()) } + fn import_cards(&mut self) -> Result<()> { + let existing = self.target_col.storage.all_cards_as_nid_and_ord()?; + for mut card in mem::take(&mut self.data.cards) { + if self.conflicting_notes.contains(&card.note_id) { + continue; + } + self.remap_note_id(&mut card); + if existing.contains(&(card.note_id, card.template_idx)) { + // TODO: maybe update + continue; + } + self.remap_deck_id(&mut card); + // TODO: adjust collection-relative due times + // TODO: remove cards from filtered decks + let old_id = mem::take(&mut card.id); + self.target_col.add_card(&mut card)?; + self.remapped_cards.insert(old_id, card.id); + } + Ok(()) + } + + fn remap_note_id(&self, card: &mut Card) { + if let Some(nid) = self.remapped_notes.get(&card.note_id) { + card.note_id = *nid; + } + } + + fn remap_deck_id(&self, card: &mut Card) { + if let Some(did) = self.remapped_decks.get(&card.deck_id) { + card.deck_id = *did; + } + } + + fn import_revlog(&mut self) -> Result<()> { + for mut entry in mem::take(&mut self.data.revlog) { + if let Some(cid) = self.remapped_cards.get(&entry.cid) { + entry.cid = *cid; + entry.usn = self.usn; + self.target_col.add_revlog_entry_undoable(entry)?; + } + } + Ok(()) + } + fn copy_media(&mut self) -> Result<()> { for (used, entry) in self.used_media_entries.values() { if *used { diff --git a/rslib/src/storage/card/mod.rs b/rslib/src/storage/card/mod.rs index 37617711d..6176490b5 100644 --- a/rslib/src/storage/card/mod.rs +++ b/rslib/src/storage/card/mod.rs @@ -400,6 +400,13 @@ impl super::SqliteStorage { .collect() } + pub(crate) fn all_cards_as_nid_and_ord(&self) -> Result> { + self.db + .prepare("SELECT nid, ord FROM cards")? + .query_and_then([], |r| Ok((NoteId(r.get(0)?), r.get(1)?)))? + .collect() + } + pub(crate) fn card_ids_of_notes(&self, nids: &[NoteId]) -> Result> { let mut stmt = self .db