libimagentrylink: Move from error-chain to failure
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
7357f1c985
commit
32e8c43ccb
5 changed files with 85 additions and 162 deletions
|
@ -27,8 +27,9 @@ url = "1.5"
|
|||
sha-1 = "0.7"
|
||||
hex = "0.3"
|
||||
is-match = "0.1"
|
||||
toml-query = "0.7"
|
||||
error-chain = "0.12"
|
||||
toml-query = { git = "https://github.com/matthiasbeyer/toml-query", branch = "failure" }
|
||||
failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
|
||||
libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" }
|
||||
libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" }
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,16 +39,18 @@ use libimagstore::store::Store;
|
|||
use libimagstore::storeid::StoreId;
|
||||
use libimagstore::storeid::IntoStoreId;
|
||||
use libimagutil::debug_result::*;
|
||||
use libimagerror::errors::ErrorMsg as EM;
|
||||
|
||||
use toml_query::read::TomlValueReadExt;
|
||||
use toml_query::read::TomlValueReadTypeExt;
|
||||
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 module_path::ModuleEntryPath;
|
||||
use error::ResultExt;
|
||||
|
||||
use self::iter::*;
|
||||
|
||||
|
@ -70,14 +72,21 @@ impl Link for Entry {
|
|||
fn get_link_uri_from_filelockentry(&self) -> Result<Option<Url>> {
|
||||
self.get_header()
|
||||
.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 {
|
||||
None => Ok(None),
|
||||
Some(ref 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>> {
|
||||
|
@ -85,7 +94,9 @@ impl Link for Entry {
|
|||
None => Ok(None),
|
||||
Some(ref s) => Url::parse(&s[..])
|
||||
.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::iter::LinkIter;
|
||||
use error::Result;
|
||||
use failure::Fallible as Result;
|
||||
|
||||
use url::Url;
|
||||
|
||||
|
|
|
@ -25,15 +25,15 @@ use libimagstore::storeid::StoreId;
|
|||
use libimagstore::storeid::IntoStoreId;
|
||||
use libimagstore::store::Entry;
|
||||
use libimagstore::store::Store;
|
||||
use libimagstore::store::Result as StoreResult;
|
||||
use libimagerror::errors::ErrorMsg as EM;
|
||||
|
||||
use toml_query::read::TomlValueReadExt;
|
||||
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::IntoValues;
|
||||
|
||||
|
@ -101,11 +101,15 @@ impl Link {
|
|||
fn to_value(&self) -> Result<Value> {
|
||||
match self {
|
||||
&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.to_str()
|
||||
.map(Value::String)
|
||||
.chain_err(|| LEK::InternalConversionError)
|
||||
.context(EM::ConversionError)
|
||||
.map_err(Error::from)
|
||||
.map(|link| {
|
||||
let mut tab = BTreeMap::new();
|
||||
|
||||
|
@ -148,7 +152,7 @@ impl Into<StoreId> for Link {
|
|||
}
|
||||
|
||||
impl IntoStoreId for Link {
|
||||
fn into_storeid(self) -> StoreResult<StoreId> {
|
||||
fn into_storeid(self) -> Result<StoreId> {
|
||||
match self {
|
||||
Link::Id { link } => Ok(link),
|
||||
Link::Annotated { link, .. } => Ok(link),
|
||||
|
@ -190,15 +194,15 @@ pub mod iter {
|
|||
use std::vec::IntoIter;
|
||||
use super::Link;
|
||||
|
||||
use error::LinkErrorKind as LEK;
|
||||
use error::ResultExt;
|
||||
use error::Result;
|
||||
|
||||
use failure::Error;
|
||||
use failure::Fallible as Result;
|
||||
use failure::ResultExt;
|
||||
use toml::Value;
|
||||
use itertools::Itertools;
|
||||
|
||||
use libimagstore::store::Store;
|
||||
use libimagstore::store::FileLockEntry;
|
||||
use libimagerror::errors::ErrorMsg as EM;
|
||||
|
||||
pub struct LinkIter(IntoIter<Link>);
|
||||
|
||||
|
@ -232,7 +236,7 @@ pub mod iter {
|
|||
.unique()
|
||||
.sorted()
|
||||
.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()
|
||||
}
|
||||
}
|
||||
|
@ -393,7 +397,10 @@ impl InternalLinker for Entry {
|
|||
let res = self
|
||||
.get_header()
|
||||
.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());
|
||||
process_rw_result(res)
|
||||
}
|
||||
|
@ -417,19 +424,18 @@ impl InternalLinker for Entry {
|
|||
let new_links = LinkIter::new(new_links)
|
||||
.into_values()
|
||||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
.fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
elem.chain_err(|| LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
v
|
||||
})
|
||||
v.push(elem.context(EM::ConversionError)?);
|
||||
Ok(v)
|
||||
})
|
||||
})?;
|
||||
let res = self
|
||||
.get_header_mut()
|
||||
.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)
|
||||
}
|
||||
|
||||
|
@ -464,9 +470,9 @@ 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(LE::from)? {
|
||||
match store.get(id).map_err(Error::from)? {
|
||||
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<()> {
|
||||
let links = links.into_values()
|
||||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
.fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
elem.chain_err(|| LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
v
|
||||
})
|
||||
v.push(elem.context(EM::ConversionError)?);
|
||||
Ok(v)
|
||||
})
|
||||
})?;
|
||||
|
||||
debug!("Setting new link array: {:?}", links);
|
||||
let process = header
|
||||
.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(|_| ())
|
||||
}
|
||||
|
||||
|
@ -527,13 +532,10 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
|
|||
.chain(LinkIter::new(vec![from.into()]))
|
||||
.into_values()
|
||||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
.fold(Ok(vec![]), |acc: Result<Vec<_>>, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
elem.chain_err(|| LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
v
|
||||
})
|
||||
v.push(elem.context(EM::ConversionError)?);
|
||||
Ok(v)
|
||||
})
|
||||
})?;
|
||||
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
|
||||
.get_header_mut()
|
||||
.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(|_| ())
|
||||
})
|
||||
|
@ -553,7 +557,7 @@ fn process_rw_result(links: Result<Option<Value>>) -> Result<LinkIter> {
|
|||
let links = match links {
|
||||
Err(e) => {
|
||||
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) => {
|
||||
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(_)) => {
|
||||
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(_))) {
|
||||
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");
|
||||
return Err(LEK::ExistingLinkTypeWrong.into());
|
||||
return Err(err_msg("Existing Link type error"));
|
||||
}
|
||||
|
||||
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")
|
||||
|| !tab.contains_key("annotation") {
|
||||
debug!("Things missing... returning Error instance");
|
||||
Err(LE::from_kind(LEK::LinkParserError))
|
||||
Err(err_msg("Link parser error"))
|
||||
} else {
|
||||
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")
|
||||
.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");
|
||||
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 {
|
||||
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 {
|
||||
fn check_link_consistency(&self) -> Result<()>;
|
||||
|
@ -631,9 +638,6 @@ pub mod store_check {
|
|||
fn check_link_consistency(&self) -> Result<()> {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use error::LinkErrorKind as LEK;
|
||||
use error::LinkError as LE;
|
||||
use error::Result as LResult;
|
||||
use internal::InternalLinker;
|
||||
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
@ -660,9 +664,7 @@ pub mod store_check {
|
|||
.fold(Ok(HashMap::new()), |map, element| {
|
||||
map.and_then(|mut map| {
|
||||
debug!("Checking element = {:?}", element);
|
||||
let entry = element?.ok_or_else(|| {
|
||||
LE::from(String::from("TODO: Not yet handled"))
|
||||
})?;
|
||||
let entry = element?.ok_or_else(|| err_msg("TODO: Not yet handled"))?;
|
||||
|
||||
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
|
||||
//
|
||||
// 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() {
|
||||
if is_match!(self.get(id.clone()), Ok(Some(_))) {
|
||||
debug!("Exists in store: {:?}", id);
|
||||
|
||||
if !id.exists()? {
|
||||
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 {
|
||||
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
|
||||
let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> LE {
|
||||
LE::from_kind(LEK::DeadLink(src, target))
|
||||
let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> Error {
|
||||
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
|
||||
|
@ -760,7 +764,8 @@ pub mod store_check {
|
|||
.and_then(|nw| {
|
||||
all_collected_storeids_exist(&nw)
|
||||
.map(|_| nw)
|
||||
.chain_err(|| LEK::LinkHandlingError)
|
||||
.context(err_msg("Link handling error"))
|
||||
.map_err(Error::from)
|
||||
})
|
||||
.and_then(|nw| {
|
||||
for (id, linking) in nw.iter() {
|
||||
|
|
|
@ -43,7 +43,7 @@ extern crate url;
|
|||
extern crate sha1;
|
||||
extern crate hex;
|
||||
#[macro_use] extern crate is_match;
|
||||
#[macro_use] extern crate error_chain;
|
||||
#[macro_use] extern crate failure;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate env_logger;
|
||||
|
@ -54,7 +54,6 @@ extern crate libimagutil;
|
|||
|
||||
module_entry_path_mod!("links");
|
||||
|
||||
pub mod error;
|
||||
pub mod external;
|
||||
pub mod internal;
|
||||
|
||||
|
|
Loading…
Reference in a new issue