Merge branch 'error-context' into master
This commit is contained in:
commit
85f8082cbe
39 changed files with 177 additions and 65 deletions
|
@ -370,6 +370,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
for (module_name, v) in t {
|
for (module_name, v) in t {
|
||||||
let destinations = inner_try! {
|
let destinations = inner_try! {
|
||||||
v.read("destinations")
|
v.read("destinations")
|
||||||
|
.context("Failed reading header 'destinations'")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(EM::TomlQueryError)?
|
.context(EM::TomlQueryError)?
|
||||||
.map(|val| {
|
.map(|val| {
|
||||||
|
@ -384,6 +385,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
|
|
||||||
let level = inner_try! {
|
let level = inner_try! {
|
||||||
v.read_string("level")
|
v.read_string("level")
|
||||||
|
.context("Failed reading header 'level'")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(EM::TomlQueryError)?
|
.context(EM::TomlQueryError)?
|
||||||
.map(|s| match_log_level_str(&s))
|
.map(|s| match_log_level_str(&s))
|
||||||
|
|
|
@ -408,6 +408,7 @@ impl<'a> Runtime<'a> {
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
lock.read_to_string(&mut buf)
|
lock.read_to_string(&mut buf)
|
||||||
|
.context("Failed to read stdin to buffer")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.and_then(|_| {
|
.and_then(|_| {
|
||||||
trace!("Got IDs = {}", buf);
|
trace!("Got IDs = {}", buf);
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub fn config_implicit_store_create_allowed(config: &Option<Value>) -> Result<bo
|
||||||
|
|
||||||
if let Some(ref t) = *config {
|
if let Some(ref t) = *config {
|
||||||
t.read_bool(key)
|
t.read_bool(key)
|
||||||
|
.context(format_err!("Error reading header '{}' in configuration", key))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(EM::TomlQueryError)?
|
.context(EM::TomlQueryError)?
|
||||||
.ok_or_else(|| format_err!("Config key missing: {}", key))
|
.ok_or_else(|| format_err!("Config key missing: {}", key))
|
||||||
|
|
|
@ -184,6 +184,9 @@ impl<'a> StoreIdWithBase<'a> {
|
||||||
store_part.display());
|
store_part.display());
|
||||||
let p = full_path
|
let p = full_path
|
||||||
.strip_prefix(store_part)
|
.strip_prefix(store_part)
|
||||||
|
.context(format_err!("Cannot strip prefix '{}' from path: '{}'",
|
||||||
|
store_part.display(),
|
||||||
|
full_path.display()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(err_msg("Error building Store Id from full path"))?;
|
.context(err_msg("Error building Store Id from full path"))?;
|
||||||
Ok(StoreIdWithBase(store_part, PathBuf::from(p)))
|
Ok(StoreIdWithBase(store_part, PathBuf::from(p)))
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
|
@ -52,19 +53,28 @@ impl<'a> BookmarkCollectionStore<'a> for Store {
|
||||||
|
|
||||||
fn new(&'a self, name: &str) -> Result<FileLockEntry<'a>> {
|
fn new(&'a self, name: &str) -> Result<FileLockEntry<'a>> {
|
||||||
crate::module_path::new_id(name)
|
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)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&'a self, name: &str) -> Result<Option<FileLockEntry<'a>>> {
|
fn get(&'a self, name: &str) -> Result<Option<FileLockEntry<'a>>> {
|
||||||
crate::module_path::new_id(name)
|
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)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(&'a self, name: &str) -> Result<()> {
|
fn delete(&'a self, name: &str) -> Result<()> {
|
||||||
crate::module_path::new_id(name)
|
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)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use libimagerror::errors::ErrorMsg as EM;
|
||||||
use crate::contact::Contact;
|
use crate::contact::Contact;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
pub struct ContactIter<'a>(StoreIdIterator, &'a Store);
|
pub struct ContactIter<'a>(StoreIdIterator, &'a Store);
|
||||||
|
|
||||||
|
@ -44,12 +45,21 @@ impl<'a> Iterator for ContactIter<'a> {
|
||||||
loop {
|
loop {
|
||||||
match self.0.next() {
|
match self.0.next() {
|
||||||
None => return None,
|
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) {
|
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
|
Ok(None) => return
|
||||||
Some(Err(Error::from(EM::EntryNotFound(sid.local_display_string())))),
|
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(true) => return Some(Ok(entry)),
|
||||||
Ok(false) => continue,
|
Ok(false) => continue,
|
||||||
Err(e) => return Some(Err(e)),
|
Err(e) => return Some(Err(e)),
|
||||||
|
|
|
@ -27,6 +27,7 @@ use toml_query::insert::TomlValueInsertExt;
|
||||||
use vobject::vcard::Vcard;
|
use vobject::vcard::Vcard;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
use libimagstore::storeid::StoreId;
|
use libimagstore::storeid::StoreId;
|
||||||
use libimagstore::iter::Entries;
|
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
|
/// That means calculating the StoreId and the Value from the vcard data
|
||||||
fn prepare_fetching_from_store(buf: &str) -> Result<(StoreId, Value)> {
|
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);
|
debug!("Parsed: {:?}", vcard);
|
||||||
|
|
||||||
let uid = vcard.uid()
|
let uid = vcard.uid()
|
||||||
|
|
|
@ -30,6 +30,7 @@ use itertools::Itertools;
|
||||||
use chrono::naive::NaiveDateTime;
|
use chrono::naive::NaiveDateTime;
|
||||||
use chrono::Timelike;
|
use chrono::Timelike;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::entry::IsDiaryEntry;
|
use crate::entry::IsDiaryEntry;
|
||||||
|
@ -141,6 +142,7 @@ impl Diary for Store {
|
||||||
fn diary_names(&self) -> Result<DiaryNameIterator> {
|
fn diary_names(&self) -> Result<DiaryNameIterator> {
|
||||||
self.entries()
|
self.entries()
|
||||||
.map(|it| DiaryNameIterator::new(it.into_storeid_iter()))
|
.map(|it| DiaryNameIterator::new(it.into_storeid_iter()))
|
||||||
|
.context("Failed building DiaryNameIteator from entries iterator")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,7 @@ impl FromStoreId for DiaryId {
|
||||||
let day: Result<u32> = next_component(&mut cmps)
|
let day: Result<u32> = next_component(&mut cmps)
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
s.parse::<u32>()
|
s.parse::<u32>()
|
||||||
|
.context("Failed to parse day from u32")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(err_msg("ID parse error"))
|
.context(err_msg("ID parse error"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
@ -242,6 +243,7 @@ impl FromStoreId for DiaryId {
|
||||||
let month: Result<u32> = next_component(&mut cmps)
|
let month: Result<u32> = next_component(&mut cmps)
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
s.parse::<u32>()
|
s.parse::<u32>()
|
||||||
|
.context("Failed to parse month from u32")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(err_msg("ID Parse error"))
|
.context(err_msg("ID Parse error"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
@ -250,6 +252,7 @@ impl FromStoreId for DiaryId {
|
||||||
let year: Result<i32> = next_component(&mut cmps)
|
let year: Result<i32> = next_component(&mut cmps)
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
s.parse::<i32>()
|
s.parse::<i32>()
|
||||||
|
.context("Failed to parse year from i32")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(err_msg("ID Parse error"))
|
.context(err_msg("ID Parse error"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
|
|
@ -25,6 +25,7 @@ use chrono::Local;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
|
||||||
use crate::iter::HabitInstanceStoreIdIterator;
|
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<StoreId> {
|
fn instance_id_for_name_and_datestr(habit_name: &String, habit_date: &String) -> Result<StoreId> {
|
||||||
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 {
|
pub mod builder {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
use libimagstore::storeid::StoreIdIterator;
|
use libimagstore::storeid::StoreIdIterator;
|
||||||
use libimagstore::storeid::StoreIdIteratorWithStore;
|
use libimagstore::storeid::StoreIdIteratorWithStore;
|
||||||
|
@ -33,11 +34,11 @@ impl Iterator for HabitTemplateStoreIdIterator {
|
||||||
|
|
||||||
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() {
|
||||||
match n {
|
match n.context("Error while iterating").map_err(Error::from) {
|
||||||
Ok(n) => if n.is_habit_template() {
|
Ok(n) => if n.is_habit_template() {
|
||||||
return Some(Ok(n))
|
return Some(Ok(n))
|
||||||
},
|
},
|
||||||
Err(e) => return Some(Err(e).map_err(Error::from)),
|
Err(e) => return Some(Err(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -21,6 +21,7 @@ use std::ops::BitXor;
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
use crate::habit::HabitTemplate;
|
use crate::habit::HabitTemplate;
|
||||||
use crate::instance::HabitInstance;
|
use crate::instance::HabitInstance;
|
||||||
|
@ -88,6 +89,7 @@ pub fn get_string_header_from_entry(e: &Entry, path: &'static str) -> Result<Str
|
||||||
e.get_header()
|
e.get_header()
|
||||||
.read_string(path)?
|
.read_string(path)?
|
||||||
.ok_or_else(|| EM::EntryHeaderFieldMissing(path))
|
.ok_or_else(|| EM::EntryHeaderFieldMissing(path))
|
||||||
|
.context(format_err!("Error while reading header '{}' from '{}'", path, e.get_location()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ use libimagentryutil::isa::IsKindHeaderPathProvider;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
|
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
@ -38,12 +39,13 @@ provide_kindflag_path!(pub IsLog, "log.is_log");
|
||||||
|
|
||||||
impl Log for Entry {
|
impl Log for Entry {
|
||||||
fn is_log(&self) -> Result<bool> {
|
fn is_log(&self) -> Result<bool> {
|
||||||
self.is::<IsLog>().map_err(From::from)
|
self.is::<IsLog>().context("Cannot check whether Entry is a Log").map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_log_entry(&mut self) -> Result<()> {
|
fn make_log_entry(&mut self) -> Result<()> {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert("log.is_log", Value::Boolean(true))
|
.insert("log.is_log", Value::Boolean(true))
|
||||||
|
.context("Cannot insert 'log.is_log' into header of entry")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,12 +57,17 @@ impl Mail for Entry {
|
||||||
.context(format_err!("Cannot parse Email {}", mail_file_location.display()))?
|
.context(format_err!("Cannot parse Email {}", mail_file_location.display()))?
|
||||||
.headers
|
.headers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|hdr| match hdr.get_key() {
|
.filter_map(|hdr| {
|
||||||
Err(e) => Some(Err(e).map_err(Error::from)),
|
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 {
|
Ok(k) => if k == field {
|
||||||
Some(Ok(hdr))
|
Some(Ok(hdr))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
},
|
||||||
|
Err(e) => Some(Err(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
|
@ -135,12 +140,17 @@ impl<'a> MailHeader<'a> {
|
||||||
pub fn get_field(&self, field: &str) -> Result<Option<String>> {
|
pub fn get_field(&self, field: &str) -> Result<Option<String>> {
|
||||||
match self.0
|
match self.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|hdr| match hdr.get_key() {
|
.filter_map(|hdr| {
|
||||||
Err(e) => Some(Err(e).map_err(Error::from)),
|
match hdr.get_key()
|
||||||
|
.context(format_err!("Cannot get field {}", field))
|
||||||
|
.map_err(Error::from)
|
||||||
|
{
|
||||||
Ok(key) => if key == field {
|
Ok(key) => if key == field {
|
||||||
Some(Ok(hdr))
|
Some(Ok(hdr))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
},
|
||||||
|
Err(e) => Some(Err(e))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
|
|
|
@ -39,8 +39,7 @@ pub(crate) fn get_message_header_at_key<P: AsRef<Path>, K: AsRef<str>>(p: P, k:
|
||||||
.context(format_err!("Cannot parse Email {}", p.as_ref().display()))?
|
.context(format_err!("Cannot parse Email {}", p.as_ref().display()))?
|
||||||
.headers
|
.headers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|hdr| match hdr.get_key() {
|
.filter_map(|hdr| match hdr.get_key().context("Cannot get key from mail header").map_err(Error::from) {
|
||||||
Err(e) => Some(Err(e).map_err(Error::from)),
|
|
||||||
Ok(key) => {
|
Ok(key) => {
|
||||||
let lower_key = key.to_lowercase();
|
let lower_key = key.to_lowercase();
|
||||||
trace!("Test: {} == {}", lower_key, k.as_ref());
|
trace!("Test: {} == {}", lower_key, k.as_ref());
|
||||||
|
@ -49,11 +48,12 @@ pub(crate) fn get_message_header_at_key<P: AsRef<Path>, K: AsRef<str>>(p: P, k:
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
Err(e) => Some(Err(e))
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| format_err!("'{}' not found in {}", k.as_ref(), p.as_ref().display()))?
|
.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: AsRef<Path>>(p: P) -> Result<String> {
|
pub(crate) fn get_message_id_for_mailfile<P: AsRef<Path>>(p: P) -> Result<String> {
|
||||||
|
@ -77,6 +77,7 @@ pub fn get_mail_text_content<P: AsRef<Path>>(p: P) -> Result<String> {
|
||||||
::mailparse::parse_mail(::std::fs::read_to_string(p.as_ref())?.as_bytes())
|
::mailparse::parse_mail(::std::fs::read_to_string(p.as_ref())?.as_bytes())
|
||||||
.context(format_err!("Cannot parse Email {}", p.as_ref().display()))?
|
.context(format_err!("Cannot parse Email {}", p.as_ref().display()))?
|
||||||
.get_body()
|
.get_body()
|
||||||
|
.context("Cannot get body of mail")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ use libimagstore::storeid::StoreIdIterator;
|
||||||
use crate::notestoreid::*;
|
use crate::notestoreid::*;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NoteIterator(StoreIdIterator);
|
pub struct NoteIterator(StoreIdIterator);
|
||||||
|
@ -40,11 +41,11 @@ impl Iterator for NoteIterator {
|
||||||
|
|
||||||
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() {
|
||||||
match n {
|
match n.context("Error while iterating").map_err(Error::from) {
|
||||||
Ok(n) => if n.is_note_id() {
|
Ok(n) => if n.is_note_id() {
|
||||||
return Some(Ok(n));
|
return Some(Ok(n));
|
||||||
},
|
},
|
||||||
Err(e) => return Some(Err(e).map_err(Error::from)),
|
Err(e) => return Some(Err(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ use toml_query::set::TomlValueSetExt;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
pub trait Note {
|
pub trait Note {
|
||||||
fn set_name(&mut self, n: String) -> Result<()>;
|
fn set_name(&mut self, n: String) -> Result<()>;
|
||||||
|
@ -40,6 +41,7 @@ impl Note for Entry {
|
||||||
fn set_name(&mut self, n: String) -> Result<()> {
|
fn set_name(&mut self, n: String) -> Result<()> {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.set("note.name", Value::String(n))
|
.set("note.name", Value::String(n))
|
||||||
|
.context(format_err!("Cannot set 'note.name' in header of {}", self.get_location()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use toml::Value;
|
||||||
use toml_query::insert::TomlValueInsertExt;
|
use toml_query::insert::TomlValueInsertExt;
|
||||||
use chrono::naive::NaiveDateTime as NDT;
|
use chrono::naive::NaiveDateTime as NDT;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
|
@ -60,6 +61,7 @@ impl<'a> Iterator for CreateTimeTrackIter<'a>
|
||||||
res.and_then(|(id, starttime)| {
|
res.and_then(|(id, starttime)| {
|
||||||
self.store
|
self.store
|
||||||
.create(id)
|
.create(id)
|
||||||
|
.context("Failed to create entry")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.and_then(|mut entry| {
|
.and_then(|mut entry| {
|
||||||
let v = Value::String(starttime.format(DATE_TIME_FORMAT).to_string());
|
let v = Value::String(starttime.format(DATE_TIME_FORMAT).to_string());
|
||||||
|
|
|
@ -37,6 +37,7 @@ use toml_query::delete::TomlValueDeleteExt;
|
||||||
use toml_query::insert::TomlValueInsertExt;
|
use toml_query::insert::TomlValueInsertExt;
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
pub trait TimeTracking {
|
pub trait TimeTracking {
|
||||||
|
@ -64,6 +65,8 @@ impl TimeTracking for Entry {
|
||||||
fn get_timetrack_tag(&self) -> Result<TTT> {
|
fn get_timetrack_tag(&self) -> Result<TTT> {
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string(DATE_TIME_TAG_HEADER_PATH)
|
.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)?
|
.map_err(Error::from)?
|
||||||
.ok_or_else(|| Error::from(EM::EntryHeaderReadError))
|
.ok_or_else(|| Error::from(EM::EntryHeaderReadError))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
|
@ -74,6 +77,8 @@ impl TimeTracking for Entry {
|
||||||
|
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert(DATE_TIME_START_HEADER_PATH, Value::String(s))
|
.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_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -81,6 +86,8 @@ impl TimeTracking for Entry {
|
||||||
fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>> {
|
fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>> {
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string(DATE_TIME_START_HEADER_PATH)
|
.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)
|
.map_err(Error::from)
|
||||||
.and_then(header_value_to_dt)
|
.and_then(header_value_to_dt)
|
||||||
}
|
}
|
||||||
|
@ -88,6 +95,8 @@ impl TimeTracking for Entry {
|
||||||
fn delete_start_datetime(&mut self) -> Result<()> {
|
fn delete_start_datetime(&mut self) -> Result<()> {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.delete(DATE_TIME_START_HEADER_PATH)
|
.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_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -97,6 +106,8 @@ impl TimeTracking for Entry {
|
||||||
|
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert(DATE_TIME_END_HEADER_PATH, Value::String(s))
|
.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_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -104,6 +115,8 @@ impl TimeTracking for Entry {
|
||||||
fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>> {
|
fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>> {
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string(DATE_TIME_END_HEADER_PATH)
|
.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)
|
.map_err(Error::from)
|
||||||
.and_then(header_value_to_dt)
|
.and_then(header_value_to_dt)
|
||||||
}
|
}
|
||||||
|
@ -111,6 +124,8 @@ impl TimeTracking for Entry {
|
||||||
fn delete_end_datetime(&mut self) -> Result<()> {
|
fn delete_end_datetime(&mut self) -> Result<()> {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.delete(DATE_TIME_END_HEADER_PATH)
|
.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_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -135,7 +150,10 @@ impl TimeTracking for Entry {
|
||||||
|
|
||||||
fn header_value_to_dt(val: Option<String>) -> Result<Option<NaiveDateTime>> {
|
fn header_value_to_dt(val: Option<String>) -> Result<Option<NaiveDateTime>> {
|
||||||
match val {
|
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),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ use chrono::NaiveDateTime as NDT;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use toml_query::insert::TomlValueInsertExt;
|
use toml_query::insert::TomlValueInsertExt;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
|
@ -70,6 +71,8 @@ impl<'a> TimeTrackStore<'a> for Store {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
COMPILER.compile(CRATE_NAME, start)
|
COMPILER.compile(CRATE_NAME, start)
|
||||||
|
.context(format_err!("Failed to compile DatePath for crate '{}' with start = '{}'",
|
||||||
|
CRATE_NAME, start))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|mut id| {
|
.map(|mut id| {
|
||||||
id.local_push(PathBuf::from(ts.as_str()));
|
id.local_push(PathBuf::from(ts.as_str()));
|
||||||
|
|
|
@ -27,6 +27,7 @@ use libimagentrylink::internal::InternalLinker;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
use failure::ResultExt;
|
||||||
|
|
||||||
pub struct Wiki<'a, 'b>(&'a Store, &'b str);
|
pub struct Wiki<'a, 'b>(&'a Store, &'b str);
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ impl<'a, 'b> Wiki<'a, 'b> {
|
||||||
|
|
||||||
self.0
|
self.0
|
||||||
.get(sid)
|
.get(sid)
|
||||||
|
.context("Cannot get ID from store")
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.ok_or_else(|| Error::from(err_msg("Missing index")))
|
.ok_or_else(|| Error::from(err_msg("Missing index")))
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use libimagentrylink::internal::InternalLinker;
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
use crate::store::CATEGORY_REGISTER_NAME_FIELD_PATH;
|
use crate::store::CATEGORY_REGISTER_NAME_FIELD_PATH;
|
||||||
|
@ -49,6 +50,7 @@ impl Category for Entry {
|
||||||
trace!("Getting category name of '{:?}'", self.get_location());
|
trace!("Getting category name of '{:?}'", self.get_location());
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string(CATEGORY_REGISTER_NAME_FIELD_PATH)
|
.read_string(CATEGORY_REGISTER_NAME_FIELD_PATH)
|
||||||
|
.context(format_err!("Failed to read header at '{}'", CATEGORY_REGISTER_NAME_FIELD_PATH))
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.ok_or_else(|| Error::from(err_msg("Category name missing")))
|
.ok_or_else(|| Error::from(err_msg("Category name missing")))
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl EntryCategory for Entry {
|
||||||
trace!("Setting category '{}' UNCHECKED", s);
|
trace!("Setting category '{}' UNCHECKED", s);
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert(&String::from("category.value"), Value::String(s.to_string()))
|
.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)
|
.context(EM::EntryHeaderWriteError)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
@ -84,7 +84,7 @@ impl EntryCategory for Entry {
|
||||||
trace!("Has category? '{}'", self.get_location());
|
trace!("Has category? '{}'", self.get_location());
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read("category.value")
|
.read("category.value")
|
||||||
.map_err(Error::from)
|
.context(format_err!("Failed to read header at 'category.value' of '{}'", self.get_location()))
|
||||||
.context(EM::EntryHeaderReadError)
|
.context(EM::EntryHeaderReadError)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|x| x.is_some())
|
.map(|x| x.is_some())
|
||||||
|
@ -101,7 +101,7 @@ impl EntryCategory for Entry {
|
||||||
|
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.delete("category.value")
|
.delete("category.value")
|
||||||
.map_err(Error::from)
|
.context(format_err!("Failed to delete header at 'category.value' of '{}'", self.get_location()))
|
||||||
.context(EM::EntryHeaderWriteError)
|
.context(EM::EntryHeaderWriteError)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
use libimagstore::storeid::StoreIdIterator;
|
use libimagstore::storeid::StoreIdIterator;
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagerror::errors::ErrorMsg as EM;
|
|
||||||
|
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
|
||||||
|
@ -60,8 +59,8 @@ 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() {
|
||||||
match sid {
|
match sid.context("Error while iterating over category names").map_err(Error::from) {
|
||||||
Err(e) => return Some(Err(e).map_err(Error::from)),
|
Err(e) => return Some(Err(e)),
|
||||||
Ok(sid) => {
|
Ok(sid) => {
|
||||||
if sid.is_in_collection(&["category"]) {
|
if sid.is_in_collection(&["category"]) {
|
||||||
let func = |store: &Store| { // hack for returning Some(Result<_, _>)
|
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"))?
|
.ok_or_else(|| err_msg("Store read error"))?
|
||||||
.get_header()
|
.get_header()
|
||||||
.read_string(query)
|
.read_string(query)
|
||||||
.map_err(Error::from)
|
.context(format_err!("Failed to read header at '{}'", query))?
|
||||||
.context(EM::EntryHeaderReadError)?
|
|
||||||
.ok_or_else(|| err_msg("Store read error"))
|
.ok_or_else(|| err_msg("Store read error"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
};
|
};
|
||||||
|
@ -99,8 +97,8 @@ 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() {
|
||||||
match next {
|
match next.context("Error while iterating over category entries").map_err(Error::from) {
|
||||||
Err(e) => return Some(Err(e).map_err(Error::from)),
|
Err(e) => return Some(Err(e)),
|
||||||
Ok(next) => {
|
Ok(next) => {
|
||||||
let getter = |next| -> Result<(String, FileLockEntry<'a>)> {
|
let getter = |next| -> Result<(String, FileLockEntry<'a>)> {
|
||||||
let entry = self.0
|
let entry = self.0
|
||||||
|
|
|
@ -92,6 +92,9 @@ impl EntryDate for Entry {
|
||||||
|
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert(&DATE_HEADER_LOCATION, Value::String(date))
|
.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_err(Error::from)
|
||||||
.map(|opt| opt.map(|stri| {
|
.map(|opt| opt.map(|stri| {
|
||||||
stri.as_str()
|
stri.as_str()
|
||||||
|
|
|
@ -38,10 +38,10 @@
|
||||||
)]
|
)]
|
||||||
|
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
|
#[macro_use] extern crate failure;
|
||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate failure;
|
|
||||||
|
|
||||||
extern crate libimagerror;
|
extern crate libimagerror;
|
||||||
extern crate libimagstore;
|
extern crate libimagstore;
|
||||||
|
|
|
@ -66,7 +66,9 @@ impl EditHeader for Entry {
|
||||||
fn edit_header_and_content(&mut self, rt: &Runtime) -> Result<()> {
|
fn edit_header_and_content(&mut self, rt: &Runtime) -> Result<()> {
|
||||||
let mut header_and_content = self.to_str()?;
|
let mut header_and_content = self.to_str()?;
|
||||||
let _ = edit_in_tmpfile(rt, &mut header_and_content)?;
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use toml_query::read::TomlValueReadExt;
|
||||||
use filters::failable::filter::FailableFilter;
|
use filters::failable::filter::FailableFilter;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::builtin::header::field_path::FieldPath;
|
use crate::builtin::header::field_path::FieldPath;
|
||||||
|
@ -47,6 +48,9 @@ impl FailableFilter<Entry> for FieldExists {
|
||||||
fn filter(&self, e: &Entry) -> Result<bool> {
|
fn filter(&self, e: &Entry) -> Result<bool> {
|
||||||
e.get_header()
|
e.get_header()
|
||||||
.read(&self.header_field_path[..])
|
.read(&self.header_field_path[..])
|
||||||
|
.context(format_err!("Failed reading header '{}' in '{}'",
|
||||||
|
self.header_field_path,
|
||||||
|
e.get_location()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|o| o.is_some())
|
.map(|o| o.is_some())
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ extern crate regex;
|
||||||
extern crate semver;
|
extern crate semver;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
extern crate failure;
|
#[macro_use] extern crate failure;
|
||||||
|
|
||||||
extern crate libimagstore;
|
extern crate libimagstore;
|
||||||
extern crate libimagentrytag;
|
extern crate libimagentrytag;
|
||||||
|
|
|
@ -60,11 +60,16 @@ impl GPSEntry for Entry {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert("gps.coordinates", c.into())
|
.insert("gps.coordinates", c.into())
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
.context(format_err!("Error while inserting header 'gps.coordinates' in '{}'", self.get_location()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_coordinates(&self) -> Result<Option<Coordinates>> {
|
fn get_coordinates(&self) -> Result<Option<Coordinates>> {
|
||||||
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),
|
Some(hdr) => Coordinates::from_value(hdr).map(Some),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -89,7 +94,7 @@ impl GPSEntry for Entry {
|
||||||
let hdr = self.get_header_mut();
|
let hdr = self.get_header_mut();
|
||||||
for pattern in patterns.iter() {
|
for pattern in patterns.iter() {
|
||||||
let _ = hdr.delete(pattern)
|
let _ = hdr.delete(pattern)
|
||||||
.map_err(Error::from)
|
.context(format_err!("Error while deleting header '{}'", pattern))
|
||||||
.context("Error writing header")?;
|
.context("Error writing header")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
extern crate failure;
|
#[macro_use] extern crate failure;
|
||||||
|
|
||||||
extern crate libimagstore;
|
extern crate libimagstore;
|
||||||
extern crate libimagerror;
|
extern crate libimagerror;
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl Link for Entry {
|
||||||
fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> {
|
fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> {
|
||||||
self.get_header()
|
self.get_header()
|
||||||
.read_string("links.external.content.url")
|
.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)
|
.context(EM::EntryHeaderReadError)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.and_then(|opt| match opt {
|
.and_then(|opt| match opt {
|
||||||
|
@ -79,11 +79,13 @@ impl Link for Entry {
|
||||||
debug!("Found url, parsing: {:?}", s);
|
debug!("Found url, parsing: {:?}", s);
|
||||||
Url::parse(&s[..])
|
Url::parse(&s[..])
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
.context(format_err!("Failed to parse URL: '{}'", s))
|
||||||
.context(err_msg("Invalid URI"))
|
.context(err_msg("Invalid URI"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(Some)
|
.map(Some)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
.context("Failed to get link URI from entry")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +93,7 @@ impl Link for Entry {
|
||||||
match self.get_header().read_string("links.external.url")? {
|
match self.get_header().read_string("links.external.url")? {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
Some(ref s) => Url::parse(&s[..])
|
Some(ref s) => Url::parse(&s[..])
|
||||||
|
.context(format_err!("Failed to parse URL: '{}'", s))
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(EM::EntryHeaderReadError)
|
.context(EM::EntryHeaderReadError)
|
||||||
|
|
|
@ -265,7 +265,7 @@ impl InternalLinker for Entry {
|
||||||
let res = self
|
let res = self
|
||||||
.get_header()
|
.get_header()
|
||||||
.read("links.internal")
|
.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::EntryHeaderReadError)
|
||||||
.context(EM::EntryHeaderError)
|
.context(EM::EntryHeaderError)
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
@ -299,7 +299,7 @@ impl InternalLinker for Entry {
|
||||||
let res = self
|
let res = self
|
||||||
.get_header_mut()
|
.get_header_mut()
|
||||||
.insert("links.internal", Value::Array(new_links))
|
.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)
|
.context(EM::EntryHeaderReadError)
|
||||||
.map_err(Error::from);
|
.map_err(Error::from);
|
||||||
process_rw_result(res)
|
process_rw_result(res)
|
||||||
|
@ -336,7 +336,7 @@ impl InternalLinker for Entry {
|
||||||
|
|
||||||
fn unlink(&mut self, store: &Store) -> Result<()> {
|
fn unlink(&mut self, store: &Store) -> Result<()> {
|
||||||
for id in self.get_internal_links()?.map(|l| l.get_store_id().clone()) {
|
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)?,
|
Some(mut entry) => self.remove_internal_link(&mut entry)?,
|
||||||
None => return Err(err_msg("Link target does not exist")),
|
None => return Err(err_msg("Link target does not exist")),
|
||||||
}
|
}
|
||||||
|
@ -382,7 +382,7 @@ fn rewrite_links<I: Iterator<Item = Link>>(header: &mut Value, links: I) -> Resu
|
||||||
debug!("Setting new link array: {:?}", links);
|
debug!("Setting new link array: {:?}", links);
|
||||||
let process = header
|
let process = header
|
||||||
.insert("links.internal", Value::Array(links))
|
.insert("links.internal", Value::Array(links))
|
||||||
.map_err(Error::from)
|
.context(format_err!("Failed to insert header 'links.internal'"))
|
||||||
.context(EM::EntryHeaderReadError)
|
.context(EM::EntryHeaderReadError)
|
||||||
.map_err(Error::from);
|
.map_err(Error::from);
|
||||||
process_rw_result(process).map(|_| ())
|
process_rw_result(process).map(|_| ())
|
||||||
|
@ -409,7 +409,7 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
|
||||||
let res = target
|
let res = target
|
||||||
.get_header_mut()
|
.get_header_mut()
|
||||||
.insert("links.internal", Value::Array(links))
|
.insert("links.internal", Value::Array(links))
|
||||||
.map_err(Error::from)
|
.context(format_err!("Failed to insert header 'links.internal'"))
|
||||||
.context(EM::EntryHeaderReadError)
|
.context(EM::EntryHeaderReadError)
|
||||||
.map_err(Error::from);
|
.map_err(Error::from);
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub mod fassade {
|
||||||
use libimagentryutil::isa::Is;
|
use libimagentryutil::isa::Is;
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use crate::hasher::sha1::Sha1Hasher;
|
use crate::hasher::sha1::Sha1Hasher;
|
||||||
|
@ -104,7 +105,7 @@ pub mod fassade {
|
||||||
impl RefFassade for Entry {
|
impl RefFassade for Entry {
|
||||||
/// Check whether the underlying object is actually a ref
|
/// Check whether the underlying object is actually a ref
|
||||||
fn is_ref(&self) -> Result<bool> {
|
fn is_ref(&self) -> Result<bool> {
|
||||||
self.is::<IsRef>().map_err(Error::from)
|
self.is::<IsRef>().context("Failed to check is-ref flag").map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ref_with_hasher<H: Hasher>(&self) -> RefWithHasher<H> {
|
fn as_ref_with_hasher<H: Hasher>(&self) -> RefWithHasher<H> {
|
||||||
|
@ -163,7 +164,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
|
||||||
|
|
||||||
/// Check whether the underlying object is actually a ref
|
/// Check whether the underlying object is actually a ref
|
||||||
fn is_ref(&self) -> Result<bool> {
|
fn is_ref(&self) -> Result<bool> {
|
||||||
self.0.is::<IsRef>().map_err(Error::from)
|
self.0.is::<IsRef>().context("Failed to check is-ref flag").map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hash(&self) -> Result<&str> {
|
fn get_hash(&self) -> Result<&str> {
|
||||||
|
@ -171,6 +172,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
|
||||||
self.0
|
self.0
|
||||||
.get_header()
|
.get_header()
|
||||||
.read(&header_path)
|
.read(&header_path)
|
||||||
|
.context(format_err!("Failed to read header at '{}'", header_path))
|
||||||
.map_err(Error::from)?
|
.map_err(Error::from)?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::from(EM::EntryHeaderFieldMissing("ref.hash.<hash>"))
|
Error::from(EM::EntryHeaderFieldMissing("ref.hash.<hash>"))
|
||||||
|
@ -210,7 +212,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
|
||||||
self.0
|
self.0
|
||||||
.get_header()
|
.get_header()
|
||||||
.read("ref.relpath")
|
.read("ref.relpath")
|
||||||
.map_err(Error::from)?
|
.context("Failed to read header at 'ref.relpath'")?
|
||||||
.ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath")))
|
.ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath")))
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
v.as_str()
|
v.as_str()
|
||||||
|
@ -223,19 +225,20 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
|
||||||
fn hash_valid(&self, config: &Config) -> Result<bool> {
|
fn hash_valid(&self, config: &Config) -> Result<bool> {
|
||||||
let ref_header = self.0
|
let ref_header = self.0
|
||||||
.get_header()
|
.get_header()
|
||||||
.read("ref")?
|
.read("ref")
|
||||||
|
.context("Failed to read header at 'ref'")?
|
||||||
.ok_or_else(|| err_msg("Header missing at 'ref'"))?;
|
.ok_or_else(|| err_msg("Header missing at 'ref'"))?;
|
||||||
|
|
||||||
let basepath_name = ref_header
|
let basepath_name = ref_header
|
||||||
.read("basepath")
|
.read("basepath")
|
||||||
.map_err(Error::from)?
|
.context("Failed to read header at 'ref.basepath'")?
|
||||||
.ok_or_else(|| err_msg("Header missing at 'ref.basepath'"))?
|
.ok_or_else(|| err_msg("Header missing at 'ref.basepath'"))?
|
||||||
.as_str()
|
.as_str()
|
||||||
.ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?;
|
.ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash.<hash>", "string")))?;
|
||||||
|
|
||||||
let path = ref_header
|
let path = ref_header
|
||||||
.read("relpath")
|
.read("relpath")
|
||||||
.map_err(Error::from)?
|
.context("Failed to read header at 'ref.relpath'")?
|
||||||
.ok_or_else(|| err_msg("Header missing at 'ref.relpath'"))?
|
.ok_or_else(|| err_msg("Header missing at 'ref.relpath'"))?
|
||||||
.as_str()
|
.as_str()
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
|
@ -246,7 +249,7 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> {
|
||||||
|
|
||||||
ref_header
|
ref_header
|
||||||
.read(H::NAME)
|
.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))
|
.ok_or_else(|| format_err!("Header missing at 'ref.{}'", H::NAME))
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
v.as_str().ok_or_else(|| {
|
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());
|
trace!("Using relpath = {} to make header section", relpath.display());
|
||||||
make_header_section(hash, H::NAME, relpath, basepath_name)
|
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::<IsRef>())
|
.and_then(|_| self.0.set_isflag::<IsRef>())
|
||||||
.context("Making ref out of entry")?;
|
.context("Making ref out of entry")?;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ impl Tagable for Value {
|
||||||
|
|
||||||
fn get_tags(&self) -> Result<Vec<Tag>> {
|
fn get_tags(&self) -> Result<Vec<Tag>> {
|
||||||
self.read("tag.values")
|
self.read("tag.values")
|
||||||
|
.context(format_err!("Failed to read header at 'tag.values'"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.context(EM::EntryHeaderReadError)?
|
.context(EM::EntryHeaderReadError)?
|
||||||
.map(|val| {
|
.map(|val| {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
@ -79,7 +80,12 @@ impl Is for ::libimagstore::store::Entry {
|
||||||
fn is<T: IsKindHeaderPathProvider>(&self) -> Result<bool> {
|
fn is<T: IsKindHeaderPathProvider>(&self) -> Result<bool> {
|
||||||
let field = T::kindflag_header_location();
|
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),
|
Some(b) => Ok(b),
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
}
|
}
|
||||||
|
@ -88,6 +94,7 @@ impl Is for ::libimagstore::store::Entry {
|
||||||
fn set_isflag<T: IsKindHeaderPathProvider>(&mut self) -> Result<()> {
|
fn set_isflag<T: IsKindHeaderPathProvider>(&mut self) -> Result<()> {
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.insert(T::kindflag_header_location(), Value::Boolean(true))
|
.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_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -96,6 +103,7 @@ impl Is for ::libimagstore::store::Entry {
|
||||||
trace!("Trying to remove: {}", T::kindflag_header_location());
|
trace!("Trying to remove: {}", T::kindflag_header_location());
|
||||||
self.get_header_mut()
|
self.get_header_mut()
|
||||||
.delete(T::kindflag_header_location())
|
.delete(T::kindflag_header_location())
|
||||||
|
.context(format_err!("Failed deleting header '{}' in '{}'", T::kindflag_header_location(), self.get_location()))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
extern crate filters;
|
extern crate filters;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
extern crate failure;
|
#[macro_use] extern crate failure;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
|
||||||
extern crate libimagstore;
|
extern crate libimagstore;
|
||||||
|
|
|
@ -27,7 +27,6 @@ use crate::viewer::Viewer;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
|
||||||
|
|
||||||
pub struct EditorView<'a>(&'a Runtime<'a>);
|
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();
|
let mut entry = e.to_str()?.clone().to_string();
|
||||||
edit_in_tmpfile(self.0, &mut entry)
|
edit_in_tmpfile(self.0, &mut entry)
|
||||||
.context(err_msg("Error while viewing"))
|
.context("Error while viewing")
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,10 +178,12 @@ pub fn ask_select_from_list(list: &[&str]) -> Result<String> {
|
||||||
/// The `nl` parameter can be used to configure whether a newline character should be printed
|
/// 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<()> {
|
pub fn ask_question(question: &str, nl: bool, output: &mut Write) -> Result<()> {
|
||||||
if nl {
|
if nl {
|
||||||
writeln!(output, "[imag]: {}?", Yellow.paint(question)).map_err(Error::from)
|
writeln!(output, "[imag]: {}?", Yellow.paint(question))
|
||||||
} else {
|
} 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)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in a new issue