move note code into notes.rs, add ability to rollback when unchanged

This commit is contained in:
Damien Elmes 2020-03-05 16:29:04 +10:00
parent ae06b9e446
commit 47c142a74c
6 changed files with 36 additions and 26 deletions

View file

@ -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::err::Result;
use crate::i18n::I18n; use crate::i18n::I18n;
use crate::log::Logger; use crate::log::Logger;
@ -35,6 +38,7 @@ pub(crate) struct RequestContext<'a> {
pub storage: StorageContext<'a>, pub storage: StorageContext<'a>,
pub i18n: &'a I18n, pub i18n: &'a I18n,
pub log: &'a Logger, pub log: &'a Logger,
pub should_commit: bool,
} }
impl Collection { impl Collection {
@ -52,6 +56,7 @@ impl Collection {
storage: self.storage.context(self.server), storage: self.storage.context(self.server),
i18n: &self.i18n, i18n: &self.i18n,
log: &self.log, log: &self.log,
should_commit: true,
}; };
func(&mut ctx) func(&mut ctx)
} }
@ -67,13 +72,15 @@ impl Collection {
let mut res = func(ctx); let mut res = func(ctx);
if res.is_ok() { if res.is_ok() && ctx.should_commit {
if let Err(e) = ctx.storage.commit_rust_op(op) { 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); res = Err(e);
} }
} }
if res.is_err() { if res.is_err() || !ctx.should_commit {
ctx.storage.rollback_rust_trx()?; ctx.storage.rollback_rust_trx()?;
} }

View file

@ -17,6 +17,7 @@ pub mod i18n;
pub mod latex; pub mod latex;
pub mod log; pub mod log;
pub mod media; pub mod media;
pub mod notes;
pub mod sched; pub mod sched;
pub mod storage; pub mod storage;
pub mod template; pub mod template;

View file

