Fix dupe identity check

Canonify tags before checking if dupe is identical, but only add update
tags later if appropriate.
This commit is contained in:
RumovZ 2022-06-06 11:04:59 +02:00
parent 1e17435335
commit 4d98f0656e

View file

@ -74,13 +74,29 @@ struct DeckIdsByNameOrId {
} }
struct NoteContext { struct NoteContext {
/// Prepared and with canonified tags.
note: Note, note: Note,
dupes: Vec<Note>, dupes: Vec<Duplicate>,
cards: Vec<Card>, cards: Vec<Card>,
notetype: Arc<Notetype>, notetype: Arc<Notetype>,
deck_id: DeckId, deck_id: DeckId,
} }
struct Duplicate {
note: Note,
identical: bool,
}
impl Duplicate {
fn new(dupe: Note, original: &Note) -> Self {
let identical = dupe.equal_fields_and_tags(original);
Self {
note: dupe,
identical,
}
}
}
impl DeckIdsByNameOrId { impl DeckIdsByNameOrId {
fn new(col: &mut Collection, default: &NameOrId) -> Result<Self> { fn new(col: &mut Collection, default: &NameOrId) -> Result<Self> {
let names: HashMap<String, DeckId> = col let names: HashMap<String, DeckId> = col
@ -191,6 +207,7 @@ impl<'a> Context<'a> {
) -> Result<NoteContext> { ) -> Result<NoteContext> {
let (mut note, cards) = foreign.into_native(&notetype, deck_id, self.today, global_tags); let (mut note, cards) = foreign.into_native(&notetype, deck_id, self.today, global_tags);
note.prepare_for_update(&notetype, self.normalize_notes)?; note.prepare_for_update(&notetype, self.normalize_notes)?;
self.col.canonify_note_tags(&mut note, self.usn)?;
let dupes = self.find_duplicates(&notetype, &note)?; let dupes = self.find_duplicates(&notetype, &note)?;
Ok(NoteContext { Ok(NoteContext {
@ -202,14 +219,19 @@ impl<'a> Context<'a> {
}) })
} }
fn find_duplicates(&mut self, notetype: &Notetype, note: &Note) -> Result<Vec<Note>> { fn find_duplicates(&mut self, notetype: &Notetype, note: &Note) -> Result<Vec<Duplicate>> {
let checksum = note let checksum = note
.checksum .checksum
.ok_or_else(|| AnkiError::invalid_input("note unprepared"))?; .ok_or_else(|| AnkiError::invalid_input("note unprepared"))?;
self.existing_notes let dupes = self
.existing_notes
.get(&(notetype.id, checksum)) .get(&(notetype.id, checksum))
.map(|dupe_ids| self.col.get_full_duplicates(note, dupe_ids)) .map(|dupe_ids| self.col.get_full_duplicates(note, dupe_ids))
.unwrap_or_else(|| Ok(vec![])) .unwrap_or_else(|| Ok(vec![]))?;
Ok(dupes
.into_iter()
.map(|dupe| Duplicate::new(dupe, note))
.collect())
} }
fn import_note( fn import_note(
@ -228,7 +250,6 @@ impl<'a> Context<'a> {
} }
fn add_note(&mut self, mut ctx: NoteContext, log_queue: &mut Vec<LogNote>) -> Result<()> { fn add_note(&mut self, mut ctx: NoteContext, log_queue: &mut Vec<LogNote>) -> Result<()> {
self.col.canonify_note_tags(&mut ctx.note, self.usn)?;
ctx.note.usn = self.usn; ctx.note.usn = self.usn;
self.col.add_note_only_undoable(&mut ctx.note)?; self.col.add_note_only_undoable(&mut ctx.note)?;
self.add_cards(&mut ctx.cards, &ctx.note, ctx.deck_id, ctx.notetype)?; self.add_cards(&mut ctx.cards, &ctx.note, ctx.deck_id, ctx.notetype)?;
@ -261,25 +282,27 @@ impl<'a> Context<'a> {
} }
fn prepare_note_for_update(&mut self, note: &mut Note, updated_tags: &[String]) -> Result<()> { fn prepare_note_for_update(&mut self, note: &mut Note, updated_tags: &[String]) -> Result<()> {
note.tags.extend(updated_tags.iter().cloned()); if !updated_tags.is_empty() {
self.col.canonify_note_tags(note, self.usn)?; note.tags.extend(updated_tags.iter().cloned());
self.col.canonify_note_tags(note, self.usn)?;
}
note.set_modified(self.usn); note.set_modified(self.usn);
Ok(()) Ok(())
} }
fn maybe_update_dupe( fn maybe_update_dupe(
&mut self, &mut self,
dupe: Note, dupe: Duplicate,
ctx: &mut NoteContext, ctx: &mut NoteContext,
log: &mut NoteLog, log: &mut NoteLog,
) -> Result<()> { ) -> Result<()> {
ctx.note.id = dupe.id; ctx.note.id = dupe.note.id;
ctx.note.guid = dupe.guid.clone(); ctx.note.guid = dupe.note.guid.clone();
if dupe.equal_fields_and_tags(&ctx.note) { if dupe.identical {
log.duplicate.push(dupe.into_log_note()); log.duplicate.push(dupe.note.into_log_note());
} else { } else {
self.col.update_note_undoable(&ctx.note, &dupe)?; self.col.update_note_undoable(&ctx.note, &dupe.note)?;
log.first_field_match.push(dupe.into_log_note()); log.first_field_match.push(dupe.note.into_log_note());
} }
self.add_cards(&mut ctx.cards, &ctx.note, ctx.deck_id, ctx.notetype.clone()) self.add_cards(&mut ctx.cards, &ctx.note, ctx.deck_id, ctx.notetype.clone())
} }