libimagentrylink: Move from error-chain to failure

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2018-10-30 18:40:51 +01:00
parent 7357f1c985
commit 32e8c43ccb
5 changed files with 85 additions and 162 deletions

View file

@ -27,8 +27,9 @@ url = "1.5"
sha-1 = "0.7" sha-1 = "0.7"
hex = "0.3" hex = "0.3"
is-match = "0.1" is-match = "0.1"
toml-query = "0.7" toml-query = { git = "https://github.com/matthiasbeyer/toml-query", branch = "failure" }
error-chain = "0.12" failure = "0.1"
failure_derive = "0.1"
libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" } libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" } libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" }

View file

@ -1,93 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use libimagstore::storeid::StoreId;
error_chain! {
types {
LinkError, LinkErrorKind, ResultExt, Result;
}
links {
StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind);
}
foreign_links {
TomlQueryError(::toml_query::error::Error);
UrlError(::url::ParseError);
}
errors {
EntryHeaderReadError {
description("Error while reading an entry header")
display("Error while reading an entry header")
}
EntryHeaderWriteError {
description("Error while writing an entry header")
display("Error while writing an entry header")
}
ExistingLinkTypeWrong {
description("Existing link entry has wrong type")
display("Existing link entry has wrong type")
}
LinkTargetDoesNotExist {
description("Link target does not exist in the store")
display("Link target does not exist in the store")
}
LinkParserError {
description("Link cannot be parsed")
display("Link cannot be parsed")
}
LinkParserFieldMissingError {
description("Link cannot be parsed: Field missing")
display("Link cannot be parsed: Field missing")
}
LinkParserFieldTypeError {
description("Link cannot be parsed: Field type wrong")
display("Link cannot be parsed: Field type wrong")
}
InternalConversionError {
description("Error while converting values internally")
display("Error while converting values internally")
}
InvalidUri {
description("URI is not valid")
display("URI is not valid")
}
DeadLink(from: StoreId, to: StoreId) {
description("Dead link")
display("Dead link from: {from} to: {to}", from = from, to = to)
}
LinkHandlingError {
description("Error in link handling")
display("Error in link handling")
}
}
}

View file

