mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 17:26:36 -04:00
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:
parent
1e17435335
commit
4d98f0656e
1 changed files with 37 additions and 14 deletions
|
@ -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(¬etype, deck_id, self.today, global_tags);
|
let (mut note, cards) = foreign.into_native(¬etype, deck_id, self.today, global_tags);
|
||||||
note.prepare_for_update(¬etype, self.normalize_notes)?;
|
note.prepare_for_update(¬etype, self.normalize_notes)?;
|
||||||
|
self.col.canonify_note_tags(&mut note, self.usn)?;
|
||||||
let dupes = self.find_duplicates(¬etype, ¬e)?;
|
let dupes = self.find_duplicates(¬etype, ¬e)?;
|
||||||
|
|
||||||
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())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue