Merge pull request #1471 from matthiasbeyer/libimagstore/store-entries-do-not-collect

libimagstore: Do not collect in Iterators
This commit is contained in:
Matthias Beyer 2018-05-01 22:14:26 +02:00 committed by GitHub
commit 195d921218
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 317 additions and 361 deletions

View file

@ -89,7 +89,7 @@ fn main() {
let edit_header = rt.cli().is_present("edit-header"); let edit_header = rt.cli().is_present("edit-header");
let edit_header_only = rt.cli().is_present("edit-header-only"); 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()) .into_get_iter(rt.store())
.trace_unwrap_exit(1) .trace_unwrap_exit(1)
.map(|o| o.unwrap_or_else(|| { .map(|o| o.unwrap_or_else(|| {

View file

@ -45,6 +45,7 @@ use filters::filter::Filter;
use libimagrt::setup::generate_runtime_setup; use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace; use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
@ -86,6 +87,7 @@ fn main() {
rt.store() rt.store()
.entries() .entries()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter(|id| collection_filter.filter(id)) .filter(|id| collection_filter.filter(id))
.map(|id| if print_storepath { .map(|id| if print_storepath {
id id

View file

@ -54,7 +54,6 @@ extern crate libimagutil;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit;
use libimagentrylink::external::ExternalLinker; use libimagentrylink::external::ExternalLinker;
use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::InternalLinker;
@ -255,12 +254,11 @@ fn unlink(rt: &Runtime) {
.map(PathBuf::from) .map(PathBuf::from)
.collect::<Vec<PathBuf>>().into_iter() // for lifetime inference .collect::<Vec<PathBuf>>().into_iter() // for lifetime inference
.map(StoreId::new_baseless) .map(StoreId::new_baseless)
.unwrap_with(|e| { trace_error(&e); exit(1) })
.into_get_iter(rt.store()) .into_get_iter(rt.store())
.unwrap_with(|e| { trace_error(&e); exit(1) }) .trace_unwrap_exit(1)
.filter_map(|e| e) .filter_map(|x| x)
.map(|mut entry| entry.unlink(rt.store())) .map(|mut entry| entry.unlink(rt.store()))
.unwrap_with(|e| { trace_error(&e); exit(1) }) .trace_unwrap_exit(1)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
} }

View file

@ -49,9 +49,11 @@ use std::path::PathBuf;
use libimagrt::setup::generate_runtime_setup; use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace; use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagstore::error::StoreError;
use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::InternalLinker;
use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::iter::get::StoreIdGetIteratorExtension;
@ -91,11 +93,11 @@ fn main() {
}) })
.get_internal_links() .get_internal_links()
.map_err_trace_exit_unwrap(1) .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()) .into_get_iter(rt.store())
.trace_unwrap_exit(1)
.map(|e| { .map(|e| {
e.map_err_trace_exit_unwrap(1) e.unwrap_or_else(|| {
.unwrap_or_else(|| {
error!("Linked entry does not exist"); error!("Linked entry does not exist");
exit(1) exit(1)
}) })

View file

@ -68,10 +68,10 @@ use libimagentryview::builtin::md::MarkdownViewer;
use libimagentryview::viewer::Viewer; use libimagentryview::viewer::Viewer;
use libimagentryview::error::ViewError as VE; use libimagentryview::error::ViewError as VE;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::error::StoreError; use libimagstore::error::StoreError;
use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
mod ui; mod ui;
use ui::build_ui; use ui::build_ui;
@ -89,11 +89,10 @@ fn main() {
if rt.cli().is_present("in") { if rt.cli().is_present("in") {
let files = entry_ids let files = entry_ids
.into_iter()
.into_get_iter(rt.store()) .into_get_iter(rt.store())
.trace_unwrap_exit(1)
.map(|e| { .map(|e| {
e.map_err_trace_exit_unwrap(1) e.ok_or_else(|| String::from("Entry not found"))
.ok_or_else(|| String::from("Entry not found"))
.map_err(StoreError::from) .map_err(StoreError::from)
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
}) })
@ -175,7 +174,6 @@ fn main() {
drop(files); drop(files);
} else { } else {
let iter = entry_ids let iter = entry_ids
.into_iter()
.into_get_iter(rt.store()) .into_get_iter(rt.store())
.map(|e| { .map(|e| {
e.map_err_trace_exit_unwrap(1) e.map_err_trace_exit_unwrap(1)
@ -249,13 +247,13 @@ fn main() {
} }
} }
fn entry_ids(rt: &Runtime) -> Vec<StoreId> { fn entry_ids(rt: &Runtime) -> StoreIdIterator {
match rt.cli().values_of("id") { match rt.cli().values_of("id") {
Some(pathes) => pathes Some(p) => {
.map(PathBuf::from) let pathes : Vec<String> = p.map(String::from).collect();
.map(PathBuf::into_storeid) let iter = pathes.into_iter().map(PathBuf::from).map(PathBuf::into_storeid);
.trace_unwrap_exit(1) StoreIdIterator::new(Box::new(iter))
.collect(), },
None => if rt.cli().is_present("entries-from-stdin") { None => if rt.cli().is_present("entries-from-stdin") {
let stdin = rt.stdin().unwrap_or_else(|| { let stdin = rt.stdin().unwrap_or_else(|| {
@ -269,11 +267,10 @@ fn entry_ids(rt: &Runtime) -> Vec<StoreId> {
::std::process::exit(1) ::std::process::exit(1)
}); });
buf.lines() let lines : Vec<String> = buf.lines().map(String::from).collect();
.map(PathBuf::from) let iter = lines.into_iter().map(PathBuf::from).map(PathBuf::into_storeid);
.map(PathBuf::into_storeid)
.trace_unwrap_exit(1) StoreIdIterator::new(Box::new(iter))
.collect()
} else { } else {
error!("Something weird happened. I was not able to find the path of the entries to edit"); error!("Something weird happened. I was not able to find the path of the entries to edit");
::std::process::exit(1) ::std::process::exit(1)

View file

@ -23,6 +23,7 @@ use libimagdiary::diary::Diary;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagutil::warn_exit::warn_exit; use libimagutil::warn_exit::warn_exit;
use libimagerror::trace::MapErrTrace; use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagutil::debug_result::*; use libimagutil::debug_result::*;
@ -40,6 +41,7 @@ pub fn list(rt: &Runtime) {
let mut ids = Diary::entries(rt.store(), &diaryname) let mut ids = Diary::entries(rt.store(), &diaryname)
.map_dbg_str("Ok") .map_dbg_str("Ok")
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.map(|id| DiaryId::from_storeid(&id)) .map(|id| DiaryId::from_storeid(&id))
.collect::<Result<Vec<_>>>() .collect::<Result<Vec<_>>>()
.map_err_trace_exit_unwrap(1); .map_err_trace_exit_unwrap(1);

View file

@ -21,6 +21,7 @@ use libimagdiary::diary::Diary;
use libimagdiary::viewer::DiaryViewer as DV; use libimagdiary::viewer::DiaryViewer as DV;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagerror::trace::MapErrTrace; use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagutil::warn_exit::warn_exit; use libimagutil::warn_exit::warn_exit;
use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagentryview::viewer::Viewer; use libimagentryview::viewer::Viewer;
@ -34,7 +35,7 @@ pub fn view(rt: &Runtime) {
let entries = Diary::entries(rt.store(), &diaryname) let entries = Diary::entries(rt.store(), &diaryname)
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.into_get_iter(rt.store()) .into_get_iter(rt.store())
.filter_map(Result::ok) .trace_unwrap_exit(1)
.map(|e| e.unwrap_or_else(|| { .map(|e| e.unwrap_or_else(|| {
error!("Failed to fetch entry"); error!("Failed to fetch entry");
::std::process::exit(1) ::std::process::exit(1)

View file

@ -57,6 +57,7 @@ use prettytable::row::Row;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup; use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::trace::{MapErrTrace, trace_error};
use libimagerror::iter::TraceIterator;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
use libimaghabit::store::HabitStore; use libimaghabit::store::HabitStore;
@ -167,6 +168,7 @@ fn delete(rt: &Runtime) {
.store() .store()
.all_habit_templates() .all_habit_templates()
.map_err_trace_exit_unwrap(1) .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 .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 .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, &Some(ref h) => h.habit_name().map_err_trace_exit_unwrap(1) == name,
@ -198,6 +200,7 @@ fn delete(rt: &Runtime) {
fle fle
.linked_instances() .linked_instances()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(get_instance) .filter_map(get_instance)
.filter(has_template_name) .filter(has_template_name)
.map(instance_location) .map(instance_location)
@ -249,6 +252,7 @@ fn today(rt: &Runtime, future: bool) {
.store() .store()
.all_habit_templates() .all_habit_templates()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(|id| match rt.store().get(id.clone()) { .filter_map(|id| match rt.store().get(id.clone()) {
Ok(Some(h)) => Some(h), Ok(Some(h)) => Some(h),
Ok(None) => { Ok(None) => {
@ -396,6 +400,7 @@ fn list(rt: &Runtime) {
.store() .store()
.all_habit_templates() .all_habit_templates()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(|id| match rt.store().get(id.clone()) { .filter_map(|id| match rt.store().get(id.clone()) {
Ok(Some(h)) => Some(h), Ok(Some(h)) => Some(h),
Ok(None) => { Ok(None) => {
@ -451,6 +456,7 @@ fn show(rt: &Runtime) {
.store() .store()
.all_habit_templates() .all_habit_templates()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(|id| get_from_store(rt.store(), id)) .filter_map(|id| get_from_store(rt.store(), id))
.filter(|h| h.habit_name().map(|n| name == n).map_err_trace_exit_unwrap(1)) .filter(|h| h.habit_name().map(|n| name == n).map_err_trace_exit_unwrap(1))
.enumerate() .enumerate()
@ -474,6 +480,7 @@ fn show(rt: &Runtime) {
let _ = habit let _ = habit
.linked_instances() .linked_instances()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(|instance_id| { .filter_map(|instance_id| {
debug!("Getting: {:?}", instance_id); debug!("Getting: {:?}", instance_id);
rt.store().get(instance_id).map_err_trace_exit_unwrap(1) rt.store().get(instance_id).map_err_trace_exit_unwrap(1)
@ -505,6 +512,7 @@ fn done(rt: &Runtime) {
.store() .store()
.all_habit_templates() .all_habit_templates()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter_map(|id| get_from_store(rt.store(), id)) .filter_map(|id| get_from_store(rt.store(), id))
.filter(|h| { .filter(|h| {
let due = h.next_instance_date().map_err_trace_exit_unwrap(1); let due = h.next_instance_date().map_err_trace_exit_unwrap(1);

View file

@ -43,6 +43,7 @@ extern crate libimagutil;
use std::io::Write; use std::io::Write;
use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::trace::{MapErrTrace, trace_error};
use libimagerror::iter::TraceIterator;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
use libimagmail::mail::Mail; use libimagmail::mail::Mail;
@ -143,6 +144,7 @@ fn list(rt: &Runtime) {
let _ = rt.store() let _ = rt.store()
.entries() .entries()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.filter(|id| id.is_in_collection(&["mail"])) .filter(|id| id.is_in_collection(&["mail"]))
.filter_map(|id| { .filter_map(|id| {
rt.store() rt.store()

View file

@ -50,6 +50,7 @@ use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup; use libimagrt::setup::generate_runtime_setup;
use libimagtodo::taskstore::TaskStore; use libimagtodo::taskstore::TaskStore;
use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::trace::{MapErrTrace, trace_error};
use libimagerror::iter::TraceIterator;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
@ -124,7 +125,7 @@ fn list(rt: &Runtime) {
let res = rt.store().all_tasks() // get all tasks let res = rt.store().all_tasks() // get all tasks
.map(|iter| { // and if this succeeded .map(|iter| { // and if this succeeded
// filter out the ones were we can read the uuid // 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) { match rt.store().retrieve(storeid) {
Ok(fle) => { Ok(fle) => {
match fle.get_header().read_string("todo.uuid") { match fle.get_header().read_string("todo.uuid") {

View file

@ -34,6 +34,7 @@ use std::io::Write;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup; use libimagrt::setup::generate_runtime_setup;
use libimagerror::iter::TraceIterator;
use libimagerror::trace::MapErrTrace; use libimagerror::trace::MapErrTrace;
use libimagerror::exit::ExitUnwrap; use libimagerror::exit::ExitUnwrap;
use libimagerror::io::ToExitCode; use libimagerror::io::ToExitCode;
@ -90,6 +91,7 @@ fn ids(rt: &Runtime, wiki_name: &str) {
}) })
.all_ids() .all_ids()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.trace_unwrap_exit(1)
.for_each(|id| { .for_each(|id| {
let _ = writeln!(outlock, "{}{}", prefix, id) let _ = writeln!(outlock, "{}{}", prefix, id)
.to_exit_code() .to_exit_code()

View file

@ -22,6 +22,7 @@ use std::process::Command;
use std::env; use std::env;
use std::process::exit; use std::process::exit;
use std::io::Stdin; use std::io::Stdin;
use std::sync::Arc;
pub use clap::App; pub use clap::App;
use clap::AppSettings; use clap::AppSettings;
@ -132,7 +133,7 @@ impl<'a> Runtime<'a> {
let store_result = if cli_app.use_inmemory_fs() { let store_result = if cli_app.use_inmemory_fs() {
Store::new_with_backend(storepath, Store::new_with_backend(storepath,
&config, &config,
Box::new(InMemoryFileAbstraction::default())) Arc::new(InMemoryFileAbstraction::default()))
} else { } else {
Store::new(storepath, &config) Store::new(storepath, &config)
}; };

View file

@ -168,20 +168,15 @@ impl FileAbstraction for FSFileAbstraction {
fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE> { fn pathes_recursively(&self, basepath: PathBuf) -> Result<PathIterator, SE> {
use walkdir::WalkDir; use walkdir::WalkDir;
let i : Result<Vec<PathBuf>, SE> = WalkDir::new(basepath) let i = WalkDir::new(basepath)
.min_depth(1) .min_depth(1)
.max_open(100)
.into_iter() .into_iter()
.map(|r| { .map(|r| {
r.map(|e| PathBuf::from(e.path())) r.map(|e| PathBuf::from(e.path())).chain_err(|| SE::from_kind(SEK::FileError))
.chain_err(|| SE::from_kind(SEK::FileError))
})
.fold(Ok(vec![]), |acc, e| {
acc.and_then(move |mut a| {
a.push(e?);
Ok(a)
})
}); });
Ok(PathIterator::new(Box::new(i?.into_iter())))
Ok(PathIterator::new(Box::new(i)))
} }
} }

View file

@ -183,15 +183,15 @@ impl FileAbstraction for InMemoryFileAbstraction {
fn pathes_recursively(&self, _basepath: PathBuf) -> Result<PathIterator, SE> { fn pathes_recursively(&self, _basepath: PathBuf) -> Result<PathIterator, SE> {
debug!("Getting all pathes"); debug!("Getting all pathes");
let keys : Vec<PathBuf> = self let keys : Vec<Result<PathBuf, SE>> = self
.backend() .backend()
.lock() .lock()
.map_err(|_| SE::from_kind(SEK::FileError))? .map_err(|_| SE::from_kind(SEK::FileError))?
.get_mut() .get_mut()
.keys() .keys()
.map(PathBuf::from) .map(PathBuf::from)
.collect(); .map(Ok)
// we collect here as this happens only in tests and in memory anyways, so no problem .collect(); // we have to collect() because of the lock() above.
Ok(PathIterator::new(Box::new(keys.into_iter()))) Ok(PathIterator::new(Box::new(keys.into_iter())))
} }

View file

@ -18,20 +18,31 @@
// //
use std::path::PathBuf; 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 /// A wrapper for an iterator over `PathBuf`s
pub struct PathIterator(Box<Iterator<Item = PathBuf>>); pub struct PathIterator(Box<Iterator<Item = Result<PathBuf>>>);
impl PathIterator { impl PathIterator {
pub fn new(iter: Box<Iterator<Item = PathBuf>>) -> PathIterator { pub fn new(iter: Box<Iterator<Item = Result<PathBuf>>>) -> PathIterator {
PathIterator(iter) PathIterator(iter)
} }
pub fn store_id_constructing(self, storepath: PathBuf, backend: Arc<FileAbstraction>)
-> StoreIdConstructingIterator
{
StoreIdConstructingIterator(self, storepath, backend)
}
} }
impl Iterator for PathIterator { impl Iterator for PathIterator {
type Item = PathBuf; type Item = Result<PathBuf>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.0.next() 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<FileAbstraction>);
impl Iterator for StoreIdConstructingIterator {
type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> {
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
}
}

View file

@ -27,7 +27,7 @@ use storeid::StoreId;
mod fs; mod fs;
mod inmemory; mod inmemory;
mod iter; pub(crate) mod iter;
pub use self::fs::FSFileAbstraction; pub use self::fs::FSFileAbstraction;
pub use self::fs::FSFileAbstractionInstance; pub use self::fs::FSFileAbstractionInstance;

View file

@ -17,111 +17,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // 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<Iterator<Item = StoreId> + 'a>, &'a Store);
impl<'a> $itername<'a> {
pub fn new(inner: Box<Iterator<Item = StoreId> + 'a>, store: &'a Store) -> Self {
$itername(inner, store)
}
}
impl<'a> Iterator for $itername<'a> {
type Item = Result<$yield>;
fn next(&mut self) -> Option<Self::Item> {
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<Item = StoreId> + 'a
{
fn $extfnname(self, store: &'a Store) -> $itername<'a> {
$itername(Box::new(self), store)
}
}
}
}
use error::StoreError;
pub enum ExtensionError<E> {
Forwarded(E),
StoreError(StoreError)
}
macro_rules! mk_iterator_mod { 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<Item = RResult<StoreId, E>>
{
type Item = RResult<$yield, $crate::iter::ExtensionError<E>>;
fn next(&mut self) -> Option<Self::Item> {
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, modname = $modname:ident,
itername = $itername:ident, itername = $itername:ident,
@ -131,13 +27,47 @@ macro_rules! mk_iterator_mod {
fun = $fun:expr fun = $fun:expr
} => { } => {
pub mod $modname { pub mod $modname {
mk_iterator! { use storeid::StoreId;
modname = $modname, #[allow(unused_imports)]
itername = $itername, use store::FileLockEntry;
iteryield = $yield, use store::Store;
extname = $extname, use error::StoreError;
extfnname = $extfnname, use std::result::Result as RResult;
fun = $fun
pub struct $itername<'a, E>(Box<Iterator<Item = RResult<StoreId, E>> + 'a>, &'a Store)
where E: From<StoreError>;
impl<'a, E> $itername<'a, E>
where E: From<StoreError>
{
pub fn new(inner: Box<Iterator<Item = RResult<StoreId, E>> + 'a>, store: &'a Store) -> Self {
$itername(inner, store)
}
}
impl<'a, E> Iterator for $itername<'a, E>
where E: From<StoreError>
{
type Item = RResult<$yield, E>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|id| $fun(id?, self.1).map_err(E::from))
}
}
pub trait $extname<'a, E>
where E: From<StoreError>
{
fn $extfnname(self, store: &'a Store) -> $itername<'a, E>;
}
impl<'a, I, E> $extname<'a, E> for I
where I: Iterator<Item = RResult<StoreId, E>> + 'a,
E: From<StoreError>
{
fn $extfnname(self, store: &'a Store) -> $itername<'a, E> {
$itername(Box::new(self), store)
}
} }
} }
} }
@ -149,9 +79,7 @@ mk_iterator_mod! {
iteryield = FileLockEntry<'a>, iteryield = FileLockEntry<'a>,
extname = StoreIdCreateIteratorExtension, extname = StoreIdCreateIteratorExtension,
extfnname = into_create_iter, extfnname = into_create_iter,
fun = |id: StoreId, store: &'a Store| store.create(id), fun = |id: StoreId, store: &'a Store| store.create(id)
resultitername = StoreCreateResultIterator,
resultextname = StoreIdCreateResultIteratorExtension
} }
mk_iterator_mod! { mk_iterator_mod! {
@ -160,9 +88,7 @@ mk_iterator_mod! {
iteryield = (), iteryield = (),
extname = StoreIdDeleteIteratorExtension, extname = StoreIdDeleteIteratorExtension,
extfnname = into_delete_iter, extfnname = into_delete_iter,
fun = |id: StoreId, store: &'a Store| store.delete(id), fun = |id: StoreId, store: &'a Store| store.delete(id)
resultitername = StoreDeleteResultIterator,
resultextname = StoreIdDeleteResultIteratorExtension
} }
mk_iterator_mod! { mk_iterator_mod! {
@ -171,9 +97,7 @@ mk_iterator_mod! {
iteryield = Option<FileLockEntry<'a>>, iteryield = Option<FileLockEntry<'a>>,
extname = StoreIdGetIteratorExtension, extname = StoreIdGetIteratorExtension,
extfnname = into_get_iter, extfnname = into_get_iter,
fun = |id: StoreId, store: &'a Store| store.get(id), fun = |id: StoreId, store: &'a Store| store.get(id)
resultitername = StoreGetResultIterator,
resultextname = StoreIdGetResultIteratorExtension
} }
mk_iterator_mod! { mk_iterator_mod! {
@ -182,9 +106,7 @@ mk_iterator_mod! {
iteryield = FileLockEntry<'a>, iteryield = FileLockEntry<'a>,
extname = StoreIdRetrieveIteratorExtension, extname = StoreIdRetrieveIteratorExtension,
extfnname = into_retrieve_iter, extfnname = into_retrieve_iter,
fun = |id: StoreId, store: &'a Store| store.retrieve(id), fun = |id: StoreId, store: &'a Store| store.retrieve(id)
resultitername = StoreRetrieveResultIterator,
resultextname = StoreIdRetrieveResultIteratorExtension
} }
#[cfg(test)] #[cfg(test)]

View file

@ -137,7 +137,7 @@ impl Iterator for Walk {
impl StoreEntry { impl StoreEntry {
fn new(id: StoreId, backend: &Box<FileAbstraction>) -> Result<StoreEntry> { fn new(id: StoreId, backend: &Arc<FileAbstraction>) -> Result<StoreEntry> {
let pb = id.clone().into_pathbuf()?; let pb = id.clone().into_pathbuf()?;
#[cfg(feature = "fs-lock")] #[cfg(feature = "fs-lock")]
@ -214,7 +214,7 @@ pub struct Store {
/// The backend to use /// The backend to use
/// ///
/// This provides the filesystem-operation functions (or pretends to) /// This provides the filesystem-operation functions (or pretends to)
backend: Box<FileAbstraction>, backend: Arc<FileAbstraction>,
} }
impl Store { impl Store {
@ -235,7 +235,7 @@ impl Store {
/// - On success: Store object /// - On success: Store object
/// ///
pub fn new(location: PathBuf, store_config: &Option<Value>) -> Result<Store> { pub fn new(location: PathBuf, store_config: &Option<Value>) -> Result<Store> {
let backend = Box::new(FSFileAbstraction::default()); let backend = Arc::new(FSFileAbstraction::default());
Store::new_with_backend(location, store_config, backend) Store::new_with_backend(location, store_config, backend)
} }
@ -245,7 +245,7 @@ impl Store {
/// Do not use directly, only for testing purposes. /// Do not use directly, only for testing purposes.
pub fn new_with_backend(location: PathBuf, pub fn new_with_backend(location: PathBuf,
store_config: &Option<Value>, store_config: &Option<Value>,
backend: Box<FileAbstraction>) -> Result<Store> { backend: Arc<FileAbstraction>) -> Result<Store> {
use configuration::*; use configuration::*;
debug!("Building new Store object"); debug!("Building new Store object");
@ -279,33 +279,6 @@ impl Store {
Ok(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<FileAbstraction>) -> Result<()> {
self.backend
.drain()
.and_then(|drain| backend.fill(drain))
.map(|_| self.backend = backend)
}
/// Creates the Entry at the given location (inside the entry) /// Creates the Entry at the given location (inside the entry)
/// ///
/// # Return value /// # Return value
@ -741,25 +714,12 @@ impl Store {
} }
/// Get _all_ entries in the store (by id as iterator) /// Get _all_ entries in the store (by id as iterator)
pub fn entries<'a>(&'a self) -> Result<StoreIdIteratorWithStore<'a>> { pub fn entries(&self) -> Result<StoreIdIteratorWithStore> {
self.backend self.backend
.pathes_recursively(self.path().clone()) .pathes_recursively(self.path().clone())
.and_then(|iter| { .map(|i| i.store_id_constructing(self.path().clone(), self.backend.clone()))
let mut elems = vec![]; .map(Box::new)
for element in iter { .map(|it| StoreIdIteratorWithStore::new(it, self))
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))
})
} }
/// Gets the path where this store is on the disk /// Gets the path where this store is on the disk
@ -1215,12 +1175,13 @@ Hai
#[cfg(test)] #[cfg(test)]
mod store_tests { mod store_tests {
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use super::Store; use super::Store;
use file_abstraction::InMemoryFileAbstraction; use file_abstraction::InMemoryFileAbstraction;
pub fn get_store() -> Store { 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() 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));
}
}
} }

View file

@ -241,7 +241,7 @@ macro_rules! module_entry_path_mod {
} }
pub struct StoreIdIterator { pub struct StoreIdIterator {
iter: Box<Iterator<Item = StoreId>>, iter: Box<Iterator<Item = Result<StoreId>>>,
} }
impl Debug for StoreIdIterator { impl Debug for StoreIdIterator {
@ -254,16 +254,16 @@ impl Debug for StoreIdIterator {
impl StoreIdIterator { impl StoreIdIterator {
pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator { pub fn new(iter: Box<Iterator<Item = Result<StoreId>>>) -> StoreIdIterator {
StoreIdIterator { iter } StoreIdIterator { iter }
} }
} }
impl Iterator for StoreIdIterator { impl Iterator for StoreIdIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<StoreId> { fn next(&mut self) -> Option<Self::Item> {
self.iter.next() self.iter.next()
} }
@ -280,16 +280,18 @@ impl<'a> Deref for StoreIdIteratorWithStore<'a> {
} }
impl<'a> Iterator for StoreIdIteratorWithStore<'a> { impl<'a> Iterator for StoreIdIteratorWithStore<'a> {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<StoreId> { fn next(&mut self) -> Option<Self::Item> {
self.0.next() self.0.next()
} }
} }
use error::StoreError;
impl<'a> StoreIdIteratorWithStore<'a> { impl<'a> StoreIdIteratorWithStore<'a> {
pub fn new(iter: Box<Iterator<Item = StoreId>>, store: &'a Store) -> Self { pub fn new(iter: Box<Iterator<Item = Result<StoreId>>>, store: &'a Store) -> Self {
StoreIdIteratorWithStore(StoreIdIterator::new(iter), store) StoreIdIteratorWithStore(StoreIdIterator::new(iter), store)
} }
@ -300,7 +302,7 @@ impl<'a> StoreIdIteratorWithStore<'a> {
/// Transform the iterator into a StoreCreateIterator /// Transform the iterator into a StoreCreateIterator
/// ///
/// This immitates the API from `libimagstore::iter`. /// 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) StoreCreateIterator::new(Box::new(self.0), self.1)
} }
@ -308,7 +310,7 @@ impl<'a> StoreIdIteratorWithStore<'a> {
/// ///
/// ///
/// This immitates the API from `libimagstore::iter`. /// 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) StoreDeleteIterator::new(Box::new(self.0), self.1)
} }
@ -316,7 +318,7 @@ impl<'a> StoreIdIteratorWithStore<'a> {
/// ///
/// ///
/// This immitates the API from `libimagstore::iter`. /// 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) StoreGetIterator::new(Box::new(self.0), self.1)
} }
@ -324,7 +326,7 @@ impl<'a> StoreIdIteratorWithStore<'a> {
/// ///
/// ///
/// This immitates the API from `libimagstore::iter`. /// 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) StoreRetrieveIterator::new(Box::new(self.0), self.1)
} }

View file

@ -43,8 +43,9 @@ impl<'a> Iterator for ContactIter<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
match self.0.next() { match self.0.next() {
None => return None, None => return None,
Some(sid) => match self.1.get(sid.clone()).map_err(From::from) { 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)), Err(e) => return Some(Err(e)),
Ok(None) => return Some(Err(CE::from_kind(CEK::EntryNotFound(sid)))), Ok(None) => return Some(Err(CE::from_kind(CEK::EntryNotFound(sid)))),
Ok(Some(entry)) => match entry.is_contact().map_err(From::from) { Ok(Some(entry)) => match entry.is_contact().map_err(From::from) {

View file

@ -81,7 +81,10 @@ impl<'a> ContactStore<'a> for Store {
let iter = self let iter = self
.entries()? .entries()?
.without_store() .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))) Ok(StoreIdIterator::new(Box::new(iter)))
} }

View file

@ -94,13 +94,27 @@ impl Diary for Store {
.chain_err(|| DEK::StoreReadError) .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<Result<DiaryId>> { fn get_youngest_entry_id(&self, diary_name: &str) -> Option<Result<DiaryId>> {
use error::DiaryError as DE;
match Diary::entries(self, diary_name) { match Diary::entries(self, diary_name) {
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
Ok(entries) => { Ok(entries) => {
entries let mut sorted_entries = vec![];
.map(|e| DiaryId::from_storeid(&e))
.sorted_by(|a, b| { 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) { match (a, b) {
(&Ok(ref a), &Ok(ref b)) => { (&Ok(ref a), &Ok(ref b)) => {
let a : NaiveDateTime = a.clone().into(); let a : NaiveDateTime = a.clone().into();

View file

@ -103,16 +103,17 @@ impl Filter<StoreId> for DiaryEntryIterator {
} }
impl Iterator for DiaryEntryIterator { impl Iterator for DiaryEntryIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
match self.iter.next() { match self.iter.next() {
None => return None, None => return None,
Some(s) => { Some(Err(e)) => return Some(Err(e).map_err(DE::from)),
Some(Ok(s)) => {
debug!("Next element: {:?}", s); debug!("Next element: {:?}", s);
if Filter::filter(self, &s) { if Filter::filter(self, &s) {
return Some(s) return Some(Ok(s))
} else { } else {
continue continue
} }
@ -141,16 +142,19 @@ impl Iterator for DiaryNameIterator {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.0.next() { while let Some(next) = self.0.next() {
if next.is_in_collection(&["diary"]) { match next {
return Some(next Err(e) => return Some(Err(e).map_err(DE::from)),
.to_str() Ok(next) => if next.is_in_collection(&["diary"]) {
.chain_err(|| DEK::DiaryNameFindingError) return Some(next
.and_then(|s| { .to_str()
s.split("diary/") .chain_err(|| DEK::DiaryNameFindingError)
.nth(1) .and_then(|s| {
.and_then(|n| n.split("/").nth(0).map(String::from)) s.split("diary/")
.ok_or(DE::from_kind(DEK::DiaryNameFindingError)) .nth(1)
})) .and_then(|n| n.split("/").nth(0).map(String::from))
.ok_or(DE::from_kind(DEK::DiaryNameFindingError))
}));
},
} }
} }

View file

@ -131,7 +131,8 @@ impl HabitTemplate for Entry {
let iter = self let iter = self
.get_internal_links()? .get_internal_links()?
.map(|link| link.get_store_id().clone()) .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)); let sidi = StoreIdIterator::new(Box::new(iter));
Ok(HabitInstanceStoreIdIterator::new(sidi)) Ok(HabitInstanceStoreIdIterator::new(sidi))

View file

@ -22,16 +22,21 @@ use libimagstore::storeid::StoreIdIteratorWithStore;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use util::IsHabitCheck; use util::IsHabitCheck;
use error::Result;
use error::HabitError as HE;
pub struct HabitTemplateStoreIdIterator(StoreIdIterator); pub struct HabitTemplateStoreIdIterator(StoreIdIterator);
impl Iterator for HabitTemplateStoreIdIterator { impl Iterator for HabitTemplateStoreIdIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(n) = self.0.next() { while let Some(n) = self.0.next() {
if n.is_habit_template() { match n {
return Some(n) Ok(n) => if n.is_habit_template() {
return Some(Ok(n))
},
Err(e) => return Some(Err(e).map_err(HE::from)),
} }
} }
None None
@ -59,12 +64,15 @@ impl HabitInstanceStoreIdIterator {
} }
impl Iterator for HabitInstanceStoreIdIterator { impl Iterator for HabitInstanceStoreIdIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(n) = self.0.next() { while let Some(n) = self.0.next() {
if n.is_habit_instance() { match n {
return Some(n) Ok(n) => if n.is_habit_instance() {
return Some(Ok(n));
},
Err(e) => return Some(Err(e).map_err(HE::from)),
} }
} }
None None

View file

@ -21,6 +21,8 @@ use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator; use libimagstore::storeid::StoreIdIterator;
use notestoreid::*; use notestoreid::*;
use error::Result;
use error::NoteError as NE;
#[derive(Debug)] #[derive(Debug)]
pub struct NoteIterator(StoreIdIterator); pub struct NoteIterator(StoreIdIterator);
@ -34,12 +36,15 @@ impl NoteIterator {
} }
impl Iterator for NoteIterator { impl Iterator for NoteIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(n) = self.0.next() { while let Some(n) = self.0.next() {
if n.is_note_id() { match n {
return Some(n); Ok(n) => if n.is_note_id() {
return Some(Ok(n));
},
Err(e) => return Some(Err(e).map_err(NE::from)),
} }
} }

View file

@ -37,12 +37,15 @@ impl<'a> Iterator for TimeTrackingsGetIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.0.next() { while let Some(next) = self.0.next() {
if next.is_in_collection(&[CRATE_NAME]) { match next {
return match self.1.get(next) { Err(e) => return Some(Err(e)),
Ok(Some(fle)) => Some(Ok(fle)), Ok(next) => if next.is_in_collection(&[CRATE_NAME]) {
Ok(None) => continue, return match self.1.get(next) {
Err(e) => Some(Err(e)) Ok(Some(fle)) => Some(Ok(fle)),
}; Ok(None) => continue,
Err(e) => Some(Err(e))
};
}
} }
} }

View file

@ -26,6 +26,8 @@ pub mod tag;
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::sync::Arc;
use chrono::naive::NaiveDate; use chrono::naive::NaiveDate;
use libimagstore::store::Store; use libimagstore::store::Store;
@ -37,7 +39,7 @@ mod test {
use std::path::PathBuf; use std::path::PathBuf;
use libimagstore::file_abstraction::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -20,6 +20,9 @@
use libimagstore::storeid::StoreIdIterator; use libimagstore::storeid::StoreIdIterator;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use error::Result;
use error::TodoError as TE;
pub struct TaskIdIterator(StoreIdIterator); pub struct TaskIdIterator(StoreIdIterator);
impl TaskIdIterator { impl TaskIdIterator {
@ -31,14 +34,15 @@ impl TaskIdIterator {
} }
impl Iterator for TaskIdIterator { impl Iterator for TaskIdIterator {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
match self.0.next() { match self.0.next() {
None => return None, None => return None,
Some(n) => if n.is_in_collection(&["todo", "taskwarrior"]) { Some(Err(e)) => return Some(Err(e).map_err(TE::from)),
return Some(n) Some(Ok(n)) => if n.is_in_collection(&["todo", "taskwarrior"]) {
return Some(Ok(n))
}, // else continue }, // else continue
} }
} }

View file

@ -108,12 +108,15 @@ impl<'a, 'b> Wiki<'a, 'b> {
pub struct WikiIdIterator<'a>(StoreIdIteratorWithStore<'a>, IdIsInWikiFilter<'a>); pub struct WikiIdIterator<'a>(StoreIdIteratorWithStore<'a>, IdIsInWikiFilter<'a>);
impl<'a> Iterator for WikiIdIterator<'a> { impl<'a> Iterator for WikiIdIterator<'a> {
type Item = StoreId; type Item = Result<StoreId>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.0.next() { while let Some(next) = self.0.next() {
if self.1.filter(&next) { match next {
return Some(next) Ok(next) => if self.1.filter(&next) {
return Some(Ok(next));
},
Err(e) => return Some(Err(e).map_err(WE::from)),
} }
} }

View file

@ -92,7 +92,7 @@ impl Annotateable for Entry {
fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>> { fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>> {
self.get_internal_links() self.get_internal_links()
.map_err(From::from) .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)) .map(|i| AnnotationIter::new(i, store))
} }

View file

@ -24,6 +24,7 @@ use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreIdIterator; use libimagstore::storeid::StoreIdIterator;
use error::Result; use error::Result;
use error::AnnotationError as AE;
use error::AnnotationErrorKind as AEK; use error::AnnotationErrorKind as AEK;
use error::ResultExt; use error::ResultExt;
@ -43,18 +44,21 @@ impl<'a> Iterator for AnnotationIter<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
match self.0.next().map(|id| self.1.get(id)) { match self.0.next() {
Some(Ok(Some(entry))) => { None => return None, // iterator consumed
match entry.get_header().read_bool("annotation.is_annotation").chain_err(|| AEK::HeaderReadError) { Some(Err(e)) => return Some(Err(e).map_err(AE::from)),
Ok(None) => continue, // not an annotation Some(Ok(id)) => match self.1.get(id) {
Ok(Some(false)) => continue, Err(e) => return Some(Err(e).chain_err(|| AEK::StoreReadError)),
Ok(Some(true)) => return Some(Ok(entry)), Ok(Some(entry)) => {
Err(e) => return Some(Err(e)), match entry.get_header().read_bool("annotation.is_annotation").chain_err(|| AEK::HeaderReadError) {
} Ok(None) => continue, // not an annotation
}, Ok(Some(false)) => continue,
Some(Ok(None)) => continue, Ok(Some(true)) => return Some(Ok(entry)),
Some(Err(e)) => return Some(Err(e).chain_err(|| AEK::StoreReadError)), Err(e) => return Some(Err(e)),
None => return None, // iterator consumed }
},
Ok(None) => continue,
}
} }
} }
} }

View file

@ -55,7 +55,7 @@ impl Category for Entry {
fn get_entries<'a>(&self, store: &'a Store) -> Result<CategoryEntryIterator<'a>> { fn get_entries<'a>(&self, store: &'a Store) -> Result<CategoryEntryIterator<'a>> {
trace!("Getting linked entries for category '{:?}'", self.get_location()); 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 sit = StoreIdIterator::new(Box::new(sit));
let name = self.get_name()?; let name = self.get_name()?;
Ok(CategoryEntryIterator::new(store, sit, name)) Ok(CategoryEntryIterator::new(store, sit, name))

View file

@ -60,18 +60,23 @@ impl<'a> Iterator for CategoryNameIter<'a> {
let query = CATEGORY_REGISTER_NAME_FIELD_PATH; let query = CATEGORY_REGISTER_NAME_FIELD_PATH;
while let Some(sid) = self.1.next() { while let Some(sid) = self.1.next() {
if sid.is_in_collection(&["category"]) { match sid {
let func = |store: &Store| { // hack for returning Some(Result<_, _>) Err(e) => return Some(Err(e).map_err(CE::from)),
store Ok(sid) => {
.get(sid)? if sid.is_in_collection(&["category"]) {
.ok_or_else(|| CE::from_kind(CEK::StoreReadError))? let func = |store: &Store| { // hack for returning Some(Result<_, _>)
.get_header() store
.read_string(query) .get(sid)?
.chain_err(|| CEK::HeaderReadError)? .ok_or_else(|| CE::from_kind(CEK::StoreReadError))?
.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 } // else continue
} }
@ -92,20 +97,25 @@ impl<'a> Iterator for CategoryEntryIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.1.next() { while let Some(next) = self.1.next() {
let getter = |next| -> Result<(String, FileLockEntry<'a>)> { match next {
let entry = self.0 Err(e) => return Some(Err(e).map_err(CE::from)),
.get(next)? Ok(next) => {
.ok_or_else(|| CE::from_kind(CEK::StoreReadError))?; let getter = |next| -> Result<(String, FileLockEntry<'a>)> {
Ok((entry.get_category()?, entry)) let entry = self.0
}; .get(next)?
.ok_or_else(|| CE::from_kind(CEK::StoreReadError))?;
Ok((entry.get_category()?, entry))
};
match getter(next) { match getter(next) {
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
Ok((c, e)) => { Ok((c, e)) => {
if c == self.2 { if c == self.2 {
return Some(Ok(e)) return Some(Ok(e))
// } else { // } else {
// continue // continue
}
}
} }
} }
} }

View file

@ -111,6 +111,7 @@ impl CategoryStore for Store {
mod tests { mod tests {
extern crate env_logger; extern crate env_logger;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use super::*; use super::*;
@ -118,7 +119,7 @@ mod tests {
pub fn get_store() -> Store { pub fn get_store() -> Store {
use libimagstore::store::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -195,7 +195,7 @@ fn val_to_ndt(v: &Value) -> Result<NaiveDateTime> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::path::PathBuf; use std::path::PathBuf;
use toml_query::read::TomlValueReadExt; use std::sync::Arc;
use super::*; use super::*;
@ -204,10 +204,11 @@ mod tests {
use chrono::naive::NaiveDateTime; use chrono::naive::NaiveDateTime;
use chrono::naive::NaiveDate; use chrono::naive::NaiveDate;
use chrono::naive::NaiveTime; use chrono::naive::NaiveTime;
use toml_query::read::TomlValueReadExt;
pub fn get_store() -> Store { pub fn get_store() -> Store {
use libimagstore::store::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -102,6 +102,7 @@ impl GPSEntry for Entry {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use libimagstore::store::Store; use libimagstore::store::Store;
@ -113,7 +114,7 @@ mod tests {
fn get_store() -> Store { fn get_store() -> Store {
use libimagstore::file_abstraction::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -406,6 +406,7 @@ impl ExternalLinker for Entry {
mod tests { mod tests {
use super::*; use super::*;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use libimagstore::store::Store; use libimagstore::store::Store;
@ -416,7 +417,7 @@ mod tests {
pub fn get_store() -> Store { pub fn get_store() -> Store {
use libimagstore::file_abstraction::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -772,6 +772,7 @@ pub mod store_check {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use libimagstore::store::Store; use libimagstore::store::Store;
@ -784,7 +785,7 @@ mod test {
pub fn get_store() -> Store { pub fn get_store() -> Store {
use libimagstore::file_abstraction::InMemoryFileAbstraction; 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() Store::new_with_backend(PathBuf::from("/"), &None, backend).unwrap()
} }

View file

@ -233,6 +233,7 @@ mod tests {
use super::*; use super::*;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::InternalLinker;
@ -244,7 +245,7 @@ mod tests {
pub fn get_store() -> Store { pub fn get_store() -> Store {
use libimagstore::file_abstraction::InMemoryFileAbstraction; use libimagstore::file_abstraction::InMemoryFileAbstraction;
let fs = InMemoryFileAbstraction::default(); 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] #[test]