From 47c142a74c7153617dc61c5f3d83a65f2a3835ef Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 5 Mar 2020 16:29:04 +1000 Subject: [PATCH] move note code into notes.rs, add ability to rollback when unchanged --- rslib/src/collection.rs | 13 ++++++++++--- rslib/src/lib.rs | 1 + rslib/src/media/check.rs | 28 ++++++++++++++-------------- rslib/src/media/mod.rs | 1 - rslib/src/{media/col.rs => notes.rs} | 10 +++------- rslib/src/storage/sqlite.rs | 9 ++++++++- 6 files changed, 36 insertions(+), 26 deletions(-) rename rslib/src/{media/col.rs => notes.rs} (93%) diff --git a/rslib/src/collection.rs b/rslib/src/collection.rs index ef9837e8b..c728edca6 100644 --- a/rslib/src/collection.rs +++ b/rslib/src/collection.rs @@ -1,3 +1,6 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + use crate::err::Result; use crate::i18n::I18n; use crate::log::Logger; @@ -35,6 +38,7 @@ pub(crate) struct RequestContext<'a> { pub storage: StorageContext<'a>, pub i18n: &'a I18n, pub log: &'a Logger, + pub should_commit: bool, } impl Collection { @@ -52,6 +56,7 @@ impl Collection { storage: self.storage.context(self.server), i18n: &self.i18n, log: &self.log, + should_commit: true, }; func(&mut ctx) } @@ -67,13 +72,15 @@ impl Collection { let mut res = func(ctx); - if res.is_ok() { - if let Err(e) = ctx.storage.commit_rust_op(op) { + if res.is_ok() && ctx.should_commit { + if let Err(e) = ctx.storage.mark_modified() { + res = Err(e); + } else if let Err(e) = ctx.storage.commit_rust_op(op) { res = Err(e); } } - if res.is_err() { + if res.is_err() || !ctx.should_commit { ctx.storage.rollback_rust_trx()?; } diff --git a/rslib/src/lib.rs b/rslib/src/lib.rs index 16849b2d2..8f815dce8 100644 --- a/rslib/src/lib.rs +++ b/rslib/src/lib.rs @@ -17,6 +17,7 @@ pub mod i18n; pub mod latex; pub mod log; pub mod media; +pub mod notes; pub mod sched; pub mod storage; pub mod template; diff --git a/rslib/src/media/check.rs b/rslib/src/media/check.rs index ee8b71115..b5338d631 100644 --- a/rslib/src/media/check.rs +++ b/rslib/src/media/check.rs @@ -6,11 +6,11 @@ use crate::err::{AnkiError, DBErrorKind, Result}; use crate::i18n::{tr_args, tr_strs, FString}; use crate::latex::extract_latex_expanding_clozes; use crate::log::debug; -use crate::media::col::{for_every_note, get_note_types, mark_collection_modified, set_note, Note}; use crate::media::database::MediaDatabaseContext; use crate::media::files::{ data_for_file, filename_if_normalized, trash_folder, MEDIA_SYNC_FILESIZE_LIMIT, }; +use crate::notes::{for_every_note, get_note_types, set_note, Note}; use crate::text::{normalize_to_nfc, MediaRef}; use crate::{media::MediaManager, text::extract_media_refs}; use coarsetime::Instant; @@ -42,26 +42,26 @@ struct MediaFolderCheck { oversize: Vec, } -pub struct MediaChecker<'a, P> +pub struct MediaChecker<'a, 'b, P> where P: FnMut(usize) -> bool, { - ctx: &'a RequestContext<'a>, + ctx: &'a mut RequestContext<'b>, mgr: &'a MediaManager, progress_cb: P, checked: usize, progress_updated: Instant, } -impl

MediaChecker<'_, P> +impl

MediaChecker<'_, '_, P> where P: FnMut(usize) -> bool, { - pub(crate) fn new<'a>( - ctx: &'a RequestContext<'a>, + pub(crate) fn new<'a, 'b>( + ctx: &'a mut RequestContext<'b>, mgr: &'a MediaManager, progress_cb: P, - ) -> MediaChecker<'a, P> { + ) -> MediaChecker<'a, 'b, P> { MediaChecker { ctx, mgr, @@ -404,8 +404,8 @@ where Ok(()) })?; - if collection_modified { - mark_collection_modified(&self.ctx.storage.db)?; + if !collection_modified { + self.ctx.should_commit = false; } Ok(referenced_files) @@ -546,7 +546,7 @@ mod test { let progress = |_n| true; let (output, report) = col.transact(None, |ctx| { - let mut checker = MediaChecker::new(&ctx, &mgr, progress); + let mut checker = MediaChecker::new(ctx, &mgr, progress); let output = checker.check()?; let summary = checker.summarize_output(&mut output.clone()); Ok((output, summary)) @@ -616,7 +616,7 @@ Unused: unused.jpg let progress = |_n| true; col.transact(None, |ctx| { - let mut checker = MediaChecker::new(&ctx, &mgr, progress); + let mut checker = MediaChecker::new(ctx, &mgr, progress); checker.restore_trash() })?; @@ -630,7 +630,7 @@ Unused: unused.jpg // if we repeat the process, restoring should do the same thing if the contents are equal fs::write(trash_folder.join("test.jpg"), "test")?; col.transact(None, |ctx| { - let mut checker = MediaChecker::new(&ctx, &mgr, progress); + let mut checker = MediaChecker::new(ctx, &mgr, progress); checker.restore_trash() })?; assert_eq!(files_in_dir(&trash_folder), Vec::::new()); @@ -642,7 +642,7 @@ Unused: unused.jpg // but rename if required fs::write(trash_folder.join("test.jpg"), "test2")?; col.transact(None, |ctx| { - let mut checker = MediaChecker::new(&ctx, &mgr, progress); + let mut checker = MediaChecker::new(ctx, &mgr, progress); checker.restore_trash() })?; assert_eq!(files_in_dir(&trash_folder), Vec::::new()); @@ -666,7 +666,7 @@ Unused: unused.jpg let progress = |_n| true; let mut output = col.transact(None, |ctx| { - let mut checker = MediaChecker::new(&ctx, &mgr, progress); + let mut checker = MediaChecker::new(ctx, &mgr, progress); checker.check() })?; diff --git a/rslib/src/media/mod.rs b/rslib/src/media/mod.rs index c0dcfcca8..a3351b95c 100644 --- a/rslib/src/media/mod.rs +++ b/rslib/src/media/mod.rs @@ -12,7 +12,6 @@ use std::path::{Path, PathBuf}; pub mod changetracker; pub mod check; -pub mod col; pub mod database; pub mod files; pub mod sync; diff --git a/rslib/src/media/col.rs b/rslib/src/notes.rs similarity index 93% rename from rslib/src/media/col.rs rename to rslib/src/notes.rs index a87567a4c..c4289e9b1 100644 --- a/rslib/src/media/col.rs +++ b/rslib/src/notes.rs @@ -1,10 +1,11 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -/// Basic note reading/updating functionality for the media DB check. +/// At the moment, this is just basic note reading/updating functionality for +/// the media DB check. use crate::err::{AnkiError, DBErrorKind, Result}; use crate::text::strip_html_preserving_image_filenames; -use crate::time::{i64_unix_millis, i64_unix_secs}; +use crate::time::i64_unix_secs; use crate::types::{ObjID, Timestamp, Usn}; use rusqlite::{params, Connection, Row, NO_PARAMS}; use serde_aux::field_attributes::deserialize_number_from_string; @@ -140,8 +141,3 @@ pub(super) fn set_note(db: &Connection, note: &mut Note, note_type: &NoteType) - Ok(()) } - -pub(super) fn mark_collection_modified(db: &Connection) -> Result<()> { - db.execute("update col set mod=?", params![i64_unix_millis()])?; - Ok(()) -} diff --git a/rslib/src/storage/sqlite.rs b/rslib/src/storage/sqlite.rs index 2e4bd37d1..886a8f801 100644 --- a/rslib/src/storage/sqlite.rs +++ b/rslib/src/storage/sqlite.rs @@ -4,7 +4,7 @@ use crate::collection::CollectionOp; use crate::err::Result; use crate::err::{AnkiError, DBErrorKind}; -use crate::time::i64_unix_secs; +use crate::time::{i64_unix_millis, i64_unix_secs}; use crate::types::Usn; use rusqlite::{params, Connection, NO_PARAMS}; use std::path::{Path, PathBuf}; @@ -173,6 +173,13 @@ impl StorageContext<'_> { ////////////////////////////////////////// + pub(crate) fn mark_modified(&self) -> Result<()> { + self.db + .prepare_cached("update col set mod=?")? + .execute(params![i64_unix_millis()])?; + Ok(()) + } + #[allow(dead_code)] pub(crate) fn usn(&mut self) -> Result { if self.server {