diff --git a/lib/core/libimagrt/src/logger.rs b/lib/core/libimagrt/src/logger.rs index 3090fb3f..ef586bbb 100644 --- a/lib/core/libimagrt/src/logger.rs +++ b/lib/core/libimagrt/src/logger.rs @@ -370,6 +370,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>) for (module_name, v) in t { let destinations = inner_try! { v.read("destinations") + .context("Failed reading header 'destinations'") .map_err(Error::from) .context(EM::TomlQueryError)? .map(|val| { @@ -384,6 +385,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>) let level = inner_try! { v.read_string("level") + .context("Failed reading header 'level'") .map_err(Error::from) .context(EM::TomlQueryError)? .map(|s| match_log_level_str(&s)) diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index a4cba80f..58321938 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -408,6 +408,7 @@ impl<'a> Runtime<'a> { let mut buf = String::new(); lock.read_to_string(&mut buf) + .context("Failed to read stdin to buffer") .map_err(Error::from) .and_then(|_| { trace!("Got IDs = {}", buf); diff --git a/lib/core/libimagstore/src/configuration.rs b/lib/core/libimagstore/src/configuration.rs index d0b3452d..3b9cc1e8 100644 --- a/lib/core/libimagstore/src/configuration.rs +++ b/lib/core/libimagstore/src/configuration.rs @@ -34,6 +34,7 @@ pub fn config_implicit_store_create_allowed(config: &Option) -> Result StoreIdWithBase<'a> { store_part.display()); let p = full_path .strip_prefix(store_part) + .context(format_err!("Cannot strip prefix '{}' from path: '{}'", + store_part.display(), + full_path.display())) .map_err(Error::from) .context(err_msg("Error building Store Id from full path"))?; Ok(StoreIdWithBase(store_part, PathBuf::from(p))) diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 9d2dd1e3..19f10f64 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -27,6 +27,7 @@ use regex::Regex; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use libimagstore::store::Store; @@ -52,19 +53,28 @@ impl<'a> BookmarkCollectionStore<'a> for Store { fn new(&'a self, name: &str) -> Result> { crate::module_path::new_id(name) - .and_then(|id| self.create(id).map_err(Error::from)) + .and_then(|id| self.create(id) + .context("Failed to create FileLockEntry") + .map_err(Error::from)) + .context("Failed to create Id for new Bookmark Collection") .map_err(Error::from) } fn get(&'a self, name: &str) -> Result>> { crate::module_path::new_id(name) - .and_then(|id| self.get(id).map_err(Error::from)) + .and_then(|id| self.get(id) + .context("Failed to get FileLockEntry") + .map_err(Error::from)) + .context("Failed to get Bookmark Collection") .map_err(Error::from) } fn delete(&'a self, name: &str) -> Result<()> { crate::module_path::new_id(name) - .and_then(|id| self.delete(id).map_err(Error::from)) + .and_then(|id| self.delete(id) + .context("Failed to delete FileLockEntry") + .map_err(Error::from)) + .context("Failed to delete Bookmark Collection") .map_err(Error::from) } diff --git a/lib/domain/libimagcontact/src/iter.rs b/lib/domain/libimagcontact/src/iter.rs index ea836d55..9335882c 100644 --- a/lib/domain/libimagcontact/src/iter.rs +++ b/lib/domain/libimagcontact/src/iter.rs @@ -25,6 +25,7 @@ use libimagerror::errors::ErrorMsg as EM; use crate::contact::Contact; use failure::Fallible as Result; use failure::Error; +use failure::ResultExt; pub struct ContactIter<'a>(StoreIdIterator, &'a Store); @@ -44,12 +45,21 @@ impl<'a> Iterator for ContactIter<'a> { loop { match self.0.next() { None => return None, - Some(Err(e)) => return Some(Err(e).map_err(Error::from)), + Some(Err(e)) => { + let e = Err(e) + .context("Found error while iterating over contacts") + .map_err(Error::from); + + return Some(e) + }, Some(Ok(sid)) => match self.1.get(sid.clone()).map_err(From::from) { Err(e) => return Some(Err(e)), Ok(None) => return Some(Err(Error::from(EM::EntryNotFound(sid.local_display_string())))), - Ok(Some(entry)) => match entry.is_contact().map_err(Error::from) { + Ok(Some(entry)) => match entry.is_contact() + .context("Cannot check whether entry is a contact") + .map_err(Error::from) + { Ok(true) => return Some(Ok(entry)), Ok(false) => continue, Err(e) => return Some(Err(e)), diff --git a/lib/domain/libimagcontact/src/store.rs b/lib/domain/libimagcontact/src/store.rs index 351365b4..66c76469 100644 --- a/lib/domain/libimagcontact/src/store.rs +++ b/lib/domain/libimagcontact/src/store.rs @@ -27,6 +27,7 @@ use toml_query::insert::TomlValueInsertExt; use vobject::vcard::Vcard; use failure::Error; use failure::Fallible as Result; +use failure::ResultExt; use libimagstore::storeid::StoreId; use libimagstore::iter::Entries; @@ -152,7 +153,7 @@ impl<'a> ContactStore<'a> for Store { /// /// That means calculating the StoreId and the Value from the vcard data fn prepare_fetching_from_store(buf: &str) -> Result<(StoreId, Value)> { - let vcard = Vcard::build(&buf).map_err(Error::from)?; + let vcard = Vcard::build(&buf).context("Cannot parse Vcard").map_err(Error::from)?; debug!("Parsed: {:?}", vcard); let uid = vcard.uid() diff --git a/lib/domain/libimagdiary/src/diary.rs b/lib/domain/libimagdiary/src/diary.rs index 0c447df5..b268b0b6 100644 --- a/lib/domain/libimagdiary/src/diary.rs +++ b/lib/domain/libimagdiary/src/diary.rs @@ -30,6 +30,7 @@ use itertools::Itertools; use chrono::naive::NaiveDateTime; use chrono::Timelike; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use crate::entry::IsDiaryEntry; @@ -141,6 +142,7 @@ impl Diary for Store { fn diary_names(&self) -> Result { self.entries() .map(|it| DiaryNameIterator::new(it.into_storeid_iter())) + .context("Failed building DiaryNameIteator from entries iterator") .map_err(Error::from) } diff --git a/lib/domain/libimagdiary/src/diaryid.rs b/lib/domain/libimagdiary/src/diaryid.rs index bdf94447..c28aebdd 100644 --- a/lib/domain/libimagdiary/src/diaryid.rs +++ b/lib/domain/libimagdiary/src/diaryid.rs @@ -234,6 +234,7 @@ impl FromStoreId for DiaryId { let day: Result = next_component(&mut cmps) .and_then(|s| { s.parse::() + .context("Failed to parse day from u32") .map_err(Error::from) .context(err_msg("ID parse error")) .map_err(Error::from) @@ -242,6 +243,7 @@ impl FromStoreId for DiaryId { let month: Result = next_component(&mut cmps) .and_then(|s| { s.parse::() + .context("Failed to parse month from u32") .map_err(Error::from) .context(err_msg("ID Parse error")) .map_err(Error::from) @@ -250,6 +252,7 @@ impl FromStoreId for DiaryId { let year: Result = next_component(&mut cmps) .and_then(|s| { s.parse::() + .context("Failed to parse year from i32") .map_err(Error::from) .context(err_msg("ID Parse error")) .map_err(Error::from) diff --git a/lib/domain/libimaghabit/src/habit.rs b/lib/domain/libimaghabit/src/habit.rs index 2e99a443..7041dff7 100644 --- a/lib/domain/libimaghabit/src/habit.rs +++ b/lib/domain/libimaghabit/src/habit.rs @@ -25,6 +25,7 @@ use chrono::Local; use chrono::NaiveDate; use failure::Error; use failure::Fallible as Result; +use failure::ResultExt; use failure::err_msg; use crate::iter::HabitInstanceStoreIdIterator; @@ -257,7 +258,9 @@ impl HabitTemplate for Entry { } fn instance_id_for_name_and_datestr(habit_name: &String, habit_date: &String) -> Result { - crate::module_path::new_id(format!("instance/{}-{}", habit_name, habit_date)).map_err(Error::from) + crate::module_path::new_id(format!("instance/{}-{}", habit_name, habit_date)) + .context(format_err!("Failed building ID for instance: habit name = {}, habit date = {}", habit_name, habit_date)) + .map_err(Error::from) } pub mod builder { diff --git a/lib/domain/libimaghabit/src/iter.rs b/lib/domain/libimaghabit/src/iter.rs index f58dbd56..3344e9a8 100644 --- a/lib/domain/libimaghabit/src/iter.rs +++ b/lib/domain/libimaghabit/src/iter.rs @@ -19,6 +19,7 @@ use failure::Error; use failure::Fallible as Result; +use failure::ResultExt; use libimagstore::storeid::StoreIdIterator; use libimagstore::storeid::StoreIdIteratorWithStore; @@ -33,11 +34,11 @@ impl Iterator for HabitTemplateStoreIdIterator { fn next(&mut self) -> Option { while let Some(n) = self.0.next() { - match n { + match n.context("Error while iterating").map_err(Error::from) { Ok(n) => if n.is_habit_template() { return Some(Ok(n)) }, - Err(e) => return Some(Err(e).map_err(Error::from)), + Err(e) => return Some(Err(e)), } } None diff --git a/lib/domain/libimaghabit/src/util.rs b/lib/domain/libimaghabit/src/util.rs index 51adb6c1..bfe99374 100644 --- a/lib/domain/libimaghabit/src/util.rs +++ b/lib/domain/libimaghabit/src/util.rs @@ -21,6 +21,7 @@ use std::ops::BitXor; use failure::Error; use failure::Fallible as Result; +use failure::ResultExt; use crate::habit::HabitTemplate; use crate::instance::HabitInstance; @@ -88,6 +89,7 @@ pub fn get_string_header_from_entry(e: &Entry, path: &'static str) -> Result Result { - self.is::().map_err(From::from) + self.is::().context("Cannot check whether Entry is a Log").map_err(From::from) } fn make_log_entry(&mut self) -> Result<()> { self.get_header_mut() .insert("log.is_log", Value::Boolean(true)) + .context("Cannot insert 'log.is_log' into header of entry") .map_err(Error::from) .map(|_| ()) } diff --git a/lib/domain/libimagmail/src/mail.rs b/lib/domain/libimagmail/src/mail.rs index fca352b7..5da48580 100644 --- a/lib/domain/libimagmail/src/mail.rs +++ b/lib/domain/libimagmail/src/mail.rs @@ -57,12 +57,17 @@ impl Mail for Entry { .context(format_err!("Cannot parse Email {}", mail_file_location.display()))? .headers .into_iter() - .filter_map(|hdr| match hdr.get_key() { - Err(e) => Some(Err(e).map_err(Error::from)), - Ok(k) => if k == field { - Some(Ok(hdr)) - } else { - None + .filter_map(|hdr| { + match hdr.get_key() + .context(format_err!("Cannot fetch key '{}' from Email {}", field, mail_file_location.display())) + .map_err(Error::from) + { + Ok(k) => if k == field { + Some(Ok(hdr)) + } else { + None + }, + Err(e) => Some(Err(e)), } }) .next() @@ -135,12 +140,17 @@ impl<'a> MailHeader<'a> { pub fn get_field(&self, field: &str) -> Result> { match self.0 .iter() - .filter_map(|hdr| match hdr.get_key() { - Err(e) => Some(Err(e).map_err(Error::from)), - Ok(key) => if key == field { - Some(Ok(hdr)) - } else { - None + .filter_map(|hdr| { + match hdr.get_key() + .context(format_err!("Cannot get field {}", field)) + .map_err(Error::from) + { + Ok(key) => if key == field { + Some(Ok(hdr)) + } else { + None + }, + Err(e) => Some(Err(e)) } }) .next() diff --git a/lib/domain/libimagmail/src/util.rs b/lib/domain/libimagmail/src/util.rs index c4c3c91f..4be9a786 100644 --- a/lib/domain/libimagmail/src/util.rs +++ b/lib/domain/libimagmail/src/util.rs @@ -39,8 +39,7 @@ pub(crate) fn get_message_header_at_key, K: AsRef>(p: P, k: .context(format_err!("Cannot parse Email {}", p.as_ref().display()))? .headers .into_iter() - .filter_map(|hdr| match hdr.get_key() { - Err(e) => Some(Err(e).map_err(Error::from)), + .filter_map(|hdr| match hdr.get_key().context("Cannot get key from mail header").map_err(Error::from) { Ok(key) => { let lower_key = key.to_lowercase(); trace!("Test: {} == {}", lower_key, k.as_ref()); @@ -49,11 +48,12 @@ pub(crate) fn get_message_header_at_key, K: AsRef>(p: P, k: } else { None } - } + }, + Err(e) => Some(Err(e)) }) .next() .ok_or_else(|| format_err!("'{}' not found in {}", k.as_ref(), p.as_ref().display()))? - .and_then(|hdr| hdr.get_value().map_err(Error::from)) + .and_then(|hdr| hdr.get_value().context("Cannot get value from mail header").map_err(Error::from)) } pub(crate) fn get_message_id_for_mailfile>(p: P) -> Result { @@ -77,6 +77,7 @@ pub fn get_mail_text_content>(p: P) -> Result { ::mailparse::parse_mail(::std::fs::read_to_string(p.as_ref())?.as_bytes()) .context(format_err!("Cannot parse Email {}", p.as_ref().display()))? .get_body() + .context("Cannot get body of mail") .map_err(Error::from) } diff --git a/lib/domain/libimagnotes/src/iter.rs b/lib/domain/libimagnotes/src/iter.rs index 74908c8f..3dc2047e 100644 --- a/lib/domain/libimagnotes/src/iter.rs +++ b/lib/domain/libimagnotes/src/iter.rs @@ -23,6 +23,7 @@ use libimagstore::storeid::StoreIdIterator; use crate::notestoreid::*; use failure::Fallible as Result; use failure::Error; +use failure::ResultExt; #[derive(Debug)] pub struct NoteIterator(StoreIdIterator); @@ -40,11 +41,11 @@ impl Iterator for NoteIterator { fn next(&mut self) -> Option { while let Some(n) = self.0.next() { - match n { + match n.context("Error while iterating").map_err(Error::from) { Ok(n) => if n.is_note_id() { return Some(Ok(n)); }, - Err(e) => return Some(Err(e).map_err(Error::from)), + Err(e) => return Some(Err(e)), } } diff --git a/lib/domain/libimagnotes/src/note.rs b/lib/domain/libimagnotes/src/note.rs index 2a55ce2b..15a0142f 100644 --- a/lib/domain/libimagnotes/src/note.rs +++ b/lib/domain/libimagnotes/src/note.rs @@ -27,6 +27,7 @@ use toml_query::set::TomlValueSetExt; use failure::Fallible as Result; use failure::Error; +use failure::ResultExt; pub trait Note { fn set_name(&mut self, n: String) -> Result<()>; @@ -40,6 +41,7 @@ impl Note for Entry { fn set_name(&mut self, n: String) -> Result<()> { self.get_header_mut() .set("note.name", Value::String(n)) + .context(format_err!("Cannot set 'note.name' in header of {}", self.get_location())) .map_err(Error::from) .map(|_| ()) } diff --git a/lib/domain/libimagtimetrack/src/iter/create.rs b/lib/domain/libimagtimetrack/src/iter/create.rs index 82519036..d08fc253 100644 --- a/lib/domain/libimagtimetrack/src/iter/create.rs +++ b/lib/domain/libimagtimetrack/src/iter/create.rs @@ -21,6 +21,7 @@ use toml::Value; use toml_query::insert::TomlValueInsertExt; use chrono::naive::NaiveDateTime as NDT; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use crate::constants::*; @@ -60,6 +61,7 @@ impl<'a> Iterator for CreateTimeTrackIter<'a> res.and_then(|(id, starttime)| { self.store .create(id) + .context("Failed to create entry") .map_err(Error::from) .and_then(|mut entry| { let v = Value::String(starttime.format(DATE_TIME_FORMAT).to_string()); diff --git a/lib/domain/libimagtimetrack/src/timetracking.rs b/lib/domain/libimagtimetrack/src/timetracking.rs index 045725f2..f47be7f7 100644 --- a/lib/domain/libimagtimetrack/src/timetracking.rs +++ b/lib/domain/libimagtimetrack/src/timetracking.rs @@ -37,6 +37,7 @@ use toml_query::delete::TomlValueDeleteExt; use toml_query::insert::TomlValueInsertExt; use toml_query::read::TomlValueReadTypeExt; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; pub trait TimeTracking { @@ -64,6 +65,8 @@ impl TimeTracking for Entry { fn get_timetrack_tag(&self) -> Result { self.get_header() .read_string(DATE_TIME_TAG_HEADER_PATH) + .context(format_err!("Failed to read header '{}' of {}", DATE_TIME_TAG_HEADER_PATH, + self.get_location())) .map_err(Error::from)? .ok_or_else(|| Error::from(EM::EntryHeaderReadError)) .map(Into::into) @@ -74,6 +77,8 @@ impl TimeTracking for Entry { self.get_header_mut() .insert(DATE_TIME_START_HEADER_PATH, Value::String(s)) + .context(format_err!("Failed get header '{}' of {}", DATE_TIME_START_HEADER_PATH, + self.get_location())) .map_err(Error::from) .map(|_| ()) } @@ -81,6 +86,8 @@ impl TimeTracking for Entry { fn get_start_datetime(&self) -> Result> { self.get_header() .read_string(DATE_TIME_START_HEADER_PATH) + .context(format_err!("Failed read header '{}' of {}", DATE_TIME_START_HEADER_PATH, + self.get_location())) .map_err(Error::from) .and_then(header_value_to_dt) } @@ -88,6 +95,8 @@ impl TimeTracking for Entry { fn delete_start_datetime(&mut self) -> Result<()> { self.get_header_mut() .delete(DATE_TIME_START_HEADER_PATH) + .context(format_err!("Failed delete header '{}' of {}", DATE_TIME_START_HEADER_PATH, + self.get_location())) .map_err(Error::from) .map(|_| ()) } @@ -97,6 +106,8 @@ impl TimeTracking for Entry { self.get_header_mut() .insert(DATE_TIME_END_HEADER_PATH, Value::String(s)) + .context(format_err!("Failed insert header '{}' in {}", DATE_TIME_END_HEADER_PATH, + self.get_location())) .map_err(Error::from) .map(|_| ()) } @@ -104,6 +115,8 @@ impl TimeTracking for Entry { fn get_end_datetime(&self) -> Result> { self.get_header() .read_string(DATE_TIME_END_HEADER_PATH) + .context(format_err!("Failed read header '{}' of {}", DATE_TIME_END_HEADER_PATH, + self.get_location())) .map_err(Error::from) .and_then(header_value_to_dt) } @@ -111,6 +124,8 @@ impl TimeTracking for Entry { fn delete_end_datetime(&mut self) -> Result<()> { self.get_header_mut() .delete(DATE_TIME_END_HEADER_PATH) + .context(format_err!("Failed delete header '{}' of {}", DATE_TIME_END_HEADER_PATH, + self.get_location())) .map_err(Error::from) .map(|_| ()) } @@ -135,7 +150,10 @@ impl TimeTracking for Entry { fn header_value_to_dt(val: Option) -> Result> { match val { - Some(ref s) => NaiveDateTime::parse_from_str(s, DATE_TIME_FORMAT).map_err(Error::from).map(Some), + Some(ref s) => NaiveDateTime::parse_from_str(s, DATE_TIME_FORMAT) + .context(format_err!("Failed to parse '{}' datetime with format '{}'", + s, DATE_TIME_FORMAT)) + .map_err(Error::from).map(Some), None => Ok(None), } } diff --git a/lib/domain/libimagtimetrack/src/timetrackingstore.rs b/lib/domain/libimagtimetrack/src/timetrackingstore.rs index 2144185b..967c8958 100644 --- a/lib/domain/libimagtimetrack/src/timetrackingstore.rs +++ b/lib/domain/libimagtimetrack/src/timetrackingstore.rs @@ -26,6 +26,7 @@ use chrono::NaiveDateTime as NDT; use toml::Value; use toml_query::insert::TomlValueInsertExt; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use libimagstore::store::Store; @@ -70,6 +71,8 @@ impl<'a> TimeTrackStore<'a> for Store { use std::path::PathBuf; COMPILER.compile(CRATE_NAME, start) + .context(format_err!("Failed to compile DatePath for crate '{}' with start = '{}'", + CRATE_NAME, start)) .map_err(Error::from) .map(|mut id| { id.local_push(PathBuf::from(ts.as_str())); diff --git a/lib/domain/libimagwiki/src/wiki.rs b/lib/domain/libimagwiki/src/wiki.rs index 6e88a760..4024e29a 100644 --- a/lib/domain/libimagwiki/src/wiki.rs +++ b/lib/domain/libimagwiki/src/wiki.rs @@ -27,6 +27,7 @@ use libimagentrylink::internal::InternalLinker; use failure::Fallible as Result; use failure::Error; use failure::err_msg; +use failure::ResultExt; pub struct Wiki<'a, 'b>(&'a Store, &'b str); @@ -58,6 +59,7 @@ impl<'a, 'b> Wiki<'a, 'b> { self.0 .get(sid) + .context("Cannot get ID from store") .map_err(Error::from)? .ok_or_else(|| Error::from(err_msg("Missing index"))) } diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index de81bfbd..fb7268a7 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -27,6 +27,7 @@ use libimagentrylink::internal::InternalLinker; use toml_query::read::TomlValueReadTypeExt; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use failure::err_msg; use crate::store::CATEGORY_REGISTER_NAME_FIELD_PATH; @@ -49,6 +50,7 @@ impl Category for Entry { trace!("Getting category name of '{:?}'", self.get_location()); self.get_header() .read_string(CATEGORY_REGISTER_NAME_FIELD_PATH) + .context(format_err!("Failed to read header at '{}'", CATEGORY_REGISTER_NAME_FIELD_PATH)) .map_err(Error::from)? .ok_or_else(|| Error::from(err_msg("Category name missing"))) } diff --git a/lib/entry/libimagentrycategory/src/entry.rs b/lib/entry/libimagentrycategory/src/entry.rs index 8260de8a..9876add4 100644 --- a/lib/entry/libimagentrycategory/src/entry.rs +++ b/lib/entry/libimagentrycategory/src/entry.rs @@ -52,7 +52,7 @@ impl EntryCategory for Entry { trace!("Setting category '{}' UNCHECKED", s); self.get_header_mut() .insert(&String::from("category.value"), Value::String(s.to_string())) - .map_err(Error::from) + .context(format_err!("Failed to insert header at 'category.value' of '{}'", self.get_location())) .context(EM::EntryHeaderWriteError) .map_err(Error::from) .map(|_| ()) @@ -84,7 +84,7 @@ impl EntryCategory for Entry { trace!("Has category? '{}'", self.get_location()); self.get_header() .read("category.value") - .map_err(Error::from) + .context(format_err!("Failed to read header at 'category.value' of '{}'", self.get_location())) .context(EM::EntryHeaderReadError) .map_err(Error::from) .map(|x| x.is_some()) @@ -101,7 +101,7 @@ impl EntryCategory for Entry { self.get_header_mut() .delete("category.value") - .map_err(Error::from) + .context(format_err!("Failed to delete header at 'category.value' of '{}'", self.get_location())) .context(EM::EntryHeaderWriteError) .map_err(Error::from) .map(|_| ()) diff --git a/lib/entry/libimagentrycategory/src/iter.rs b/lib/entry/libimagentrycategory/src/iter.rs index a16f0b9b..7ed342c7 100644 --- a/lib/entry/libimagentrycategory/src/iter.rs +++ b/lib/entry/libimagentrycategory/src/iter.rs @@ -20,7 +20,6 @@ use libimagstore::storeid::StoreIdIterator; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; -use libimagerror::errors::ErrorMsg as EM; use toml_query::read::TomlValueReadTypeExt; @@ -60,8 +59,8 @@ impl<'a> Iterator for CategoryNameIter<'a> { let query = CATEGORY_REGISTER_NAME_FIELD_PATH; while let Some(sid) = self.1.next() { - match sid { - Err(e) => return Some(Err(e).map_err(Error::from)), + match sid.context("Error while iterating over category names").map_err(Error::from) { + Err(e) => return Some(Err(e)), Ok(sid) => { if sid.is_in_collection(&["category"]) { let func = |store: &Store| { // hack for returning Some(Result<_, _>) @@ -70,8 +69,7 @@ impl<'a> Iterator for CategoryNameIter<'a> { .ok_or_else(|| err_msg("Store read error"))? .get_header() .read_string(query) - .map_err(Error::from) - .context(EM::EntryHeaderReadError)? + .context(format_err!("Failed to read header at '{}'", query))? .ok_or_else(|| err_msg("Store read error")) .map_err(Error::from) }; @@ -99,8 +97,8 @@ impl<'a> Iterator for CategoryEntryIterator<'a> { fn next(&mut self) -> Option { while let Some(next) = self.1.next() { - match next { - Err(e) => return Some(Err(e).map_err(Error::from)), + match next.context("Error while iterating over category entries").map_err(Error::from) { + Err(e) => return Some(Err(e)), Ok(next) => { let getter = |next| -> Result<(String, FileLockEntry<'a>)> { let entry = self.0 diff --git a/lib/entry/libimagentrydatetime/src/datetime.rs b/lib/entry/libimagentrydatetime/src/datetime.rs index 611e5dbd..d7fcb828 100644 --- a/lib/entry/libimagentrydatetime/src/datetime.rs +++ b/lib/entry/libimagentrydatetime/src/datetime.rs @@ -92,6 +92,9 @@ impl EntryDate for Entry { self.get_header_mut() .insert(&DATE_HEADER_LOCATION, Value::String(date)) + .context(format_err!("Failed to insert header '{}' in '{}'", + *DATE_HEADER_LOCATION, + self.get_location())) .map_err(Error::from) .map(|opt| opt.map(|stri| { stri.as_str() diff --git a/lib/entry/libimagentrydatetime/src/lib.rs b/lib/entry/libimagentrydatetime/src/lib.rs index ede8b862..3e16e031 100644 --- a/lib/entry/libimagentrydatetime/src/lib.rs +++ b/lib/entry/libimagentrydatetime/src/lib.rs @@ -38,10 +38,10 @@ )] #[macro_use] extern crate lazy_static; +#[macro_use] extern crate failure; extern crate chrono; extern crate toml_query; extern crate toml; -extern crate failure; extern crate libimagerror; extern crate libimagstore; diff --git a/lib/entry/libimagentryedit/src/edit.rs b/lib/entry/libimagentryedit/src/edit.rs index d6a8f59c..51ea7114 100644 --- a/lib/entry/libimagentryedit/src/edit.rs +++ b/lib/entry/libimagentryedit/src/edit.rs @@ -66,7 +66,9 @@ impl EditHeader for Entry { fn edit_header_and_content(&mut self, rt: &Runtime) -> Result<()> { let mut header_and_content = self.to_str()?; let _ = edit_in_tmpfile(rt, &mut header_and_content)?; - self.replace_from_buffer(&header_and_content).map_err(Error::from) + self.replace_from_buffer(&header_and_content) + .context("Failed to replace header and content from buffer") + .map_err(Error::from) } } diff --git a/lib/entry/libimagentryfilter/src/builtin/header/field_exists.rs b/lib/entry/libimagentryfilter/src/builtin/header/field_exists.rs index be816c8a..674a6f08 100644 --- a/lib/entry/libimagentryfilter/src/builtin/header/field_exists.rs +++ b/lib/entry/libimagentryfilter/src/builtin/header/field_exists.rs @@ -23,6 +23,7 @@ use toml_query::read::TomlValueReadExt; use filters::failable::filter::FailableFilter; use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use crate::builtin::header::field_path::FieldPath; @@ -47,6 +48,9 @@ impl FailableFilter for FieldExists { fn filter(&self, e: &Entry) -> Result { e.get_header() .read(&self.header_field_path[..]) + .context(format_err!("Failed reading header '{}' in '{}'", + self.header_field_path, + e.get_location())) .map_err(Error::from) .map(|o| o.is_some()) } diff --git a/lib/entry/libimagentryfilter/src/lib.rs b/lib/entry/libimagentryfilter/src/lib.rs index 550bbf7f..71faa18b 100644 --- a/lib/entry/libimagentryfilter/src/lib.rs +++ b/lib/entry/libimagentryfilter/src/lib.rs @@ -40,7 +40,7 @@ extern crate regex; extern crate semver; extern crate toml; extern crate toml_query; -extern crate failure; +#[macro_use] extern crate failure; extern crate libimagstore; extern crate libimagentrytag; diff --git a/lib/entry/libimagentrygps/src/entry.rs b/lib/entry/libimagentrygps/src/entry.rs index 7c64b5c2..4bdf73be 100644 --- a/lib/entry/libimagentrygps/src/entry.rs +++ b/lib/entry/libimagentrygps/src/entry.rs @@ -60,11 +60,16 @@ impl GPSEntry for Entry { self.get_header_mut() .insert("gps.coordinates", c.into()) .map(|_| ()) + .context(format_err!("Error while inserting header 'gps.coordinates' in '{}'", self.get_location())) .map_err(Error::from) } fn get_coordinates(&self) -> Result> { - match self.get_header().read("gps.coordinates").map_err(Error::from)? { + match self + .get_header() + .read("gps.coordinates") + .context(format_err!("Error while reading header 'gps.coordinates' in '{}'", self.get_location()))? + { Some(hdr) => Coordinates::from_value(hdr).map(Some), None => Ok(None), } @@ -89,7 +94,7 @@ impl GPSEntry for Entry { let hdr = self.get_header_mut(); for pattern in patterns.iter() { let _ = hdr.delete(pattern) - .map_err(Error::from) + .context(format_err!("Error while deleting header '{}'", pattern)) .context("Error writing header")?; } diff --git a/lib/entry/libimagentrygps/src/lib.rs b/lib/entry/libimagentrygps/src/lib.rs index f819af40..8e8cade7 100644 --- a/lib/entry/libimagentrygps/src/lib.rs +++ b/lib/entry/libimagentrygps/src/lib.rs @@ -38,7 +38,7 @@ extern crate toml; extern crate toml_query; #[macro_use] extern crate serde_derive; -extern crate failure; +#[macro_use] extern crate failure; extern crate libimagstore; extern crate libimagerror; diff --git a/lib/entry/libimagentrylink/src/external.rs b/lib/entry/libimagentrylink/src/external.rs index 3151ebe2..a31871d8 100644 --- a/lib/entry/libimagentrylink/src/external.rs +++ b/lib/entry/libimagentrylink/src/external.rs @@ -70,7 +70,7 @@ impl Link for Entry { fn get_link_uri_from_filelockentry(&self) -> Result> { self.get_header() .read_string("links.external.content.url") - .map_err(Error::from) + .context(format_err!("Error reading header 'links.external.content.url' from '{}'", self.get_location())) .context(EM::EntryHeaderReadError) .map_err(Error::from) .and_then(|opt| match opt { @@ -79,11 +79,13 @@ impl Link for Entry { debug!("Found url, parsing: {:?}", s); Url::parse(&s[..]) .map_err(Error::from) + .context(format_err!("Failed to parse URL: '{}'", s)) .context(err_msg("Invalid URI")) .map_err(Error::from) .map(Some) }, }) + .context("Failed to get link URI from entry") .map_err(Error::from) } @@ -91,6 +93,7 @@ impl Link for Entry { match self.get_header().read_string("links.external.url")? { None => Ok(None), Some(ref s) => Url::parse(&s[..]) + .context(format_err!("Failed to parse URL: '{}'", s)) .map(Some) .map_err(Error::from) .context(EM::EntryHeaderReadError) diff --git a/lib/entry/libimagentrylink/src/internal.rs b/lib/entry/libimagentrylink/src/internal.rs index 2ed5e5f6..224eac99 100644 --- a/lib/entry/libimagentrylink/src/internal.rs +++ b/lib/entry/libimagentrylink/src/internal.rs @@ -265,7 +265,7 @@ impl InternalLinker for Entry { let res = self .get_header() .read("links.internal") - .map_err(Error::from) + .context(format_err!("Failed to read header 'links.internal' of '{}'", self.get_location())) .context(EM::EntryHeaderReadError) .context(EM::EntryHeaderError) .map_err(Error::from) @@ -299,7 +299,7 @@ impl InternalLinker for Entry { let res = self .get_header_mut() .insert("links.internal", Value::Array(new_links)) - .map_err(Error::from) + .context(format_err!("Failed to insert header 'links.internal' of '{}'", self.get_location())) .context(EM::EntryHeaderReadError) .map_err(Error::from); process_rw_result(res) @@ -336,7 +336,7 @@ impl InternalLinker for Entry { fn unlink(&mut self, store: &Store) -> Result<()> { for id in self.get_internal_links()?.map(|l| l.get_store_id().clone()) { - match store.get(id).map_err(Error::from)? { + match store.get(id).context("Failed to get entry")? { Some(mut entry) => self.remove_internal_link(&mut entry)?, None => return Err(err_msg("Link target does not exist")), } @@ -382,7 +382,7 @@ fn rewrite_links>(header: &mut Value, links: I) -> Resu debug!("Setting new link array: {:?}", links); let process = header .insert("links.internal", Value::Array(links)) - .map_err(Error::from) + .context(format_err!("Failed to insert header 'links.internal'")) .context(EM::EntryHeaderReadError) .map_err(Error::from); process_rw_result(process).map(|_| ()) @@ -409,7 +409,7 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> { let res = target .get_header_mut() .insert("links.internal", Value::Array(links)) - .map_err(Error::from) + .context(format_err!("Failed to insert header 'links.internal'")) .context(EM::EntryHeaderReadError) .map_err(Error::from); diff --git a/lib/entry/libimagentryref/src/reference.rs b/lib/entry/libimagentryref/src/reference.rs index 729d23ef..2f7aa353 100644 --- a/lib/entry/libimagentryref/src/reference.rs +++ b/lib/entry/libimagentryref/src/reference.rs @@ -89,6 +89,7 @@ pub mod fassade { use libimagentryutil::isa::Is; use failure::Fallible as Result; + use failure::ResultExt; use failure::Error; use crate::hasher::sha1::Sha1Hasher; @@ -104,7 +105,7 @@ pub mod fassade { impl RefFassade for Entry { /// Check whether the underlying object is actually a ref fn is_ref(&self) -> Result { - self.is::().map_err(Error::from) + self.is::().context("Failed to check is-ref flag").map_err(Error::from) } fn as_ref_with_hasher(&self) -> RefWithHasher { @@ -163,7 +164,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { /// Check whether the underlying object is actually a ref fn is_ref(&self) -> Result { - self.0.is::().map_err(Error::from) + self.0.is::().context("Failed to check is-ref flag").map_err(Error::from) } fn get_hash(&self) -> Result<&str> { @@ -171,6 +172,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { self.0 .get_header() .read(&header_path) + .context(format_err!("Failed to read header at '{}'", header_path)) .map_err(Error::from)? .ok_or_else(|| { Error::from(EM::EntryHeaderFieldMissing("ref.hash.")) @@ -210,7 +212,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { self.0 .get_header() .read("ref.relpath") - .map_err(Error::from)? + .context("Failed to read header at 'ref.relpath'")? .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath"))) .and_then(|v| { v.as_str() @@ -223,19 +225,20 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { fn hash_valid(&self, config: &Config) -> Result { let ref_header = self.0 .get_header() - .read("ref")? + .read("ref") + .context("Failed to read header at 'ref'")? .ok_or_else(|| err_msg("Header missing at 'ref'"))?; let basepath_name = ref_header .read("basepath") - .map_err(Error::from)? + .context("Failed to read header at 'ref.basepath'")? .ok_or_else(|| err_msg("Header missing at 'ref.basepath'"))? .as_str() .ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.", "string")))?; let path = ref_header .read("relpath") - .map_err(Error::from)? + .context("Failed to read header at 'ref.relpath'")? .ok_or_else(|| err_msg("Header missing at 'ref.relpath'"))? .as_str() .map(PathBuf::from) @@ -246,7 +249,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { ref_header .read(H::NAME) - .map_err(Error::from)? + .context(format_err!("Failed to read header at 'ref.{}'", H::NAME))? .ok_or_else(|| format_err!("Header missing at 'ref.{}'", H::NAME)) .and_then(|v| { v.as_str().ok_or_else(|| { @@ -352,7 +355,9 @@ impl<'a, H> MutRef for MutRefWithHasher<'a, H> trace!("Using relpath = {} to make header section", relpath.display()); make_header_section(hash, H::NAME, relpath, basepath_name) }) - .and_then(|h| self.0.get_header_mut().insert("ref", h).map_err(Error::from)) + .and_then(|h| self.0.get_header_mut().insert("ref", h) + .context("Failed to insert 'ref' in header") + .map_err(Error::from)) .and_then(|_| self.0.set_isflag::()) .context("Making ref out of entry")?; diff --git a/lib/entry/libimagentrytag/src/tagable.rs b/lib/entry/libimagentrytag/src/tagable.rs index 6ff5e4cc..196b3f0d 100644 --- a/lib/entry/libimagentrytag/src/tagable.rs +++ b/lib/entry/libimagentrytag/src/tagable.rs @@ -51,6 +51,7 @@ impl Tagable for Value { fn get_tags(&self) -> Result> { self.read("tag.values") + .context(format_err!("Failed to read header at 'tag.values'")) .map_err(Error::from) .context(EM::EntryHeaderReadError)? .map(|val| { diff --git a/lib/entry/libimagentryutil/src/isa.rs b/lib/entry/libimagentryutil/src/isa.rs index f10152b8..7730eea2 100644 --- a/lib/entry/libimagentryutil/src/isa.rs +++ b/lib/entry/libimagentryutil/src/isa.rs @@ -18,6 +18,7 @@ // use failure::Fallible as Result; +use failure::ResultExt; use failure::Error; use toml::Value; @@ -79,7 +80,12 @@ impl Is for ::libimagstore::store::Entry { fn is(&self) -> Result { let field = T::kindflag_header_location(); - match self.get_header().read_bool(field).map_err(Error::from)? { + match self + .get_header() + .read_bool(field) + .context(format_err!("Failed reading header '{}' in '{}'", field, self.get_location())) + .map_err(Error::from)? + { Some(b) => Ok(b), None => Ok(false), } @@ -88,6 +94,7 @@ impl Is for ::libimagstore::store::Entry { fn set_isflag(&mut self) -> Result<()> { self.get_header_mut() .insert(T::kindflag_header_location(), Value::Boolean(true)) + .context(format_err!("Failed inserting header '{}' in '{}'", T::kindflag_header_location(), self.get_location())) .map_err(Error::from) .map(|_| ()) } @@ -96,6 +103,7 @@ impl Is for ::libimagstore::store::Entry { trace!("Trying to remove: {}", T::kindflag_header_location()); self.get_header_mut() .delete(T::kindflag_header_location()) + .context(format_err!("Failed deleting header '{}' in '{}'", T::kindflag_header_location(), self.get_location())) .map_err(Error::from) .map(|_| ()) } diff --git a/lib/entry/libimagentryutil/src/lib.rs b/lib/entry/libimagentryutil/src/lib.rs index 6dbc1870..c5feb7cb 100644 --- a/lib/entry/libimagentryutil/src/lib.rs +++ b/lib/entry/libimagentryutil/src/lib.rs @@ -40,7 +40,7 @@ extern crate filters; extern crate toml; extern crate toml_query; -extern crate failure; +#[macro_use] extern crate failure; #[macro_use] extern crate log; extern crate libimagstore; diff --git a/lib/entry/libimagentryview/src/builtin/editor.rs b/lib/entry/libimagentryview/src/builtin/editor.rs index 8a702e63..35845649 100644 --- a/lib/entry/libimagentryview/src/builtin/editor.rs +++ b/lib/entry/libimagentryview/src/builtin/editor.rs @@ -27,7 +27,6 @@ use crate::viewer::Viewer; use failure::Fallible as Result; use failure::ResultExt; use failure::Error; -use failure::err_msg; pub struct EditorView<'a>(&'a Runtime<'a>); @@ -43,7 +42,7 @@ impl<'a> Viewer for EditorView<'a> { { let mut entry = e.to_str()?.clone().to_string(); edit_in_tmpfile(self.0, &mut entry) - .context(err_msg("Error while viewing")) + .context("Error while viewing") .map_err(Error::from) } } diff --git a/lib/etc/libimaginteraction/src/ask.rs b/lib/etc/libimaginteraction/src/ask.rs index 56a411e1..ea112d7c 100644 --- a/lib/etc/libimaginteraction/src/ask.rs +++ b/lib/etc/libimaginteraction/src/ask.rs @@ -178,10 +178,12 @@ pub fn ask_select_from_list(list: &[&str]) -> Result { /// The `nl` parameter can be used to configure whether a newline character should be printed pub fn ask_question(question: &str, nl: bool, output: &mut Write) -> Result<()> { if nl { - writeln!(output, "[imag]: {}?", Yellow.paint(question)).map_err(Error::from) + writeln!(output, "[imag]: {}?", Yellow.paint(question)) } else { - write!(output, "[imag]: {}?", Yellow.paint(question)).map_err(Error::from) + write!(output, "[imag]: {}?", Yellow.paint(question)) } + .context("Failed to write question to output") + .map_err(Error::from) } #[cfg(test)]