@ -39,16 +39,18 @@ use libimagstore::store::Store;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagutil::debug_result::*; use libimagutil::debug_result::*;
use libimagerror::errors::ErrorMsg as EM;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use toml_query::read::TomlValueReadTypeExt; use toml_query::read::TomlValueReadTypeExt;
use toml_query::insert::TomlValueInsertExt; use toml_query::insert::TomlValueInsertExt;
use failure::Error;
use failure::Fallible as Result;
use failure::ResultExt;
use failure::err_msg;
use error::LinkErrorKind as LEK;
use error::Result;
use internal::InternalLinker; use internal::InternalLinker;
use module_path::ModuleEntryPath; use module_path::ModuleEntryPath;
use error::ResultExt;
use self::iter::*; use self::iter::*;
@ -70,14 +72,21 @@ 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")
.chain_err(|| LEK::EntryHeaderReadError) .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.map_err(Error::from)
.and_then(|opt| match opt { .and_then(|opt| match opt {
None => Ok(None), None => Ok(None),
Some(ref s) => { Some(ref s) => {
debug!("Found url, parsing: {:?}", s); debug!("Found url, parsing: {:?}", s);
Url::parse(&s[..]).chain_err(|| LEK::InvalidUri).map(Some) Url::parse(&s[..])
.map_err(Error::from)
.context(err_msg("Invalid URI"))
.map_err(Error::from)
.map(Some)
}, },
}) })
.map_err(Error::from)
} }
fn get_url(&self) -> Result<Option<Url>> { fn get_url(&self) -> Result<Option<Url>> {
@ -85,7 +94,9 @@ impl Link for Entry {
None => Ok(None), None => Ok(None),
Some(ref s) => Url::parse(&s[..]) Some(ref s) => Url::parse(&s[..])
.map(Some) .map(Some)
.chain_err(|| LEK::EntryHeaderReadError), .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.map_err(Error::from),
} }
} }
@ -125,7 +136,7 @@ pub mod iter {
use internal::Link; use internal::Link;
use internal::iter::LinkIter; use internal::iter::LinkIter;
use error::Result; use failure::Fallible as Result;
use url::Url; use url::Url;

View file

@ -25,15 +25,15 @@ use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::IntoStoreId;
use libimagstore::store::Entry; use libimagstore::store::Entry;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagstore::store::Result as StoreResult; use libimagerror::errors::ErrorMsg as EM;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use toml_query::insert::TomlValueInsertExt; use toml_query::insert::TomlValueInsertExt;
use failure::ResultExt;
use failure::Fallible as Result;
use failure::Error;
use failure::err_msg;
use error::LinkErrorKind as LEK;
use error::LinkError as LE;
use error::ResultExt;
use error::Result;
use self::iter::LinkIter; use self::iter::LinkIter;
use self::iter::IntoValues; use self::iter::IntoValues;
@ -101,11 +101,15 @@ impl Link {
fn to_value(&self) -> Result<Value> { fn to_value(&self) -> Result<Value> {
match self { match self {
&Link::Id { link: ref s } => &Link::Id { link: ref s } =>
s.to_str().map(Value::String).chain_err(|| LEK::InternalConversionError), s.to_str()
.map(Value::String)
.context(EM::ConversionError)
.map_err(Error::from),
&Link::Annotated { ref link, annotation: ref anno } => { &Link::Annotated { ref link, annotation: ref anno } => {
link.to_str() link.to_str()
.map(Value::String) .map(Value::String)
.chain_err(|| LEK::InternalConversionError) .context(EM::ConversionError)
.map_err(Error::from)
.map(|link| { .map(|link| {
let mut tab = BTreeMap::new(); let mut tab = BTreeMap::new();
@ -148,7 +152,7 @@ impl Into<StoreId> for Link {
} }
impl IntoStoreId for Link { impl IntoStoreId for Link {
fn into_storeid(self) -> StoreResult<StoreId> { fn into_storeid(self) -> Result<StoreId> {
match self { match self {
Link::Id { link } => Ok(link), Link::Id { link } => Ok(link),
Link::Annotated { link, .. } => Ok(link), Link::Annotated { link, .. } => Ok(link),
@ -190,15 +194,15 @@ pub mod iter {
use std::vec::IntoIter; use std::vec::IntoIter;
use super::Link; use super::Link;
use error::LinkErrorKind as LEK; use failure::Error;
use error::ResultExt; use failure::Fallible as Result;
use error::Result; use failure::ResultExt;
use toml::Value; use toml::Value;
use itertools::Itertools; use itertools::Itertools;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagstore::store::FileLockEntry; use libimagstore::store::FileLockEntry;
use libimagerror::errors::ErrorMsg as EM;
pub struct LinkIter(IntoIter<Link>); pub struct LinkIter(IntoIter<Link>);
@ -232,7 +236,7 @@ pub mod iter {
.unique() .unique()
.sorted() .sorted()
.into_iter() // Cannot sort toml::Value, hence uglyness here .into_iter() // Cannot sort toml::Value, hence uglyness here
.map(|link| link.to_value().chain_err(|| LEK::InternalConversionError)) .map(|link| link.to_value().context(EM::ConversionError).map_err(Error::from))
.collect() .collect()
} }
} }
@ -393,7 +397,10 @@ impl InternalLinker for Entry {
let res = self let res = self
.get_header() .get_header()
.read("links.internal") .read("links.internal")
.chain_err(|| LEK::EntryHeaderReadError) .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.context(EM::EntryHeaderError)
.map_err(Error::from)
.map(|r| r.cloned()); .map(|r| r.cloned());
process_rw_result(res) process_rw_result(res)
} }
@ -417,19 +424,18 @@ impl InternalLinker for Entry {
let new_links = LinkIter::new(new_links) let new_links = LinkIter::new(new_links)
.into_values() .into_values()
.into_iter() .into_iter()
.fold(Ok(vec![]), |acc, elem| { .fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
acc.and_then(move |mut v| { acc.and_then(move |mut v| {
elem.chain_err(|| LEK::InternalConversionError) v.push(elem.context(EM::ConversionError)?);
.map(|e| { Ok(v)
v.push(e);
v
})
}) })
})?; })?;
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))
.chain_err(|| LEK::EntryHeaderReadError); .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.map_err(Error::from);
process_rw_result(res) process_rw_result(res)
} }
@ -464,9 +470,9 @@ 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(LE::from)? { match store.get(id).map_err(Error::from)? {
Some(mut entry) => self.remove_internal_link(&mut entry)?, Some(mut entry) => self.remove_internal_link(&mut entry)?,
None => return Err(LEK::LinkTargetDoesNotExist.into()), None => return Err(err_msg("Link target does not exist")),
} }
} }
@ -500,20 +506,19 @@ fn add_internal_link_with_instance(this: &mut Entry, link: &mut Entry, instance:
fn rewrite_links<I: Iterator<Item = Link>>(header: &mut Value, links: I) -> Result<()> { fn rewrite_links<I: Iterator<Item = Link>>(header: &mut Value, links: I) -> Result<()> {
let links = links.into_values() let links = links.into_values()
.into_iter() .into_iter()
.fold(Ok(vec![]), |acc, elem| { .fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
acc.and_then(move |mut v| { acc.and_then(move |mut v| {
elem.chain_err(|| LEK::InternalConversionError) v.push(elem.context(EM::ConversionError)?);
.map(|e| { Ok(v)
v.push(e);
v
})
}) })
})?; })?;
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))
.chain_err(|| LEK::EntryHeaderReadError); .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.map_err(Error::from);
process_rw_result(process).map(|_| ()) process_rw_result(process).map(|_| ())
} }
@ -527,13 +532,10 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
.chain(LinkIter::new(vec![from.into()])) .chain(LinkIter::new(vec![from.into()]))
.into_values() .into_values()
.into_iter() .into_iter()
.fold(Ok(vec![]), |acc, elem| { .fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
acc.and_then(move |mut v| { acc.and_then(move |mut v| {
elem.chain_err(|| LEK::InternalConversionError) v.push(elem.context(EM::ConversionError)?);
.map(|e| { Ok(v)
v.push(e);
v
})
}) })
})?; })?;
debug!("Setting links in {:?}: {:?}", target.get_location(), links); debug!("Setting links in {:?}: {:?}", target.get_location(), links);
@ -541,7 +543,9 @@ 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))
.chain_err(|| LEK::EntryHeaderReadError); .map_err(Error::from)
.context(EM::EntryHeaderReadError)
.map_err(Error::from);
process_rw_result(res).map(|_| ()) process_rw_result(res).map(|_| ())
}) })
@ -553,7 +557,7 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
let links = match links { let links = match links {
Err(e) => { Err(e) => {
debug!("RW action on store failed. Generating LinkError"); debug!("RW action on store failed. Generating LinkError");
return Err(e).chain_err(|| LEK::EntryHeaderReadError) return Err(e).context(EM::EntryHeaderReadError).map_err(Error::from)
}, },
Ok(None) => { Ok(None) => {
debug!("We got no value from the header!"); debug!("We got no value from the header!");
@ -562,14 +566,14 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
Ok(Some(Value::Array(l))) => l, Ok(Some(Value::Array(l))) => l,
Ok(Some(_)) => { Ok(Some(_)) => {
debug!("We expected an Array for the links, but there was a non-Array!"); debug!("We expected an Array for the links, but there was a non-Array!");
return Err(LEK::ExistingLinkTypeWrong.into()); return Err(err_msg("Link type error"));
} }
}; };
if !links.iter().all(|l| is_match!(*l, Value::String(_)) || is_match!(*l, Value::Table(_))) { if !links.iter().all(|l| is_match!(*l, Value::String(_)) || is_match!(*l, Value::Table(_))) {
debug!("At least one of the Values which were expected in the Array of links is not a String or a Table!"); debug!("At least one of the Values which were expected in the Array of links is not a String or a Table!");
debug!("Generating LinkError"); debug!("Generating LinkError");
return Err(LEK::ExistingLinkTypeWrong.into()); return Err(err_msg("Existing Link type error"));
} }
let links : Vec<Link> = links.into_iter() let links : Vec<Link> = links.into_iter()
@ -585,13 +589,13 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
if !tab.contains_key("link") if !tab.contains_key("link")
|| !tab.contains_key("annotation") { || !tab.contains_key("annotation") {
debug!("Things missing... returning Error instance"); debug!("Things missing... returning Error instance");
Err(LE::from_kind(LEK::LinkParserError)) Err(err_msg("Link parser error"))
} else { } else {
let link = tab.remove("link") let link = tab.remove("link")
.ok_or(LE::from_kind(LEK::LinkParserFieldMissingError))?; .ok_or(err_msg("Link parser: field missing"))?;
let anno = tab.remove("annotation") let anno = tab.remove("annotation")
.ok_or(LE::from_kind(LEK::LinkParserFieldMissingError))?; .ok_or(err_msg("Link parser: Field missing"))?;
debug!("Ok, here we go with building a Link::Annotated"); debug!("Ok, here we go with building a Link::Annotated");
match (link, anno) { match (link, anno) {
@ -605,7 +609,7 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
} }
}) })
}, },
_ => Err(LE::from_kind(LEK::LinkParserFieldTypeError)), _ => Err(err_msg("Link parser: Field type error")),
} }
} }
} }
@ -620,8 +624,11 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
pub mod store_check { pub mod store_check {
use libimagstore::store::Store; use libimagstore::store::Store;
use error::Result;
use error::ResultExt; use failure::ResultExt;
use failure::Fallible as Result;
use failure::Error;
use failure::err_msg;
pub trait StoreLinkConsistentExt { pub trait StoreLinkConsistentExt {
fn check_link_consistency(&self) -> Result<()>; fn check_link_consistency(&self) -> Result<()>;
@ -631,9 +638,6 @@ pub mod store_check {
fn check_link_consistency(&self) -> Result<()> { fn check_link_consistency(&self) -> Result<()> {
use std::collections::HashMap; use std::collections::HashMap;
use error::LinkErrorKind as LEK;
use error::LinkError as LE;
use error::Result as LResult;
use internal::InternalLinker; use internal::InternalLinker;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
@ -660,9 +664,7 @@ pub mod store_check {
.fold(Ok(HashMap::new()), |map, element| { .fold(Ok(HashMap::new()), |map, element| {
map.and_then(|mut map| { map.and_then(|mut map| {
debug!("Checking element = {:?}", element); debug!("Checking element = {:?}", element);
let entry = element?.ok_or_else(|| { let entry = element?.ok_or_else(|| err_msg("TODO: Not yet handled"))?;
LE::from(String::from("TODO: Not yet handled"))
})?;
debug!("Checking entry = {:?}", entry.get_location()); debug!("Checking entry = {:?}", entry.get_location());
@ -687,18 +689,18 @@ pub mod store_check {
// Helper to check whethre all StoreIds in the network actually exists // Helper to check whethre all StoreIds in the network actually exists
// //
// Because why not? // Because why not?
let all_collected_storeids_exist = |network: &HashMap<StoreId, Linking>| -> LResult<()> { let all_collected_storeids_exist = |network: &HashMap<StoreId, Linking>| -> Result<()> {
for (id, _) in network.iter() { for (id, _) in network.iter() {
if is_match!(self.get(id.clone()), Ok(Some(_))) { if is_match!(self.get(id.clone()), Ok(Some(_))) {
debug!("Exists in store: {:?}", id); debug!("Exists in store: {:?}", id);
if !id.exists()? { if !id.exists()? {
warn!("Does exist in store but not on FS: {:?}", id); warn!("Does exist in store but not on FS: {:?}", id);
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist)) return Err(err_msg("Link target does not exist"))
} }
} else { } else {
warn!("Does not exist in store: {:?}", id); warn!("Does not exist in store: {:?}", id);
return Err(LE::from_kind(LEK::LinkTargetDoesNotExist)) return Err(err_msg("Link target does not exist"))
} }
} }
@ -706,8 +708,10 @@ pub mod store_check {
}; };
// Helper function to create a SLCECD::OneDirectionalLink error object // Helper function to create a SLCECD::OneDirectionalLink error object
let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> LE { let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> Error {
LE::from_kind(LEK::DeadLink(src, target)) Error::from(format_err!("Dead link: {} -> {}",
src.local_display_string(),
target.local_display_string()))
}; };
// Helper lambda to check whether the _incoming_ links of each entry actually also // Helper lambda to check whether the _incoming_ links of each entry actually also
@ -760,7 +764,8 @@ pub mod store_check {
.and_then(|nw| { .and_then(|nw| {
all_collected_storeids_exist(&nw) all_collected_storeids_exist(&nw)
.map(|_| nw) .map(|_| nw)
.chain_err(|| LEK::LinkHandlingError) .context(err_msg("Link handling error"))
.map_err(Error::from)
}) })
.and_then(|nw| { .and_then(|nw| {
for (id, linking) in nw.iter() { for (id, linking) in nw.iter() {

View file

@ -43,7 +43,7 @@ extern crate url;
extern crate sha1; extern crate sha1;
extern crate hex; extern crate hex;
#[macro_use] extern crate is_match; #[macro_use] extern crate is_match;
#[macro_use] extern crate error_chain; #[macro_use] extern crate failure;
#[cfg(test)] #[cfg(test)]
extern crate env_logger; extern crate env_logger;
@ -54,7 +54,6 @@ extern crate libimagutil;
module_entry_path_mod!("links"); module_entry_path_mod!("links");
pub mod error;
pub mod external; pub mod external;
pub mod internal; pub mod internal;