move remaining undo ops into separate files

This commit is contained in:
Damien Elmes 2021-03-06 16:10:07 +10:00
parent ad74e26c84
commit d70e35e0a2
7 changed files with 123 additions and 101 deletions

View File

@ -1,13 +1,16 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
mod counts;
mod schema11;
mod tree;
mod undo;
pub use crate::backend_proto::{
deck_kind::Kind as DeckKind, filtered_search_term::FilteredSearchOrder, Deck as DeckProto,
DeckCommon, DeckKind as DeckKindProto, FilteredDeck, FilteredSearchTerm, NormalDeck,
};
use crate::{
backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images, undo::Undo,
};
use crate::{backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images};
use crate::{
collection::Collection,
deckconf::DeckConfID,
@ -18,9 +21,6 @@ use crate::{
timestamp::TimestampSecs,
types::Usn,
};
mod counts;
mod schema11;
mod tree;
pub(crate) use counts::DueCounts;
pub use schema11::DeckSchema11;
use std::{borrow::Cow, sync::Arc};
@ -285,7 +285,7 @@ impl Collection {
// rename children
col.rename_child_decks(&existing_deck, &deck.name, usn)?;
}
col.update_single_deck_inner_undo_only(deck, &existing_deck)?;
col.update_single_deck_undoable(deck, &existing_deck)?;
if name_changed {
// after updating, we need to ensure all grandparents exist, which may not be the case
// in the parent->child case
@ -312,18 +312,6 @@ impl Collection {
self.storage.add_or_update_deck_with_existing_id(deck)
}
/// Update an individual, existing deck. Caller is responsible for ensuring deck
/// is normalized, matches parents, is not a duplicate name, and bumping mtime.
pub(crate) fn update_single_deck_inner_undo_only(
&mut self,
deck: &mut Deck,
original: &Deck,
) -> Result<()> {
self.state.deck_cache.clear();
self.save_undo(Box::new(DeckUpdated(original.clone())));
self.storage.update_deck(deck)
}
pub(crate) fn ensure_deck_name_unique(&self, deck: &mut Deck, usn: Usn) -> Result<()> {
loop {
match self.storage.get_deck_id(&deck.name)? {
@ -371,7 +359,7 @@ impl Collection {
let new_name = format!("{}\x1f{}", new_name, child_only.join("\x1f"));
child.name = new_name;
child.set_modified(usn);
self.update_single_deck_inner_undo_only(&mut child, &original)?;
self.update_single_deck_undoable(&mut child, &original)?;
}
Ok(())
@ -601,7 +589,7 @@ impl Collection {
deck.reset_stats_if_day_changed(today);
mutator(&mut deck.common);
deck.set_modified(usn);
self.update_single_deck_inner_undo_only(deck, &original)
self.update_single_deck_undoable(deck, &original)
}
pub fn drag_drop_decks(
@ -647,19 +635,6 @@ impl Collection {
}
}
#[derive(Debug)]
pub(crate) struct DeckUpdated(Deck);
impl Undo for DeckUpdated {
fn undo(mut self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
let current = col
.storage
.get_deck(self.0.id)?
.ok_or_else(|| AnkiError::invalid_input("deck disappeared"))?;
col.update_single_deck_inner_undo_only(&mut self.0, &current)
}
}
#[cfg(test)]
mod test {
use super::{human_deck_name_to_native, immediate_parent_name, normalize_native_name};

33
rslib/src/decks/undo.rs Normal file
View File

@ -0,0 +1,33 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::prelude::*;
use crate::undo::Undo;
#[derive(Debug)]
pub(crate) struct DeckUpdated(Deck);
impl Undo for DeckUpdated {
fn undo(mut self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
let current = col
.storage
.get_deck(self.0.id)?
.ok_or_else(|| AnkiError::invalid_input("deck disappeared"))?;
col.update_single_deck_undoable(&mut self.0, &current)
}
}
impl Collection {
/// Update an individual, existing deck. Caller is responsible for ensuring deck
/// is normalized, matches parents, is not a duplicate name, and bumping mtime.
/// Clears deck cache.
pub(super) fn update_single_deck_undoable(
&mut self,
deck: &mut Deck,
original: &Deck,
) -> Result<()> {
self.state.deck_cache.clear();
self.save_undo(Box::new(DeckUpdated(original.clone())));
self.storage.update_deck(deck)
}
}

View File

@ -1,11 +1,10 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
mod undo;
use crate::serde::{default_on_invalid, deserialize_int_from_number};
use crate::{define_newtype, prelude::*};
use crate::{
serde::{default_on_invalid, deserialize_int_from_number},
undo::Undo,
};
use num_enum::TryFromPrimitive;
use serde::Deserialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
@ -82,14 +81,6 @@ impl RevlogEntry {
}
impl Collection {
/// Add the provided revlog entry, modifying the ID if it is not unique.
pub(crate) fn add_revlog_entry(&mut self, mut entry: RevlogEntry) -> Result<RevlogID> {
entry.id = self.storage.add_revlog_entry(&entry, true)?;
let id = entry.id;
self.save_undo(Box::new(RevlogAdded(entry)));
Ok(id)
}
pub(crate) fn log_manually_scheduled_review(
&mut self,
card: &Card,
@ -107,28 +98,7 @@ impl Collection {
taken_millis: 0,
review_kind: RevlogReviewKind::Manual,
};
self.add_revlog_entry(entry)?;
Ok(())
}
}
#[derive(Debug)]
pub(crate) struct RevlogAdded(RevlogEntry);
#[derive(Debug)]
pub(crate) struct RevlogRemoved(RevlogEntry);
impl Undo for RevlogAdded {
fn undo(self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
col.storage.remove_revlog_entry(self.0.id)?;
col.save_undo(Box::new(RevlogRemoved(self.0)));
Ok(())
}
}
impl Undo for RevlogRemoved {
fn undo(self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
col.storage.add_revlog_entry(&self.0, false)?;
col.save_undo(Box::new(RevlogAdded(self.0)));
self.add_revlog_entry_undoable(entry)?;
Ok(())
}
}

36
rslib/src/revlog/undo.rs Normal file
View File

@ -0,0 +1,36 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::RevlogEntry;
use crate::{prelude::*, undo::Undo};
#[derive(Debug)]
pub(crate) struct RevlogAdded(RevlogEntry);
#[derive(Debug)]
pub(crate) struct RevlogRemoved(RevlogEntry);
impl Undo for RevlogAdded {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.storage.remove_revlog_entry(self.0.id)?;
col.save_undo(Box::new(RevlogRemoved(self.0)));
Ok(())
}
}
impl Undo for RevlogRemoved {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.storage.add_revlog_entry(&self.0, false)?;
col.save_undo(Box::new(RevlogAdded(self.0)));
Ok(())
}
}
impl Collection {
/// Add the provided revlog entry, modifying the ID if it is not unique.
pub(crate) fn add_revlog_entry_undoable(&mut self, mut entry: RevlogEntry) -> Result<RevlogID> {
entry.id = self.storage.add_revlog_entry(&entry, true)?;
let id = entry.id;
self.save_undo(Box::new(RevlogAdded(entry)));
Ok(id)
}
}

View File

@ -305,7 +305,7 @@ impl Collection {
answer.answered_at,
answer.milliseconds_taken,
);
self.add_revlog_entry(revlog)?;
self.add_revlog_entry_undoable(revlog)?;
Ok(())
}

View File

@ -1,6 +1,8 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
mod undo;
use crate::{
backend_proto::TagTreeNode,
collection::Collection,
@ -9,7 +11,6 @@ use crate::{
prelude::*,
text::{normalize_to_nfc, to_re},
types::Usn,
undo::Undo,
};
use regex::{NoExpand, Regex, Replacer};
@ -244,23 +245,11 @@ impl Collection {
} else if let Cow::Owned(new_name) = normalized_name {
tag.name = new_name;
}
self.register_tag_inner(&tag)?;
self.register_tag_undoable(&tag)?;
Ok(true)
}
}
/// Adds an already-validated tag to the DB and undo list.
/// Caller is responsible for setting usn.
pub(crate) fn register_tag_inner(&mut self, tag: &Tag) -> Result<()> {
self.save_undo(Box::new(AddedTag(tag.clone())));
self.storage.register_tag(&tag)
}
pub(crate) fn remove_single_tag(&mut self, tag: &Tag) -> Result<()> {
self.save_undo(Box::new(RemovedTag(tag.clone())));
self.storage.remove_single_tag(&tag.name)
}
/// If parent tag(s) exist and differ in case, return a rewritten tag.
fn adjusted_case_for_parents(&self, tag: &str) -> Result<Option<String>> {
if let Some(parent_tag) = self.first_existing_parent_tag(&tag)? {
@ -482,24 +471,6 @@ impl Collection {
}
}
#[derive(Debug)]
struct AddedTag(Tag);
#[derive(Debug)]
struct RemovedTag(Tag);
impl Undo for AddedTag {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.remove_single_tag(&self.0)
}
}
impl Undo for RemovedTag {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.register_tag_inner(&self.0)
}
}
#[cfg(test)]
mod test {
use super::*;

37
rslib/src/tags/undo.rs Normal file
View File

@ -0,0 +1,37 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use super::Tag;
use crate::{prelude::*, undo::Undo};
#[derive(Debug)]
struct AddedTag(Tag);
#[derive(Debug)]
struct RemovedTag(Tag);
impl Undo for AddedTag {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.remove_single_tag_undoable(&self.0)
}
}
impl Undo for RemovedTag {
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
col.register_tag_undoable(&self.0)
}
}
impl Collection {
/// Adds an already-validated tag to the DB and undo list.
/// Caller is responsible for setting usn.
pub(super) fn register_tag_undoable(&mut self, tag: &Tag) -> Result<()> {
self.save_undo(Box::new(AddedTag(tag.clone())));
self.storage.register_tag(&tag)
}
fn remove_single_tag_undoable(&mut self, tag: &Tag) -> Result<()> {
self.save_undo(Box::new(RemovedTag(tag.clone())));
self.storage.remove_single_tag(&tag.name)
}
}