@ -6,11 +6,11 @@ use crate::err::{AnkiError, DBErrorKind, Result};
use crate::i18n::{tr_args, tr_strs, FString}; use crate::i18n::{tr_args, tr_strs, FString};
use crate::latex::extract_latex_expanding_clozes; use crate::latex::extract_latex_expanding_clozes;
use crate::log::debug; 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::database::MediaDatabaseContext;
use crate::media::files::{ use crate::media::files::{
data_for_file, filename_if_normalized, trash_folder, MEDIA_SYNC_FILESIZE_LIMIT, 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::text::{normalize_to_nfc, MediaRef};
use crate::{media::MediaManager, text::extract_media_refs}; use crate::{media::MediaManager, text::extract_media_refs};
use coarsetime::Instant; use coarsetime::Instant;
@ -42,26 +42,26 @@ struct MediaFolderCheck {
oversize: Vec<String>, oversize: Vec<String>,
} }
pub struct MediaChecker<'a, P> pub struct MediaChecker<'a, 'b, P>
where where
P: FnMut(usize) -> bool, P: FnMut(usize) -> bool,
{ {
ctx: &'a RequestContext<'a>, ctx: &'a mut RequestContext<'b>,
mgr: &'a MediaManager, mgr: &'a MediaManager,
progress_cb: P, progress_cb: P,
checked: usize, checked: usize,
progress_updated: Instant, progress_updated: Instant,
} }
impl<P> MediaChecker<'_, P> impl<P> MediaChecker<'_, '_, P>
where where
P: FnMut(usize) -> bool, P: FnMut(usize) -> bool,
{ {
pub(crate) fn new<'a>( pub(crate) fn new<'a, 'b>(
ctx: &'a RequestContext<'a>, ctx: &'a mut RequestContext<'b>,
mgr: &'a MediaManager, mgr: &'a MediaManager,
progress_cb: P, progress_cb: P,
) -> MediaChecker<'a, P> { ) -> MediaChecker<'a, 'b, P> {
MediaChecker { MediaChecker {
ctx, ctx,
mgr, mgr,
@ -404,8 +404,8 @@ where
Ok(()) Ok(())
})?; })?;
if collection_modified { if !collection_modified {
mark_collection_modified(&self.ctx.storage.db)?; self.ctx.should_commit = false;
} }
Ok(referenced_files) Ok(referenced_files)
@ -546,7 +546,7 @@ mod test {
let progress = |_n| true; let progress = |_n| true;
let (output, report) = col.transact(None, |ctx| { 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 output = checker.check()?;
let summary = checker.summarize_output(&mut output.clone()); let summary = checker.summarize_output(&mut output.clone());
Ok((output, summary)) Ok((output, summary))
@ -616,7 +616,7 @@ Unused: unused.jpg
let progress = |_n| true; let progress = |_n| true;
col.transact(None, |ctx| { col.transact(None, |ctx| {
let mut checker = MediaChecker::new(&ctx, &mgr, progress); let mut checker = MediaChecker::new(ctx, &mgr, progress);
checker.restore_trash() 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 // if we repeat the process, restoring should do the same thing if the contents are equal
fs::write(trash_folder.join("test.jpg"), "test")?; fs::write(trash_folder.join("test.jpg"), "test")?;
col.transact(None, |ctx| { col.transact(None, |ctx| {
let mut checker = MediaChecker::new(&ctx, &mgr, progress); let mut checker = MediaChecker::new(ctx, &mgr, progress);
checker.restore_trash() checker.restore_trash()
})?; })?;
assert_eq!(files_in_dir(&trash_folder), Vec::<String>::new()); assert_eq!(files_in_dir(&trash_folder), Vec::<String>::new());
@ -642,7 +642,7 @@ Unused: unused.jpg
// but rename if required // but rename if required
fs::write(trash_folder.join("test.jpg"), "test2")?; fs::write(trash_folder.join("test.jpg"), "test2")?;
col.transact(None, |ctx| { col.transact(None, |ctx| {
let mut checker = MediaChecker::new(&ctx, &mgr, progress); let mut checker = MediaChecker::new(ctx, &mgr, progress);
checker.restore_trash() checker.restore_trash()
})?; })?;
assert_eq!(files_in_dir(&trash_folder), Vec::<String>::new()); assert_eq!(files_in_dir(&trash_folder), Vec::<String>::new());
@ -666,7 +666,7 @@ Unused: unused.jpg
let progress = |_n| true; let progress = |_n| true;
let mut output = col.transact(None, |ctx| { 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() checker.check()
})?; })?;

View file

@ -12,7 +12,6 @@ use std::path::{Path, PathBuf};
pub mod changetracker; pub mod changetracker;
pub mod check; pub mod check;
pub mod col;
pub mod database; pub mod database;
pub mod files; pub mod files;
pub mod sync; pub mod sync;

View file

@ -1,10 +1,11 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // 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::err::{AnkiError, DBErrorKind, Result};
use crate::text::strip_html_preserving_image_filenames; 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 crate::types::{ObjID, Timestamp, Usn};
use rusqlite::{params, Connection, Row, NO_PARAMS}; use rusqlite::{params, Connection, Row, NO_PARAMS};
use serde_aux::field_attributes::deserialize_number_from_string; 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(()) Ok(())
} }
pub(super) fn mark_collection_modified(db: &Connection) -> Result<()> {
db.execute("update col set mod=?", params![i64_unix_millis()])?;
Ok(())
}

View file

@ -4,7 +4,7 @@
use crate::collection::CollectionOp; use crate::collection::CollectionOp;
use crate::err::Result; use crate::err::Result;
use crate::err::{AnkiError, DBErrorKind}; 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 crate::types::Usn;
use rusqlite::{params, Connection, NO_PARAMS}; use rusqlite::{params, Connection, NO_PARAMS};
use std::path::{Path, PathBuf}; 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)] #[allow(dead_code)]
pub(crate) fn usn(&mut self) -> Result<Usn> { pub(crate) fn usn(&mut self) -> Result<Usn> {
if self.server { if self.server {