diff --git a/bin/core/imag-edit/src/main.rs b/bin/core/imag-edit/src/main.rs index 4b6387d9..46c4c3f9 100644 --- a/bin/core/imag-edit/src/main.rs +++ b/bin/core/imag-edit/src/main.rs @@ -89,7 +89,7 @@ fn main() { let edit_header = rt.cli().is_present("edit-header"); let edit_header_only = rt.cli().is_present("edit-header-only"); - StoreIdIterator::new(Box::new(sids.into_iter())) + StoreIdIterator::new(Box::new(sids.into_iter().map(Ok))) .into_get_iter(rt.store()) .trace_unwrap_exit(1) .map(|o| o.unwrap_or_else(|| { diff --git a/bin/core/imag-ids/src/main.rs b/bin/core/imag-ids/src/main.rs index 08beb465..240a03ea 100644 --- a/bin/core/imag-ids/src/main.rs +++ b/bin/core/imag-ids/src/main.rs @@ -45,6 +45,7 @@ use filters::filter::Filter; use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagstore::storeid::StoreId; @@ -86,6 +87,7 @@ fn main() { rt.store() .entries() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter(|id| collection_filter.filter(id)) .map(|id| if print_storepath { id diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index 4dd8e0de..46ce39e9 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -54,7 +54,6 @@ extern crate libimagutil; use std::io::Write; use std::path::PathBuf; -use std::process::exit; use libimagentrylink::external::ExternalLinker; use libimagentrylink::internal::InternalLinker; @@ -255,12 +254,11 @@ fn unlink(rt: &Runtime) { .map(PathBuf::from) .collect::>().into_iter() // for lifetime inference .map(StoreId::new_baseless) - .unwrap_with(|e| { trace_error(&e); exit(1) }) .into_get_iter(rt.store()) - .unwrap_with(|e| { trace_error(&e); exit(1) }) - .filter_map(|e| e) + .trace_unwrap_exit(1) + .filter_map(|x| x) .map(|mut entry| entry.unlink(rt.store())) - .unwrap_with(|e| { trace_error(&e); exit(1) }) + .trace_unwrap_exit(1) .collect::>(); } diff --git a/bin/core/imag-mv/src/main.rs b/bin/core/imag-mv/src/main.rs index fbb5021e..aeac022b 100644 --- a/bin/core/imag-mv/src/main.rs +++ b/bin/core/imag-mv/src/main.rs @@ -49,9 +49,11 @@ use std::path::PathBuf; use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; use libimagstore::storeid::StoreId; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; +use libimagstore::error::StoreError; use libimagentrylink::internal::InternalLinker; use libimagstore::iter::get::StoreIdGetIteratorExtension; @@ -91,11 +93,11 @@ fn main() { }) .get_internal_links() .map_err_trace_exit_unwrap(1) - .map(|link| link.get_store_id().clone()) + .map(|link| Ok(link.get_store_id().clone()) as Result<_, StoreError>) .into_get_iter(rt.store()) + .trace_unwrap_exit(1) .map(|e| { - e.map_err_trace_exit_unwrap(1) - .unwrap_or_else(|| { + e.unwrap_or_else(|| { error!("Linked entry does not exist"); exit(1) }) diff --git a/bin/core/imag-view/src/main.rs b/bin/core/imag-view/src/main.rs index 5cafb007..bef7e2bc 100644 --- a/bin/core/imag-view/src/main.rs +++ b/bin/core/imag-view/src/main.rs @@ -68,10 +68,10 @@ use libimagentryview::builtin::md::MarkdownViewer; use libimagentryview::viewer::Viewer; use libimagentryview::error::ViewError as VE; use libimagstore::storeid::IntoStoreId; +use libimagstore::storeid::StoreIdIterator; use libimagstore::error::StoreError; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::store::FileLockEntry; -use libimagstore::storeid::StoreId; mod ui; use ui::build_ui; @@ -89,11 +89,10 @@ fn main() { if rt.cli().is_present("in") { let files = entry_ids - .into_iter() .into_get_iter(rt.store()) + .trace_unwrap_exit(1) .map(|e| { - e.map_err_trace_exit_unwrap(1) - .ok_or_else(|| String::from("Entry not found")) + e.ok_or_else(|| String::from("Entry not found")) .map_err(StoreError::from) .map_err_trace_exit_unwrap(1) }) @@ -175,7 +174,6 @@ fn main() { drop(files); } else { let iter = entry_ids - .into_iter() .into_get_iter(rt.store()) .map(|e| { e.map_err_trace_exit_unwrap(1) @@ -249,13 +247,13 @@ fn main() { } } -fn entry_ids(rt: &Runtime) -> Vec { +fn entry_ids(rt: &Runtime) -> StoreIdIterator { match rt.cli().values_of("id") { - Some(pathes) => pathes - .map(PathBuf::from) - .map(PathBuf::into_storeid) - .trace_unwrap_exit(1) - .collect(), + Some(p) => { + let pathes : Vec = p.map(String::from).collect(); + let iter = pathes.into_iter().map(PathBuf::from).map(PathBuf::into_storeid); + StoreIdIterator::new(Box::new(iter)) + }, None => if rt.cli().is_present("entries-from-stdin") { let stdin = rt.stdin().unwrap_or_else(|| { @@ -269,11 +267,10 @@ fn entry_ids(rt: &Runtime) -> Vec { ::std::process::exit(1) }); - buf.lines() - .map(PathBuf::from) - .map(PathBuf::into_storeid) - .trace_unwrap_exit(1) - .collect() + let lines : Vec = buf.lines().map(String::from).collect(); + let iter = lines.into_iter().map(PathBuf::from).map(PathBuf::into_storeid); + + StoreIdIterator::new(Box::new(iter)) } else { error!("Something weird happened. I was not able to find the path of the entries to edit"); ::std::process::exit(1) diff --git a/bin/domain/imag-diary/src/list.rs b/bin/domain/imag-diary/src/list.rs index 55ab2740..a40cd0ff 100644 --- a/bin/domain/imag-diary/src/list.rs +++ b/bin/domain/imag-diary/src/list.rs @@ -23,6 +23,7 @@ use libimagdiary::diary::Diary; use libimagrt::runtime::Runtime; use libimagutil::warn_exit::warn_exit; use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; use libimagutil::debug_result::*; @@ -40,6 +41,7 @@ pub fn list(rt: &Runtime) { let mut ids = Diary::entries(rt.store(), &diaryname) .map_dbg_str("Ok") .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .map(|id| DiaryId::from_storeid(&id)) .collect::>>() .map_err_trace_exit_unwrap(1); diff --git a/bin/domain/imag-diary/src/view.rs b/bin/domain/imag-diary/src/view.rs index 7e48fd90..763d2456 100644 --- a/bin/domain/imag-diary/src/view.rs +++ b/bin/domain/imag-diary/src/view.rs @@ -21,6 +21,7 @@ use libimagdiary::diary::Diary; use libimagdiary::viewer::DiaryViewer as DV; use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; use libimagutil::warn_exit::warn_exit; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagentryview::viewer::Viewer; @@ -34,7 +35,7 @@ pub fn view(rt: &Runtime) { let entries = Diary::entries(rt.store(), &diaryname) .map_err_trace_exit_unwrap(1) .into_get_iter(rt.store()) - .filter_map(Result::ok) + .trace_unwrap_exit(1) .map(|e| e.unwrap_or_else(|| { error!("Failed to fetch entry"); ::std::process::exit(1) diff --git a/bin/domain/imag-habit/src/main.rs b/bin/domain/imag-habit/src/main.rs index 61b69bd6..218a0d67 100644 --- a/bin/domain/imag-habit/src/main.rs +++ b/bin/domain/imag-habit/src/main.rs @@ -57,6 +57,7 @@ use prettytable::row::Row; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::{MapErrTrace, trace_error}; +use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimaghabit::store::HabitStore; @@ -167,6 +168,7 @@ fn delete(rt: &Runtime) { .store() .all_habit_templates() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .map(|sid| (sid.clone(), rt.store().get(sid).map_err_trace_exit_unwrap(1))) // get the FileLockEntry .filter(|&(_, ref habit)| match habit { // filter for name of habit == name we look for &Some(ref h) => h.habit_name().map_err_trace_exit_unwrap(1) == name, @@ -198,6 +200,7 @@ fn delete(rt: &Runtime) { fle .linked_instances() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(get_instance) .filter(has_template_name) .map(instance_location) @@ -249,6 +252,7 @@ fn today(rt: &Runtime, future: bool) { .store() .all_habit_templates() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(|id| match rt.store().get(id.clone()) { Ok(Some(h)) => Some(h), Ok(None) => { @@ -396,6 +400,7 @@ fn list(rt: &Runtime) { .store() .all_habit_templates() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(|id| match rt.store().get(id.clone()) { Ok(Some(h)) => Some(h), Ok(None) => { @@ -451,6 +456,7 @@ fn show(rt: &Runtime) { .store() .all_habit_templates() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(|id| get_from_store(rt.store(), id)) .filter(|h| h.habit_name().map(|n| name == n).map_err_trace_exit_unwrap(1)) .enumerate() @@ -474,6 +480,7 @@ fn show(rt: &Runtime) { let _ = habit .linked_instances() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(|instance_id| { debug!("Getting: {:?}", instance_id); rt.store().get(instance_id).map_err_trace_exit_unwrap(1) @@ -505,6 +512,7 @@ fn done(rt: &Runtime) { .store() .all_habit_templates() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter_map(|id| get_from_store(rt.store(), id)) .filter(|h| { let due = h.next_instance_date().map_err_trace_exit_unwrap(1); diff --git a/bin/domain/imag-mail/src/main.rs b/bin/domain/imag-mail/src/main.rs index e010c46e..f36e01c4 100644 --- a/bin/domain/imag-mail/src/main.rs +++ b/bin/domain/imag-mail/src/main.rs @@ -43,6 +43,7 @@ extern crate libimagutil; use std::io::Write; use libimagerror::trace::{MapErrTrace, trace_error}; +use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagmail::mail::Mail; @@ -143,6 +144,7 @@ fn list(rt: &Runtime) { let _ = rt.store() .entries() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .filter(|id| id.is_in_collection(&["mail"])) .filter_map(|id| { rt.store() diff --git a/bin/domain/imag-todo/src/main.rs b/bin/domain/imag-todo/src/main.rs index cf1d4ccb..622bcce2 100644 --- a/bin/domain/imag-todo/src/main.rs +++ b/bin/domain/imag-todo/src/main.rs @@ -50,6 +50,7 @@ use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; use libimagtodo::taskstore::TaskStore; use libimagerror::trace::{MapErrTrace, trace_error}; +use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; @@ -124,7 +125,7 @@ fn list(rt: &Runtime) { let res = rt.store().all_tasks() // get all tasks .map(|iter| { // and if this succeeded // filter out the ones were we can read the uuid - let uuids : Vec<_> = iter.filter_map(|storeid| { + let uuids : Vec<_> = iter.trace_unwrap_exit(1).filter_map(|storeid| { match rt.store().retrieve(storeid) { Ok(fle) => { match fle.get_header().read_string("todo.uuid") { diff --git a/bin/domain/imag-wiki/src/main.rs b/bin/domain/imag-wiki/src/main.rs index 5c393bca..6e586009 100644 --- a/bin/domain/imag-wiki/src/main.rs +++ b/bin/domain/imag-wiki/src/main.rs @@ -34,6 +34,7 @@ use std::io::Write; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; +use libimagerror::iter::TraceIterator; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; @@ -90,6 +91,7 @@ fn ids(rt: &Runtime, wiki_name: &str) { }) .all_ids() .map_err_trace_exit_unwrap(1) + .trace_unwrap_exit(1) .for_each(|id| { let _ = writeln!(outlock, "{}{}", prefix, id) .to_exit_code() diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index 8766cda7..093bd3cc 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -22,6 +22,7 @@ use std::process::Command; use std::env; use std::process::exit; use std::io::Stdin; +use std::sync::Arc; pub use clap::App; use clap::AppSettings; @@ -132,7 +133,7 @@ impl<'a> Runtime<'a> { let store_result = if cli_app.use_inmemory_fs() { Store::new_with_backend(storepath, &config, - Box::new(InMemoryFileAbstraction::default())) + Arc::new(InMemoryFileAbstraction::default())) } else { Store::new(storepath, &config) }; diff --git a/lib/core/libimagstore/src/file_abstraction/fs.rs b/lib/core/libimagstore/src/file_abstraction/fs.rs index a41a2239..8ee7ee9d 100644 --- a/lib/core/libimagstore/src/file_abstraction/fs.rs +++ b/lib/core/libimagstore/src/file_abstraction/fs.rs @@ -168,20 +168,15 @@ impl FileAbstraction for FSFileAbstraction { fn pathes_recursively(&self, basepath: PathBuf) -> Result { use walkdir::WalkDir; - let i : Result, SE> = WalkDir::new(basepath) + let i = WalkDir::new(basepath) .min_depth(1) + .max_open(100) .into_iter() .map(|r| { - r.map(|e| PathBuf::from(e.path())) - .chain_err(|| SE::from_kind(SEK::FileError)) - }) - .fold(Ok(vec![]), |acc, e| { - acc.and_then(move |mut a| { - a.push(e?); - Ok(a) - }) + r.map(|e| PathBuf::from(e.path())).chain_err(|| SE::from_kind(SEK::FileError)) }); - Ok(PathIterator::new(Box::new(i?.into_iter()))) + + Ok(PathIterator::new(Box::new(i))) } } diff --git a/lib/core/libimagstore/src/file_abstraction/inmemory.rs b/lib/core/libimagstore/src/file_abstraction/inmemory.rs index efe0c4f4..495286fd 100644 --- a/lib/core/libimagstore/src/file_abstraction/inmemory.rs +++ b/lib/core/libimagstore/src/file_abstraction/inmemory.rs @@ -183,15 +183,15 @@ impl FileAbstraction for InMemoryFileAbstraction { fn pathes_recursively(&self, _basepath: PathBuf) -> Result { debug!("Getting all pathes"); - let keys : Vec = self + let keys : Vec> = self .backend() .lock() .map_err(|_| SE::from_kind(SEK::FileError))? .get_mut() .keys() .map(PathBuf::from) - .collect(); - // we collect here as this happens only in tests and in memory anyways, so no problem + .map(Ok) + .collect(); // we have to collect() because of the lock() above. Ok(PathIterator::new(Box::new(keys.into_iter()))) } diff --git a/lib/core/libimagstore/src/file_abstraction/iter.rs b/lib/core/libimagstore/src/file_abstraction/iter.rs index ca2862b3..dea30a5e 100644 --- a/lib/core/libimagstore/src/file_abstraction/iter.rs +++ b/lib/core/libimagstore/src/file_abstraction/iter.rs @@ -18,20 +18,31 @@ // use std::path::PathBuf; +use std::sync::Arc; + +use error::Result; +use storeid::StoreId; +use file_abstraction::FileAbstraction; /// A wrapper for an iterator over `PathBuf`s -pub struct PathIterator(Box>); +pub struct PathIterator(Box>>); impl PathIterator { - pub fn new(iter: Box>) -> PathIterator { + pub fn new(iter: Box>>) -> PathIterator { PathIterator(iter) } + pub fn store_id_constructing(self, storepath: PathBuf, backend: Arc) + -> StoreIdConstructingIterator + { + StoreIdConstructingIterator(self, storepath, backend) + } + } impl Iterator for PathIterator { - type Item = PathBuf; + type Item = Result; fn next(&mut self) -> Option { self.0.next() @@ -39,3 +50,29 @@ impl Iterator for PathIterator { } + +/// Helper type for constructing StoreIds from a PathIterator. +/// +/// Automatically ignores non-files. +pub struct StoreIdConstructingIterator(PathIterator, PathBuf, Arc); + +impl Iterator for StoreIdConstructingIterator { + type Item = Result; + + fn next(&mut self) -> Option { + while let Some(next) = self.0.next() { + match next { + Err(e) => return Some(Err(e)), + Ok(next) => match self.2.exists(&next) { + Err(e) => return Some(Err(e)), + Ok(true) => return Some(StoreId::from_full_path(&self.1, next)), + Ok(false) => { continue }, + } + } + } + + None + } + +} + diff --git a/lib/core/libimagstore/src/file_abstraction/mod.rs b/lib/core/libimagstore/src/file_abstraction/mod.rs index 893b8ca2..a3172735 100644 --- a/lib/core/libimagstore/src/file_abstraction/mod.rs +++ b/lib/core/libimagstore/src/file_abstraction/mod.rs @@ -27,7 +27,7 @@ use storeid::StoreId; mod fs; mod inmemory; -mod iter; +pub(crate) mod iter; pub use self::fs::FSFileAbstraction; pub use self::fs::FSFileAbstractionInstance; diff --git a/lib/core/libimagstore/src/iter.rs b/lib/core/libimagstore/src/iter.rs index 0171a93b..0e066b09 100644 --- a/lib/core/libimagstore/src/iter.rs +++ b/lib/core/libimagstore/src/iter.rs @@ -17,111 +17,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -macro_rules! mk_iterator { - { - modname = $modname:ident, - itername = $itername:ident, - iteryield = $yield:ty, - extname = $extname:ident, - extfnname = $extfnname:ident, - fun = $fun:expr - } => { - use storeid::StoreId; - #[allow(unused_imports)] - use store::FileLockEntry; - use store::Store; - use error::Result; - - pub struct $itername<'a>(Box + 'a>, &'a Store); - - impl<'a> $itername<'a> { - pub fn new(inner: Box + 'a>, store: &'a Store) -> Self { - $itername(inner, store) - } - } - - impl<'a> Iterator for $itername<'a> { - type Item = Result<$yield>; - - fn next(&mut self) -> Option { - self.0.next().map(|id| $fun(id, self.1)) - } - } - - pub trait $extname<'a> { - fn $extfnname(self, store: &'a Store) -> $itername<'a>; - } - - impl<'a, I> $extname<'a> for I - where I: Iterator + 'a - { - fn $extfnname(self, store: &'a Store) -> $itername<'a> { - $itername(Box::new(self), store) - } - } - } -} - -use error::StoreError; - -pub enum ExtensionError { - Forwarded(E), - StoreError(StoreError) -} - macro_rules! mk_iterator_mod { - { - modname = $modname:ident, - itername = $itername:ident, - iteryield = $yield:ty, - extname = $extname:ident, - extfnname = $extfnname:ident, - fun = $fun:expr, - resultitername = $resultitername:ident, - resultextname = $resultextname:ident - } => { - pub mod $modname { - mk_iterator! { - modname = $modname, - itername = $itername, - iteryield = $yield, - extname = $extname, - extfnname = $extfnname, - fun = $fun - } - - use std::result::Result as RResult; - - pub struct $resultitername<'a, I>(I, &'a Store); - - impl<'a, I, E> Iterator for $resultitername<'a, I> - where I: Iterator> - { - type Item = RResult<$yield, $crate::iter::ExtensionError>; - - fn next(&mut self) -> Option { - match self.0.next() { - Some(Ok(sid)) => Some($fun(sid, self.1).map_err($crate::iter::ExtensionError::StoreError)), - Some(Err(e)) => Some(Err($crate::iter::ExtensionError::Forwarded(e))), - None => None, - } - } - } - - pub trait $resultextname<'a> : Iterator { - fn $extfnname(self, store: &'a Store) -> $resultitername<'a, Self> - where Self: Sized - { - $resultitername(self, store) - } - } - - impl<'a, I> $resultextname<'a> for I - where I: Iterator - { /* empty */ } - } - }; - { modname = $modname:ident, itername = $itername:ident, @@ -131,13 +27,47 @@ macro_rules! mk_iterator_mod { fun = $fun:expr } => { pub mod $modname { - mk_iterator! { - modname = $modname, - itername = $itername, - iteryield = $yield, - extname = $extname, - extfnname = $extfnname, - fun = $fun + use storeid::StoreId; + #[allow(unused_imports)] + use store::FileLockEntry; + use store::Store; + use error::StoreError; + use std::result::Result as RResult; + + pub struct $itername<'a, E>(Box> + 'a>, &'a Store) + where E: From; + + impl<'a, E> $itername<'a, E> + where E: From + { + pub fn new(inner: Box> + 'a>, store: &'a Store) -> Self { + $itername(inner, store) + } + } + + impl<'a, E> Iterator for $itername<'a, E> + where E: From + { + type Item = RResult<$yield, E>; + + fn next(&mut self) -> Option { + self.0.next().map(|id| $fun(id?, self.1).map_err(E::from)) + } + } + + pub trait $extname<'a, E> + where E: From + { + fn $extfnname(self, store: &'a Store) -> $itername<'a, E>; + } + + impl<'a, I, E> $extname<'a, E> for I + where I: Iterator> + 'a, + E: From + { + fn $extfnname(self, store: &'a Store) -> $itername<'a, E> { + $itername(Box::new(self), store) + } } } } @@ -149,9 +79,7 @@ mk_iterator_mod! { iteryield = FileLockEntry<'a>, extname = StoreIdCreateIteratorExtension, extfnname = into_create_iter, - fun = |id: StoreId, store: &'a Store| store.create(id), - resultitername = StoreCreateResultIterator, - resultextname = StoreIdCreateResultIteratorExtension + fun = |id: StoreId, store: &'a Store| store.create(id) } mk_iterator_mod! { @@ -160,9 +88,7 @@ mk_iterator_mod! { iteryield = (), extname = StoreIdDeleteIteratorExtension, extfnname = into_delete_iter, - fun = |id: StoreId, store: &'a Store| store.delete(id), - resultitername = StoreDeleteResultIterator, - resultextname = StoreIdDeleteResultIteratorExtension + fun = |id: StoreId, store: &'a Store| store.delete(id) } mk_iterator_mod! { @@ -171,9 +97,7 @@ mk_iterator_mod! { iteryield = Option>, extname = StoreIdGetIteratorExtension, extfnname = into_get_iter, - fun = |id: StoreId, store: &'a Store| store.get(id), - resultitername = StoreGetResultIterator, - resultextname = StoreIdGetResultIteratorExtension + fun = |id: StoreId, store: &'a Store| store.get(id) } mk_iterator_mod! { @@ -182,9 +106,7 @@ mk_iterator_mod! { iteryield = FileLockEntry<'a>, extname = StoreIdRetrieveIteratorExtension, extfnname = into_retrieve_iter, - fun = |id: StoreId, store: &'a Store| store.retrieve(id), - resultitername = StoreRetrieveResultIterator, - resultextname = StoreIdRetrieveResultIteratorExtension + fun = |id: StoreId, store: &'a Store| store.retrieve(id) } #[cfg(test)] diff --git a/lib/core/libimagstore/src/store.rs b/lib/core/libimagstore/src/store.rs index 7edf3f05..44afbea6 100644 --- a/lib/core/libimagstore/src/store.rs +++ b/lib/core/libimagstore/src/store.rs @@ -137,7 +137,7 @@ impl Iterator for Walk { impl StoreEntry { - fn new(id: StoreId, backend: &Box) -> Result { + fn new(id: StoreId, backend: &Arc) -> Result { let pb = id.clone().into_pathbuf()?; #[cfg(feature = "fs-lock")] @@ -214,7 +214,7 @@ pub struct Store { /// The backend to use /// /// This provides the filesystem-operation functions (or pretends to) - backend: Box, + backend: Arc, } impl Store { @@ -235,7 +235,7 @@ impl Store { /// - On success: Store object /// pub fn new(location: PathBuf, store_config: &Option) -> Result { - let backend = Box::new(FSFileAbstraction::default()); + let backend = Arc::new(FSFileAbstraction::default()); Store::new_with_backend(location, store_config, backend) } @@ -245,7 +245,7 @@ impl Store { /// Do not use directly, only for testing purposes. pub fn new_with_backend(location: PathBuf, store_config: &Option, - backend: Box) -> Result { + backend: Arc) -> Result { use configuration::*; debug!("Building new Store object"); @@ -279,33 +279,6 @@ impl Store { Ok(store) } - /// Reset the backend of the store during runtime - /// - /// # Warning - /// - /// This is dangerous! - /// You should not be able to do that in application code, only the libimagrt should be used to - /// do this via safe and careful wrapper functions! - /// - /// If you are able to do this without using `libimagrt`, please file an issue report. - /// - /// # Purpose - /// - /// With the I/O backend of the store, the store is able to pipe itself out via (for example) - /// JSON. But because we need a functionality where we load contents from the filesystem and - /// then pipe it to stdout, we need to be able to replace the backend during runtime. - /// - /// This also applies the other way round: If we get the store from stdin and have to persist it - /// to stdout, we need to be able to replace the in-memory backend with the real filesystem - /// backend. - /// - pub fn reset_backend(&mut self, mut backend: Box) -> Result<()> { - self.backend - .drain() - .and_then(|drain| backend.fill(drain)) - .map(|_| self.backend = backend) - } - /// Creates the Entry at the given location (inside the entry) /// /// # Return value @@ -741,25 +714,12 @@ impl Store { } /// Get _all_ entries in the store (by id as iterator) - pub fn entries<'a>(&'a self) -> Result> { + pub fn entries(&self) -> Result { self.backend .pathes_recursively(self.path().clone()) - .and_then(|iter| { - let mut elems = vec![]; - for element in iter { - let is_file = { - let mut base = self.path().clone(); - base.push(element.clone()); - self.backend.is_file(&base)? - }; - - if is_file { - let sid = StoreId::from_full_path(self.path(), element)?; - elems.push(sid); - } - } - Ok(StoreIdIteratorWithStore::new(Box::new(elems.into_iter()), self)) - }) + .map(|i| i.store_id_constructing(self.path().clone(), self.backend.clone())) + .map(Box::new) + .map(|it| StoreIdIteratorWithStore::new(it, self)) } /// Gets the path where this store is on the disk @@ -1215,12 +1175,13 @@ Hai #[cfg(test)] mod store_tests { use std::path::PathBuf; + use std::sync::Arc; use super::Store; use file_abstraction::InMemoryFileAbstraction; pub fn get_store() -> Store { - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } @@ -1400,50 +1361,5 @@ mod store_tests { } } - #[test] - fn test_swap_backend_during_runtime() { - use file_abstraction::InMemoryFileAbstraction; - - let mut store = { - let backend = InMemoryFileAbstraction::default(); - let backend = Box::new(backend); - - Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() - }; - - for n in 1..100 { - let s = format!("test-{}", n); - let entry = store.create(PathBuf::from(s.clone())).unwrap(); - assert!(entry.verify().is_ok()); - let loc = entry.get_location().clone().into_pathbuf().unwrap(); - assert!(loc.starts_with("/")); - assert!(loc.ends_with(s)); - } - - { - let other_backend = InMemoryFileAbstraction::default(); - let other_backend = Box::new(other_backend); - - assert!(store.reset_backend(other_backend).is_ok()) - } - - for n in 1..100 { - let s = format!("test-{}", n); - let entry = store.get(PathBuf::from(s.clone())); - - assert!(entry.is_ok()); - let entry = entry.unwrap(); - - assert!(entry.is_some()); - let entry = entry.unwrap(); - - assert!(entry.verify().is_ok()); - - let loc = entry.get_location().clone().into_pathbuf().unwrap(); - assert!(loc.starts_with("/")); - assert!(loc.ends_with(s)); - } - } - } diff --git a/lib/core/libimagstore/src/storeid.rs b/lib/core/libimagstore/src/storeid.rs index 2bcd9ba7..3d639797 100644 --- a/lib/core/libimagstore/src/storeid.rs +++ b/lib/core/libimagstore/src/storeid.rs @@ -241,7 +241,7 @@ macro_rules! module_entry_path_mod { } pub struct StoreIdIterator { - iter: Box>, + iter: Box>>, } impl Debug for StoreIdIterator { @@ -254,16 +254,16 @@ impl Debug for StoreIdIterator { impl StoreIdIterator { - pub fn new(iter: Box>) -> StoreIdIterator { + pub fn new(iter: Box>>) -> StoreIdIterator { StoreIdIterator { iter } } } impl Iterator for StoreIdIterator { - type Item = StoreId; + type Item = Result; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { self.iter.next() } @@ -280,16 +280,18 @@ impl<'a> Deref for StoreIdIteratorWithStore<'a> { } impl<'a> Iterator for StoreIdIteratorWithStore<'a> { - type Item = StoreId; + type Item = Result; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { self.0.next() } } +use error::StoreError; + impl<'a> StoreIdIteratorWithStore<'a> { - pub fn new(iter: Box>, store: &'a Store) -> Self { + pub fn new(iter: Box>>, store: &'a Store) -> Self { StoreIdIteratorWithStore(StoreIdIterator::new(iter), store) } @@ -300,7 +302,7 @@ impl<'a> StoreIdIteratorWithStore<'a> { /// Transform the iterator into a StoreCreateIterator /// /// This immitates the API from `libimagstore::iter`. - pub fn into_create_iter(self) -> StoreCreateIterator<'a> { + pub fn into_create_iter(self) -> StoreCreateIterator<'a, StoreError> { StoreCreateIterator::new(Box::new(self.0), self.1) } @@ -308,7 +310,7 @@ impl<'a> StoreIdIteratorWithStore<'a> { /// /// /// This immitates the API from `libimagstore::iter`. - pub fn into_delete_iter(self) -> StoreDeleteIterator<'a> { + pub fn into_delete_iter(self) -> StoreDeleteIterator<'a, StoreError> { StoreDeleteIterator::new(Box::new(self.0), self.1) } @@ -316,7 +318,7 @@ impl<'a> StoreIdIteratorWithStore<'a> { /// /// /// This immitates the API from `libimagstore::iter`. - pub fn into_get_iter(self) -> StoreGetIterator<'a> { + pub fn into_get_iter(self) -> StoreGetIterator<'a, StoreError> { StoreGetIterator::new(Box::new(self.0), self.1) } @@ -324,7 +326,7 @@ impl<'a> StoreIdIteratorWithStore<'a> { /// /// /// This immitates the API from `libimagstore::iter`. - pub fn into_retrieve_iter(self) -> StoreRetrieveIterator<'a> { + pub fn into_retrieve_iter(self) -> StoreRetrieveIterator<'a, StoreError> { StoreRetrieveIterator::new(Box::new(self.0), self.1) } diff --git a/lib/domain/libimagcontact/src/iter.rs b/lib/domain/libimagcontact/src/iter.rs index 1f99c873..48f0f403 100644 --- a/lib/domain/libimagcontact/src/iter.rs +++ b/lib/domain/libimagcontact/src/iter.rs @@ -43,8 +43,9 @@ impl<'a> Iterator for ContactIter<'a> { fn next(&mut self) -> Option { loop { match self.0.next() { - None => return None, - Some(sid) => match self.1.get(sid.clone()).map_err(From::from) { + None => return None, + Some(Err(e)) => return Some(Err(e).map_err(CE::from)), + Some(Ok(sid)) => match self.1.get(sid.clone()).map_err(From::from) { Err(e) => return Some(Err(e)), Ok(None) => return Some(Err(CE::from_kind(CEK::EntryNotFound(sid)))), Ok(Some(entry)) => match entry.is_contact().map_err(From::from) { diff --git a/lib/domain/libimagcontact/src/store.rs b/lib/domain/libimagcontact/src/store.rs index 88856b70..e2b9aea4 100644 --- a/lib/domain/libimagcontact/src/store.rs +++ b/lib/domain/libimagcontact/src/store.rs @@ -81,7 +81,10 @@ impl<'a> ContactStore<'a> for Store { let iter = self .entries()? .without_store() - .filter(|id| id.is_in_collection(&["contact"])); + .filter(|id| match *id { + Ok(ref id) => id.is_in_collection(&["contact"]), + Err(_) => true, + }); Ok(StoreIdIterator::new(Box::new(iter))) } diff --git a/lib/domain/libimagdiary/src/diary.rs b/lib/domain/libimagdiary/src/diary.rs index 15ee28ba..ea4b2491 100644 --- a/lib/domain/libimagdiary/src/diary.rs +++ b/lib/domain/libimagdiary/src/diary.rs @@ -94,13 +94,27 @@ impl Diary for Store { .chain_err(|| DEK::StoreReadError) } + /// get the id of the youngest entry + /// + /// TODO: We collect internally here. We shouldn't do that. Solution unclear. fn get_youngest_entry_id(&self, diary_name: &str) -> Option> { + use error::DiaryError as DE; + match Diary::entries(self, diary_name) { Err(e) => Some(Err(e)), Ok(entries) => { - entries - .map(|e| DiaryId::from_storeid(&e)) - .sorted_by(|a, b| { + let mut sorted_entries = vec![]; + + for entry in entries { + let entry = match entry { + Ok(e) => DiaryId::from_storeid(&e), + Err(e) => return Some(Err(e).map_err(DE::from)), + }; + + sorted_entries.push(entry); + } + + sorted_entries.into_iter().sorted_by(|a, b| { match (a, b) { (&Ok(ref a), &Ok(ref b)) => { let a : NaiveDateTime = a.clone().into(); diff --git a/lib/domain/libimagdiary/src/iter.rs b/lib/domain/libimagdiary/src/iter.rs index 09f9114e..6ebc5230 100644 --- a/lib/domain/libimagdiary/src/iter.rs +++ b/lib/domain/libimagdiary/src/iter.rs @@ -103,16 +103,17 @@ impl Filter for DiaryEntryIterator { } impl Iterator for DiaryEntryIterator { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { loop { match self.iter.next() { - None => return None, - Some(s) => { + None => return None, + Some(Err(e)) => return Some(Err(e).map_err(DE::from)), + Some(Ok(s)) => { debug!("Next element: {:?}", s); if Filter::filter(self, &s) { - return Some(s) + return Some(Ok(s)) } else { continue } @@ -141,16 +142,19 @@ impl Iterator for DiaryNameIterator { fn next(&mut self) -> Option { while let Some(next) = self.0.next() { - if next.is_in_collection(&["diary"]) { - return Some(next - .to_str() - .chain_err(|| DEK::DiaryNameFindingError) - .and_then(|s| { - s.split("diary/") - .nth(1) - .and_then(|n| n.split("/").nth(0).map(String::from)) - .ok_or(DE::from_kind(DEK::DiaryNameFindingError)) - })) + match next { + Err(e) => return Some(Err(e).map_err(DE::from)), + Ok(next) => if next.is_in_collection(&["diary"]) { + return Some(next + .to_str() + .chain_err(|| DEK::DiaryNameFindingError) + .and_then(|s| { + s.split("diary/") + .nth(1) + .and_then(|n| n.split("/").nth(0).map(String::from)) + .ok_or(DE::from_kind(DEK::DiaryNameFindingError)) + })); + }, } } diff --git a/lib/domain/libimaghabit/src/habit.rs b/lib/domain/libimaghabit/src/habit.rs index 36c9dcc0..cd53c290 100644 --- a/lib/domain/libimaghabit/src/habit.rs +++ b/lib/domain/libimaghabit/src/habit.rs @@ -131,7 +131,8 @@ impl HabitTemplate for Entry { let iter = self .get_internal_links()? .map(|link| link.get_store_id().clone()) - .filter(IsHabitCheck::is_habit_instance); + .filter(IsHabitCheck::is_habit_instance) + .map(Ok); let sidi = StoreIdIterator::new(Box::new(iter)); Ok(HabitInstanceStoreIdIterator::new(sidi)) diff --git a/lib/domain/libimaghabit/src/iter.rs b/lib/domain/libimaghabit/src/iter.rs index fa64f1ae..6a1af765 100644 --- a/lib/domain/libimaghabit/src/iter.rs +++ b/lib/domain/libimaghabit/src/iter.rs @@ -22,16 +22,21 @@ use libimagstore::storeid::StoreIdIteratorWithStore; use libimagstore::storeid::StoreId; use util::IsHabitCheck; +use error::Result; +use error::HabitError as HE; pub struct HabitTemplateStoreIdIterator(StoreIdIterator); impl Iterator for HabitTemplateStoreIdIterator { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { while let Some(n) = self.0.next() { - if n.is_habit_template() { - return Some(n) + match n { + Ok(n) => if n.is_habit_template() { + return Some(Ok(n)) + }, + Err(e) => return Some(Err(e).map_err(HE::from)), } } None @@ -59,12 +64,15 @@ impl HabitInstanceStoreIdIterator { } impl Iterator for HabitInstanceStoreIdIterator { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { while let Some(n) = self.0.next() { - if n.is_habit_instance() { - return Some(n) + match n { + Ok(n) => if n.is_habit_instance() { + return Some(Ok(n)); + }, + Err(e) => return Some(Err(e).map_err(HE::from)), } } None diff --git a/lib/domain/libimagnotes/src/iter.rs b/lib/domain/libimagnotes/src/iter.rs index 263506c7..98adbbd9 100644 --- a/lib/domain/libimagnotes/src/iter.rs +++ b/lib/domain/libimagnotes/src/iter.rs @@ -21,6 +21,8 @@ use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreIdIterator; use notestoreid::*; +use error::Result; +use error::NoteError as NE; #[derive(Debug)] pub struct NoteIterator(StoreIdIterator); @@ -34,12 +36,15 @@ impl NoteIterator { } impl Iterator for NoteIterator { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { while let Some(n) = self.0.next() { - if n.is_note_id() { - return Some(n); + match n { + Ok(n) => if n.is_note_id() { + return Some(Ok(n)); + }, + Err(e) => return Some(Err(e).map_err(NE::from)), } } diff --git a/lib/domain/libimagtimetrack/src/iter/get.rs b/lib/domain/libimagtimetrack/src/iter/get.rs index e0433958..fdb55c20 100644 --- a/lib/domain/libimagtimetrack/src/iter/get.rs +++ b/lib/domain/libimagtimetrack/src/iter/get.rs @@ -37,12 +37,15 @@ impl<'a> Iterator for TimeTrackingsGetIterator<'a> { fn next(&mut self) -> Option { while let Some(next) = self.0.next() { - if next.is_in_collection(&[CRATE_NAME]) { - return match self.1.get(next) { - Ok(Some(fle)) => Some(Ok(fle)), - Ok(None) => continue, - Err(e) => Some(Err(e)) - }; + match next { + Err(e) => return Some(Err(e)), + Ok(next) => if next.is_in_collection(&[CRATE_NAME]) { + return match self.1.get(next) { + Ok(Some(fle)) => Some(Ok(fle)), + Ok(None) => continue, + Err(e) => Some(Err(e)) + }; + } } } diff --git a/lib/domain/libimagtimetrack/src/iter/mod.rs b/lib/domain/libimagtimetrack/src/iter/mod.rs index f0648ce2..556d8b93 100644 --- a/lib/domain/libimagtimetrack/src/iter/mod.rs +++ b/lib/domain/libimagtimetrack/src/iter/mod.rs @@ -26,6 +26,8 @@ pub mod tag; #[cfg(test)] mod test { + use std::sync::Arc; + use chrono::naive::NaiveDate; use libimagstore::store::Store; @@ -37,7 +39,7 @@ mod test { use std::path::PathBuf; use libimagstore::file_abstraction::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/domain/libimagtodo/src/iter.rs b/lib/domain/libimagtodo/src/iter.rs index c2871c5a..c5c63943 100644 --- a/lib/domain/libimagtodo/src/iter.rs +++ b/lib/domain/libimagtodo/src/iter.rs @@ -20,6 +20,9 @@ use libimagstore::storeid::StoreIdIterator; use libimagstore::storeid::StoreId; +use error::Result; +use error::TodoError as TE; + pub struct TaskIdIterator(StoreIdIterator); impl TaskIdIterator { @@ -31,14 +34,15 @@ impl TaskIdIterator { } impl Iterator for TaskIdIterator { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { loop { match self.0.next() { None => return None, - Some(n) => if n.is_in_collection(&["todo", "taskwarrior"]) { - return Some(n) + Some(Err(e)) => return Some(Err(e).map_err(TE::from)), + Some(Ok(n)) => if n.is_in_collection(&["todo", "taskwarrior"]) { + return Some(Ok(n)) }, // else continue } } diff --git a/lib/domain/libimagwiki/src/wiki.rs b/lib/domain/libimagwiki/src/wiki.rs index 50ef61cd..0612bec8 100644 --- a/lib/domain/libimagwiki/src/wiki.rs +++ b/lib/domain/libimagwiki/src/wiki.rs @@ -108,12 +108,15 @@ impl<'a, 'b> Wiki<'a, 'b> { pub struct WikiIdIterator<'a>(StoreIdIteratorWithStore<'a>, IdIsInWikiFilter<'a>); impl<'a> Iterator for WikiIdIterator<'a> { - type Item = StoreId; + type Item = Result; fn next(&mut self) -> Option { while let Some(next) = self.0.next() { - if self.1.filter(&next) { - return Some(next) + match next { + Ok(next) => if self.1.filter(&next) { + return Some(Ok(next)); + }, + Err(e) => return Some(Err(e).map_err(WE::from)), } } diff --git a/lib/entry/libimagentryannotation/src/annotateable.rs b/lib/entry/libimagentryannotation/src/annotateable.rs index 4906b174..d38b9c66 100644 --- a/lib/entry/libimagentryannotation/src/annotateable.rs +++ b/lib/entry/libimagentryannotation/src/annotateable.rs @@ -92,7 +92,7 @@ impl Annotateable for Entry { fn annotations<'a>(&self, store: &'a Store) -> Result> { self.get_internal_links() .map_err(From::from) - .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone())))) + .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone()).map(Ok)))) .map(|i| AnnotationIter::new(i, store)) } diff --git a/lib/entry/libimagentryannotation/src/iter.rs b/lib/entry/libimagentryannotation/src/iter.rs index 996c6ffd..9485ba07 100644 --- a/lib/entry/libimagentryannotation/src/iter.rs +++ b/lib/entry/libimagentryannotation/src/iter.rs @@ -24,6 +24,7 @@ use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreIdIterator; use error::Result; +use error::AnnotationError as AE; use error::AnnotationErrorKind as AEK; use error::ResultExt; @@ -43,18 +44,21 @@ impl<'a> Iterator for AnnotationIter<'a> { fn next(&mut self) -> Option { loop { - match self.0.next().map(|id| self.1.get(id)) { - Some(Ok(Some(entry))) => { - match entry.get_header().read_bool("annotation.is_annotation").chain_err(|| AEK::HeaderReadError) { - Ok(None) => continue, // not an annotation - Ok(Some(false)) => continue, - Ok(Some(true)) => return Some(Ok(entry)), - Err(e) => return Some(Err(e)), - } - }, - Some(Ok(None)) => continue, - Some(Err(e)) => return Some(Err(e).chain_err(|| AEK::StoreReadError)), - None => return None, // iterator consumed + match self.0.next() { + None => return None, // iterator consumed + Some(Err(e)) => return Some(Err(e).map_err(AE::from)), + Some(Ok(id)) => match self.1.get(id) { + Err(e) => return Some(Err(e).chain_err(|| AEK::StoreReadError)), + Ok(Some(entry)) => { + match entry.get_header().read_bool("annotation.is_annotation").chain_err(|| AEK::HeaderReadError) { + Ok(None) => continue, // not an annotation + Ok(Some(false)) => continue, + Ok(Some(true)) => return Some(Ok(entry)), + Err(e) => return Some(Err(e)), + } + }, + Ok(None) => continue, + } } } } diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index fab8715f..8da3342f 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -55,7 +55,7 @@ impl Category for Entry { fn get_entries<'a>(&self, store: &'a Store) -> Result> { trace!("Getting linked entries for category '{:?}'", self.get_location()); - let sit = self.get_internal_links()?.map(|l| l.get_store_id().clone()); + let sit = self.get_internal_links()?.map(|l| l.get_store_id().clone()).map(Ok); let sit = StoreIdIterator::new(Box::new(sit)); let name = self.get_name()?; Ok(CategoryEntryIterator::new(store, sit, name)) diff --git a/lib/entry/libimagentrycategory/src/iter.rs b/lib/entry/libimagentrycategory/src/iter.rs index a835b82a..ac143025 100644 --- a/lib/entry/libimagentrycategory/src/iter.rs +++ b/lib/entry/libimagentrycategory/src/iter.rs @@ -60,18 +60,23 @@ impl<'a> Iterator for CategoryNameIter<'a> { let query = CATEGORY_REGISTER_NAME_FIELD_PATH; while let Some(sid) = self.1.next() { - if sid.is_in_collection(&["category"]) { - let func = |store: &Store| { // hack for returning Some(Result<_, _>) - store - .get(sid)? - .ok_or_else(|| CE::from_kind(CEK::StoreReadError))? - .get_header() - .read_string(query) - .chain_err(|| CEK::HeaderReadError)? - .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) - }; + match sid { + Err(e) => return Some(Err(e).map_err(CE::from)), + Ok(sid) => { + if sid.is_in_collection(&["category"]) { + let func = |store: &Store| { // hack for returning Some(Result<_, _>) + store + .get(sid)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError))? + .get_header() + .read_string(query) + .chain_err(|| CEK::HeaderReadError)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) + }; - return Some(func(&self.0)) + return Some(func(&self.0)) + } + }, } // else continue } @@ -92,20 +97,25 @@ impl<'a> Iterator for CategoryEntryIterator<'a> { fn next(&mut self) -> Option { while let Some(next) = self.1.next() { - let getter = |next| -> Result<(String, FileLockEntry<'a>)> { - let entry = self.0 - .get(next)? - .ok_or_else(|| CE::from_kind(CEK::StoreReadError))?; - Ok((entry.get_category()?, entry)) - }; + match next { + Err(e) => return Some(Err(e).map_err(CE::from)), + Ok(next) => { + let getter = |next| -> Result<(String, FileLockEntry<'a>)> { + let entry = self.0 + .get(next)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError))?; + Ok((entry.get_category()?, entry)) + }; - match getter(next) { - Err(e) => return Some(Err(e)), - Ok((c, e)) => { - if c == self.2 { - return Some(Ok(e)) - // } else { - // continue + match getter(next) { + Err(e) => return Some(Err(e)), + Ok((c, e)) => { + if c == self.2 { + return Some(Ok(e)) + // } else { + // continue + } + } } } } diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index e1fb929a..8179010d 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -111,6 +111,7 @@ impl CategoryStore for Store { mod tests { extern crate env_logger; use std::path::PathBuf; + use std::sync::Arc; use super::*; @@ -118,7 +119,7 @@ mod tests { pub fn get_store() -> Store { use libimagstore::store::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/entry/libimagentrydatetime/src/datetime.rs b/lib/entry/libimagentrydatetime/src/datetime.rs index 6eb6683d..790f9f84 100644 --- a/lib/entry/libimagentrydatetime/src/datetime.rs +++ b/lib/entry/libimagentrydatetime/src/datetime.rs @@ -195,7 +195,7 @@ fn val_to_ndt(v: &Value) -> Result { #[cfg(test)] mod tests { use std::path::PathBuf; - use toml_query::read::TomlValueReadExt; + use std::sync::Arc; use super::*; @@ -204,10 +204,11 @@ mod tests { use chrono::naive::NaiveDateTime; use chrono::naive::NaiveDate; use chrono::naive::NaiveTime; + use toml_query::read::TomlValueReadExt; pub fn get_store() -> Store { use libimagstore::store::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/entry/libimagentrygps/src/entry.rs b/lib/entry/libimagentrygps/src/entry.rs index 37acb075..d6eb4be7 100644 --- a/lib/entry/libimagentrygps/src/entry.rs +++ b/lib/entry/libimagentrygps/src/entry.rs @@ -102,6 +102,7 @@ impl GPSEntry for Entry { #[cfg(test)] mod tests { use std::path::PathBuf; + use std::sync::Arc; use libimagstore::store::Store; @@ -113,7 +114,7 @@ mod tests { fn get_store() -> Store { use libimagstore::file_abstraction::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/entry/libimagentrylink/src/external.rs b/lib/entry/libimagentrylink/src/external.rs index 4d7d48bc..2d5592c6 100644 --- a/lib/entry/libimagentrylink/src/external.rs +++ b/lib/entry/libimagentrylink/src/external.rs @@ -406,6 +406,7 @@ impl ExternalLinker for Entry { mod tests { use super::*; use std::path::PathBuf; + use std::sync::Arc; use libimagstore::store::Store; @@ -416,7 +417,7 @@ mod tests { pub fn get_store() -> Store { use libimagstore::file_abstraction::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/entry/libimagentrylink/src/internal.rs b/lib/entry/libimagentrylink/src/internal.rs index e7c06fd7..480a07bc 100644 --- a/lib/entry/libimagentrylink/src/internal.rs +++ b/lib/entry/libimagentrylink/src/internal.rs @@ -772,6 +772,7 @@ pub mod store_check { #[cfg(test)] mod test { use std::path::PathBuf; + use std::sync::Arc; use libimagstore::store::Store; @@ -784,7 +785,7 @@ mod test { pub fn get_store() -> Store { use libimagstore::file_abstraction::InMemoryFileAbstraction; - let backend = Box::new(InMemoryFileAbstraction::default()); + let backend = Arc::new(InMemoryFileAbstraction::default()); Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap() } diff --git a/lib/entry/libimagentrymarkdown/src/processor.rs b/lib/entry/libimagentrymarkdown/src/processor.rs index f9b085a5..5fddcd9e 100644 --- a/lib/entry/libimagentrymarkdown/src/processor.rs +++ b/lib/entry/libimagentrymarkdown/src/processor.rs @@ -233,6 +233,7 @@ mod tests { use super::*; use std::path::PathBuf; + use std::sync::Arc; use libimagstore::store::Store; use libimagentrylink::internal::InternalLinker; @@ -244,7 +245,7 @@ mod tests { pub fn get_store() -> Store { use libimagstore::file_abstraction::InMemoryFileAbstraction; let fs = InMemoryFileAbstraction::default(); - Store::new_with_backend(PathBuf::from("/"), &None, Box::new(fs)).unwrap() + Store::new_with_backend(PathBuf::from("/"), &None, Arc::new(fs)).unwrap() } #[test]