diff --git a/rslib/src/import_export/package/apkg/import/notes.rs b/rslib/src/import_export/package/apkg/import/notes.rs index c12b4d2da..ba5178a18 100644 --- a/rslib/src/import_export/package/apkg/import/notes.rs +++ b/rslib/src/import_export/package/apkg/import/notes.rs @@ -15,6 +15,7 @@ use crate::import_export::package::UpdateCondition; use crate::import_export::ImportError; use crate::import_export::ImportProgress; use crate::import_export::NoteLog; +use crate::notes::UpdateNoteInnerWithoutCardsArgs; use crate::notetype::ChangeNotetypeInput; use crate::prelude::*; use crate::progress::ThrottlingProgressHandler; @@ -463,15 +464,21 @@ impl<'n> NoteContext<'n> { self.munge_media(&mut note)?; let original = self.get_expected_note(note.id)?; let notetype = self.get_expected_notetype(note.notetype_id)?; - self.target_col.update_note_inner_without_cards( - &mut note, - &original, - ¬etype, - self.usn, - true, - self.normalize_notes, - true, - )?; + // Preserve the incoming note's mtime to allow imports of successive exports + let incoming_mtime = note.mtime; + self.target_col + .update_note_inner_without_cards_using_mtime( + UpdateNoteInnerWithoutCardsArgs { + note: &mut note, + original: &original, + notetype: ¬etype, + usn: self.usn, + mark_note_modified: true, + normalize_text: self.normalize_notes, + update_tags: true, + }, + Some(incoming_mtime), + )?; self.imports.log_updated(note, source_id); Ok(()) } diff --git a/rslib/src/notes/mod.rs b/rslib/src/notes/mod.rs index 3f0b63e3e..851ffaa25 100644 --- a/rslib/src/notes/mod.rs +++ b/rslib/src/notes/mod.rs @@ -220,11 +220,16 @@ impl Note { Ok(()) } - pub(crate) fn set_modified(&mut self, usn: Usn) { - self.mtime = TimestampSecs::now(); + #[inline] + pub(crate) fn set_modified_with_mtime(&mut self, usn: Usn, mtime: TimestampSecs) { + self.mtime = mtime; self.usn = usn; } + pub(crate) fn set_modified(&mut self, usn: Usn) { + self.set_modified_with_mtime(usn, TimestampSecs::now()) + } + pub(crate) fn nonempty_fields<'a>(&self, fields: &'a [NoteField]) -> HashSet<&'a str> { self.fields .iter() @@ -346,6 +351,18 @@ fn invalid_char_for_field(c: char) -> bool { c.is_ascii_control() && c != '\n' && c != '\t' } +/// Used when calling [Collection::update_note_inner_without_cards] and +/// [Collection::update_note_inner_without_cards_using_mtime] +pub(crate) struct UpdateNoteInnerWithoutCardsArgs<'a> { + pub(crate) note: &'a mut Note, + pub(crate) original: &'a Note, + pub(crate) notetype: &'a Notetype, + pub(crate) usn: Usn, + pub(crate) mark_note_modified: bool, + pub(crate) normalize_text: bool, + pub(crate) update_tags: bool, +} + impl Collection { pub(crate) fn canonify_note_tags(&mut self, note: &mut Note, usn: Usn) -> Result<()> { if !note.tags.is_empty() { @@ -434,40 +451,53 @@ impl Collection { normalize_text: bool, update_tags: bool, ) -> Result<()> { - self.update_note_inner_without_cards( + self.update_note_inner_without_cards(UpdateNoteInnerWithoutCardsArgs { note, original, - ctx.notetype, - ctx.usn, + notetype: ctx.notetype, + usn: ctx.usn, mark_note_modified, normalize_text, update_tags, - )?; + })?; self.generate_cards_for_existing_note(ctx, note) } - // TODO: refactor into struct - #[allow(clippy::too_many_arguments)] - pub(crate) fn update_note_inner_without_cards( + #[inline] + pub(crate) fn update_note_inner_without_cards_using_mtime( &mut self, - note: &mut Note, - original: &Note, - notetype: &Notetype, - usn: Usn, - mark_note_modified: bool, - normalize_text: bool, - update_tags: bool, + UpdateNoteInnerWithoutCardsArgs { + note, + original, + notetype, + usn, + mark_note_modified, + normalize_text, + update_tags, + }: UpdateNoteInnerWithoutCardsArgs, + mtime: Option, ) -> Result<()> { if update_tags { self.canonify_note_tags(note, usn)?; } note.prepare_for_update(notetype, normalize_text)?; if mark_note_modified { - note.set_modified(usn); + if let Some(mtime) = mtime { + note.set_modified_with_mtime(usn, mtime); + } else { + note.set_modified(usn); + } } self.update_note_undoable(note, original) } + pub(crate) fn update_note_inner_without_cards( + &mut self, + args: UpdateNoteInnerWithoutCardsArgs<'_>, + ) -> Result<()> { + self.update_note_inner_without_cards_using_mtime(args, None) + } + pub(crate) fn remove_notes_inner(&mut self, nids: &[NoteId], usn: Usn) -> Result { let mut card_count = 0; for nid in nids { @@ -542,15 +572,15 @@ impl Collection { out.update_tags, )?; } else { - self.update_note_inner_without_cards( - &mut note, - &original, - &nt, + self.update_note_inner_without_cards(UpdateNoteInnerWithoutCardsArgs { + note: &mut note, + original: &original, + notetype: &nt, usn, - out.mark_modified, - norm, - out.update_tags, - )?; + mark_note_modified: out.mark_modified, + normalize_text: norm, + update_tags: out.update_tags, + })?; } changed_notes += 1; diff --git a/rslib/src/notetype/schemachange.rs b/rslib/src/notetype/schemachange.rs index c253afd62..f7da96b9d 100644 --- a/rslib/src/notetype/schemachange.rs +++ b/rslib/src/notetype/schemachange.rs @@ -9,6 +9,7 @@ use std::mem; use super::CardGenContext; use super::CardTemplate; use super::Notetype; +use crate::notes::UpdateNoteInnerWithoutCardsArgs; use crate::prelude::*; use crate::search::JoinSearches; use crate::search::TemplateKind; @@ -80,15 +81,15 @@ impl Collection { for nid in nids { let mut note = self.storage.get_note(nid)?.unwrap(); let original = note.clone(); - self.update_note_inner_without_cards( - &mut note, - &original, - nt, + self.update_note_inner_without_cards(UpdateNoteInnerWithoutCardsArgs { + note: &mut note, + original: &original, + notetype: nt, usn, - true, + mark_note_modified: true, normalize_text, - false, - )?; + update_tags: false, + })?; } } else { // nothing to do @@ -104,15 +105,15 @@ impl Collection { let mut note = self.storage.get_note(nid)?.unwrap(); let original = note.clone(); note.reorder_fields(&ords); - self.update_note_inner_without_cards( - &mut note, - &original, - nt, + self.update_note_inner_without_cards(UpdateNoteInnerWithoutCardsArgs { + note: &mut note, + original: &original, + notetype: nt, usn, - true, + mark_note_modified: true, normalize_text, - false, - )?; + update_tags: false, + })?; } Ok(()) }