diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2020-02-29 22:04:02 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2020-06-01 13:58:28 +0200 |
commit | 456647080e3b60b4421484a84c7fe53c1dbe94e7 (patch) | |
tree | 31d67bf3f2899203a52ff355ea0e549f19596942 | |
parent | 69f747ee8fd7be9a18f867a492f632b867316258 (diff) |
Remove mailtree module
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | lib/domain/libimagmail/src/lib.rs | 1 | ||||
-rw-r--r-- | lib/domain/libimagmail/src/mailtree.rs | 346 | ||||
-rw-r--r-- | lib/domain/libimagmail/src/store.rs | 15 |
3 files changed, 0 insertions, 362 deletions
diff --git a/lib/domain/libimagmail/src/lib.rs b/lib/domain/libimagmail/src/lib.rs index f30c5e7c..c572ef92 100644 --- a/lib/domain/libimagmail/src/lib.rs +++ b/lib/domain/libimagmail/src/lib.rs @@ -59,7 +59,6 @@ module_entry_path_mod!("mail"); pub mod notmuch; pub mod mail; -pub mod mailtree; pub mod store; mod util; diff --git a/lib/domain/libimagmail/src/mailtree.rs b/lib/domain/libimagmail/src/mailtree.rs deleted file mode 100644 index 570fcda6..00000000 --- a/lib/domain/libimagmail/src/mailtree.rs +++ /dev/null @@ -1,346 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2020 Matthias Beyer <mail@beyermatthias.de> and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -use failure::Fallible as Result; -use failure::ResultExt; -use indextree::Arena; -use indextree::NodeId; -use indextree::Node; -use itertools::Itertools; - -use crate::store::MailStoreWithConnection; -use crate::mail::Mail; -use crate::mail::LoadedMail; - - -#[derive(Debug)] -pub struct Mailtree { - arena: Arena<String>, - root: NodeId, -} - -impl Mailtree { - pub(crate) fn fill_from<'a>(store: &'a MailStoreWithConnection<'a>, root: LoadedMail) - -> Result<Self> - { - let mut arena = Arena::<String>::new(); - let root = fill_arena_with(&mut arena, store, root)?; - trace!("Arena = {:?}", root); - Ok(Mailtree { arena, root }) - } - - pub fn root(&self) -> Option<&String> { - self.arena.get(self.root).map(|node| node.get()) - } - - pub fn traverse(&self) -> Traverse { - Traverse::with(self) - } - - #[cfg(test)] - fn fill_from_iter<I>(mut it: I) -> Option<(NodeId, Mailtree)> - where I: Iterator<Item = String> - { - let mut arena = Arena::new(); - if let Some(rootdata) = it.next() { - let root = arena.new_node(rootdata); - let mut old_id = root.clone(); - - while let Some(next_data) = it.next() { - let next_id = arena.new_node(next_data); - old_id.append(next_id.clone(), &mut arena); - - old_id = next_id; - } - Some((root, Mailtree { arena, root: root })) - } else { - None - } - } -} - -fn fill_arena_with<'a>(arena: &mut Arena<String>, store: &'a MailStoreWithConnection<'a>, root: LoadedMail) -> Result<NodeId> { - trace!("Filling arena starting at: {}", root.get_id()); - - let root_id = root.get_id().clone(); - trace!("root_id = {:?}", root_id); - - let root_node = arena.new_node(root_id.clone()); - trace!("root_node = {:?}", root_node); - - let root_thread_id = root.get_thread_id().to_owned(); - trace!("root_thread_id = {:?}", root_thread_id); - drop(root); - - - let ids = store.connection().execute(|db| { - let q = format!("thread:{}", root_thread_id); - trace!("Executing query: {}", q); - let query = db.create_query(&q)?; - let r = query.search_threads()? - .map(|thread| { - trace!("Found thread: {}", thread.id()); - let messages = thread - .messages() - .map(|msg| { - let id = msg.id(); - trace!("Found Message: {}", id); - - let id = id.into_owned(); - let new_node_id = arena.new_node(id.clone()); - root_node.append(new_node_id, arena); - id - }) - .collect::<Vec<String>>(); - - trace!("Collected {} messages", messages.len()); - messages - }) - .flat_map(|v| v.into_iter()) - .unique() - .filter(|id| *id != root_id) - .map(Ok) - .collect::<Result<Vec<String>>>(); - - trace!("Query '{:?}' resulted in: {:?}", query, r); - r - })?; - - trace!("IDs = {:?}", ids); - - ids - .into_iter() - .map(|id: String| { - trace!("Trying to get: {:?}", id); - let mail = store.get_mail_by_id(&id) - .context("Getting mail by id")? - .ok_or_else(|| format_err!("Cannot find mail for id {}", id))?; - trace!("Fetched from store: {}", mail.get_location()); - - let reply = mail - .load(store.connection())? - .ok_or_else(|| format_err!("Tried to load unavailable mail: {}", mail.get_location()))?; - trace!("Loaded from store: {}", reply.get_id()); - Ok(()) - }) - .collect::<Result<Vec<_>>>() - .map(|_| root_node) -} - -/// A type for traversing the Mailtree -/// -/// Implements an iterator that yields the Message IDs combined with an "indentation", which marks -/// how deep the yielded node is in the tree. -#[derive(Debug)] -pub struct Traverse<'a> { - tree: &'a Mailtree, - next_node: Option<NodeId>, - next_indent: usize, -} - -impl<'a> Traverse<'a> { - fn with(tree: &'a Mailtree) -> Self { - Traverse { - tree, - next_node: Some(tree.root), - next_indent: 0, - } - } - - fn get_node(&self, nodeid: NodeId) -> Option<String> { - self.tree.arena.get(nodeid).map(|n| n.get()).map(ToOwned::to_owned) - } - - fn get_current_node(&self) -> Option<&Node<String>> { - self.next_node - .and_then(|nodeid| self.tree.arena.get(nodeid)) - } - - fn current_node_next_sibling(&self) -> Option<NodeId> { - self.get_current_node() - .and_then(|node| node.next_sibling()) - } - - fn current_node_first_child(&self) -> Option<NodeId> { - self.get_current_node() - .and_then(|node| node.first_child()) - } - - fn current_node_parent(&self) -> Option<NodeId> { - self.get_current_node() - .and_then(|node| node.parent()) - } -} - -impl<'a> Iterator for Traverse<'a> { - type Item = (usize, String); // (Indention, Message Id) - - fn next(&mut self) -> Option<Self::Item> { - if let Some(current_node) = self.next_node.and_then(|n| self.get_node(n)) { - let current_indent = self.next_indent; - trace!("Iterating: {:?}", self); - - if let Some(sibling) = self.current_node_next_sibling() { - trace!("Sibling found: {:?}", sibling); - // do not alter indent - self.next_node = Some(sibling); - return Some((current_indent, current_node)); - } else { - trace!("No sibling found"); - if let Some(child) = self.current_node_first_child() { - trace!("Child found: {:?}", child); - - // We have a child, make that the current node and return it - self.next_indent += 1; - self.next_node = Some(child); - return Some((current_indent, current_node)); - } else { - trace!("No child found"); - // We have no siblings and - // We have no children - // We might have to go back up one level - - if let Some(parent) = self.current_node_parent() { - trace!("Parent found: {:?}", parent); - // We have a parent - if let Some(parents_sibling) = self.tree.arena.get(parent).and_then(|n| n.next_sibling()) { - trace!("Parents sibling found: {:?}", parents_sibling); - // And the parent has a sibling - // - // Make that the next current node and go from there - self.next_indent -= 1; - self.next_node = Some(parents_sibling); - return Some((current_indent, current_node)); - } else { - trace!("No parents sibling found"); - // We are the last node: - // - We have no sibling - // - We have no child - // - Our parent has no sibling - self.next_node = None; - return Some((current_indent, current_node)) - } - } else { - trace!("No parent found"); - self.next_node = None; - return Some((current_indent, current_node)) - } - } - } - } else { - return None; - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_traverse_with() { - let data = String::from("test"); - let mut arena = Arena::new(); - let root = arena.new_node(data); - let mailtree = Mailtree { - arena, - root: root.clone() - }; - - let t = Traverse::with(&mailtree); - - assert_eq!(t.next_node, Some(root)); - assert_eq!(t.next_indent, 0); - } - - fn make_testing_mailtree(data: String) -> (NodeId, Mailtree) { - let mut arena = Arena::new(); - let root = arena.new_node(data); - - (root.clone(), Mailtree { arena, root: root }) - } - - #[test] - fn test_traverse_get_node() { - let (root_id, mt) = make_testing_mailtree(String::from("test")); - let t = Traverse::with(&mt); - let root = t.get_node(root_id); - assert!(root.is_some()); - assert_eq!(root.unwrap(), "test"); - } - - #[test] - fn test_traverse_get_current_node() { - let (_, mt) = make_testing_mailtree(String::from("test")); - let t = Traverse::with(&mt); - let node = t.get_current_node(); - - assert!(node.is_some()); - let node = node.unwrap(); - - assert_eq!(node.get(), "test"); - assert!(node.parent().is_none()); - assert!(node.first_child().is_none()); - assert!(node.last_child().is_none()); - assert!(node.previous_sibling().is_none()); - assert!(node.next_sibling().is_none()); - assert!(!node.is_removed()); - } - - #[test] - fn test_traverse_current_node_next_sibling() { - let (_, mt) = make_testing_mailtree(String::from("test")); - let t = Traverse::with(&mt); - assert!(t.current_node_next_sibling().is_none()); - } - - #[test] - fn test_traverse_current_node_first_child() { - let (_, mt) = make_testing_mailtree(String::from("test")); - let t = Traverse::with(&mt); - assert!(t.current_node_first_child().is_none()); - } - - #[test] - fn test_traverse_current_node_parent() { - let (_, mt) = make_testing_mailtree(String::from("test")); - let t = Traverse::with(&mt); - assert!(t.current_node_parent().is_none()); - } - - - // - // non-simple tests - // - - #[test] - fn test_iteration() { - let data = ["1", "2", "3", "4"]; - let (_, mt) = Mailtree::fill_from_iter(data.iter().map(ToString::to_string)).unwrap(); - let mut t = Traverse::with(&mt); - - assert_eq!(t.next().unwrap(), (0, String::from("1"))); - assert_eq!(t.next().unwrap(), (1, String::from("2"))); - assert_eq!(t.next().unwrap(), (2, String::from("3"))); - assert_eq!(t.next().unwrap(), (3, String::from("4"))); - assert!(t.next().is_none()); - } - -} - diff --git a/lib/domain/libimagmail/src/store.rs b/lib/domain/libimagmail/src/store.rs index 7a01dd1d..a2f420f7 100644 --- a/lib/domain/libimagmail/src/store.rs +++ b/lib/domain/libimagmail/src/store.rs @@ -35,7 +35,6 @@ use libimagentryutil::isa::Is; use crate::notmuch::connection::NotmuchConnection; use crate::mail::Mail; use crate::mail::IsMail; -use crate::mailtree::Mailtree; pub trait MailStore<'a> { fn with_connection(&'a self, c: &'a NotmuchConnection) -> MailStoreWithConnection<'a>; @@ -117,20 +116,6 @@ impl<'a> MailStoreWithConnection<'a> { self.get_entry_for_id(Cow::from(id)) } - pub fn get_mailtree(&self, root_id: &str) -> Result<Mailtree> { - trace!("Getting mail by id: {}", root_id); - let root = self.get_mail_by_id(root_id)? - .ok_or_else(|| format_err!("Cannot find root message: {}", root_id))?; - - trace!("Getting mail from connection: {:?}", root); - let loaded_root = root.load(self.connection())? - .ok_or_else(|| format_err!("Cannot load root message: {}", root_id))?; - - drop(root); - trace!("Filling mailtree from: {:?}, {:?}", self, loaded_root); - Mailtree::fill_from(self, loaded_root) - } - fn create_entry_for_id(&self, id: Cow<str>) -> Result<FileLockEntry<'a>> { let sid = crate::module_path::new_id(id.as_ref())?; self.store |