diff --git a/bin/core/imag-store/Cargo.toml b/bin/core/imag-store/Cargo.toml index c31f629e..55aac2ed 100644 --- a/bin/core/imag-store/Cargo.toml +++ b/bin/core/imag-store/Cargo.toml @@ -18,6 +18,7 @@ clap = ">=2.17" log = "0.3" version = "2.0.1" toml = "^0.4" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore", features = ["verify"] } libimagrt = { version = "0.4.0", path = "../../../lib/core/libimagrt" } diff --git a/bin/core/imag-store/src/create.rs b/bin/core/imag-store/src/create.rs index 68bb9667..74ffbec9 100644 --- a/bin/core/imag-store/src/create.rs +++ b/bin/core/imag-store/src/create.rs @@ -38,6 +38,7 @@ use libimagutil::debug_result::*; use error::StoreError; use error::StoreErrorKind; +use error::ResultExt; use util::build_toml_header; type Result = RResult; @@ -110,7 +111,7 @@ fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> R fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> { let content = matches .value_of("from-raw") - .ok_or(StoreError::new(StoreErrorKind::NoCommandlineCall, None)) + .ok_or(StoreError::from_kind(StoreErrorKind::NoCommandlineCall)) .map(string_from_raw_src); if content.is_err() { @@ -133,7 +134,7 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Res r }) .map_dbg_err(|e| format!("Error storing entry: {:?}", e)) - .map_err(|serr| StoreError::new(StoreErrorKind::BackendError, Some(Box::new(serr)))) + .chain_err(|| StoreErrorKind::BackendError) } fn create_with_content_and_header(rt: &Runtime, @@ -157,7 +158,7 @@ fn create_with_content_and_header(rt: &Runtime, debug!("New header set"); } }) - .map_err(|e| StoreError::new(StoreErrorKind::BackendError, Some(Box::new(e)))) + .chain_err(|| StoreErrorKind::BackendError) } fn string_from_raw_src(raw_src: &str) -> String { diff --git a/bin/core/imag-store/src/error.rs b/bin/core/imag-store/src/error.rs index bc248ade..59f9dc78 100644 --- a/bin/core/imag-store/src/error.rs +++ b/bin/core/imag-store/src/error.rs @@ -17,13 +17,22 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(StoreError, StoreErrorKind, - BackendError => "Backend Error", - NoCommandlineCall => "No commandline call" - ); -); +error_chain! { + types { + StoreError, StoreErrorKind, ResultExt, Result; + } -pub use self::error::StoreError; -pub use self::error::StoreErrorKind; + errors { + BackendError { + description("Backend Error") + display("Backend Error") + } + + NoCommandlineCall { + description("No commandline call") + display("No commandline call") + } + + } +} diff --git a/bin/core/imag-store/src/main.rs b/bin/core/imag-store/src/main.rs index bb4d2ebc..572f9e0d 100644 --- a/bin/core/imag-store/src/main.rs +++ b/bin/core/imag-store/src/main.rs @@ -37,14 +37,16 @@ extern crate clap; extern crate toml; #[cfg(test)] extern crate toml_query; #[macro_use] extern crate version; +#[macro_use] extern crate error_chain; extern crate libimagrt; extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; #[cfg(test)] #[macro_use] extern crate libimagutil; + #[cfg(not(test))] extern crate libimagutil; diff --git a/bin/domain/imag-diary/src/create.rs b/bin/domain/imag-diary/src/create.rs index b93c2805..69760399 100644 --- a/bin/domain/imag-diary/src/create.rs +++ b/bin/domain/imag-diary/src/create.rs @@ -24,7 +24,7 @@ use clap::ArgMatches; use libimagdiary::diary::Diary; use libimagdiary::diaryid::DiaryId; use libimagdiary::error::DiaryErrorKind as DEK; -use libimagdiary::error::MapErrInto; +use libimagdiary::error::ResultExt; use libimagentryedit::edit::Edit; use libimagrt::runtime::Runtime; use libimagerror::trace::trace_error_exit; @@ -46,7 +46,7 @@ pub fn create(rt: &Runtime) { } else { debug!("Editing new diary entry"); entry.edit_content(rt) - .map_err_into(DEK::DiaryEditError) + .chain_err(|| DEK::DiaryEditError) }; if let Err(e) = res { @@ -63,7 +63,7 @@ fn create_entry<'a>(diary: &'a Store, diaryname: &str, rt: &Runtime) -> FileLock diary.new_entry_today(diaryname) } else { let id = create_id_from_clispec(&create, &diaryname); - diary.retrieve(id).map_err_into(DEK::StoreReadError) + diary.retrieve(id).chain_err(|| DEK::StoreReadError) }; match entry { diff --git a/bin/domain/imag-diary/src/edit.rs b/bin/domain/imag-diary/src/edit.rs index c623e1fa..c3c99813 100644 --- a/bin/domain/imag-diary/src/edit.rs +++ b/bin/domain/imag-diary/src/edit.rs @@ -24,11 +24,11 @@ use chrono::naive::NaiveDateTime; use libimagdiary::diary::Diary; use libimagdiary::diaryid::DiaryId; use libimagdiary::error::DiaryErrorKind as DEK; -use libimagdiary::error::MapErrInto; +use libimagdiary::error::DiaryError as DE; +use libimagdiary::error::ResultExt; use libimagentryedit::edit::Edit; use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; -use libimagerror::into::IntoError; use libimagtimeui::datetime::DateTime; use libimagtimeui::parse::Parse; use libimagutil::warn_exit::warn_exit; @@ -60,8 +60,8 @@ pub fn edit(rt: &Runtime) { }) .and_then(|id| rt.store().get(id)) .map(|opte| match opte { - Some(mut e) => e.edit_content(rt).map_err_into(DEK::IOError), - None => Err(DEK::EntryNotInDiary.into_error()), + Some(mut e) => e.edit_content(rt).chain_err(|| DEK::IOError), + None => Err(DE::from_kind(DEK::EntryNotInDiary)), }) .map_err_trace() .ok(); diff --git a/bin/domain/imag-diary/src/list.rs b/bin/domain/imag-diary/src/list.rs index 90a8dd96..768ebc45 100644 --- a/bin/domain/imag-diary/src/list.rs +++ b/bin/domain/imag-diary/src/list.rs @@ -19,7 +19,7 @@ use libimagdiary::diary::Diary; use libimagdiary::error::DiaryErrorKind as DEK; -use libimagdiary::error::MapErrInto; +use libimagdiary::error::ResultExt; use libimagentrylist::listers::core::CoreLister; use libimagentrylist::lister::Lister; use libimagrt::runtime::Runtime; @@ -57,7 +57,7 @@ pub fn list(rt: &Runtime) { CoreLister::new(&entry_to_location_listing_string) .list(es) - .map_err_into(DEK::IOError) + .chain_err(|| DEK::IOError) }) .map_dbg_str("Ok") .map_err_trace() diff --git a/bin/domain/imag-mail/src/main.rs b/bin/domain/imag-mail/src/main.rs index 8596d77b..7987e281 100644 --- a/bin/domain/imag-mail/src/main.rs +++ b/bin/domain/imag-mail/src/main.rs @@ -66,13 +66,13 @@ fn import_mail(rt: &Runtime) { fn list(rt: &Runtime) { use libimagmail::error::MailErrorKind as MEK; - use libimagmail::error::MapErrInto; + use libimagmail::error::ResultExt; let store = rt.store(); let iter = match store.retrieve_for_module("ref") { Ok(iter) => iter.filter_map(|id| { - match store.get(id).map_err_into(MEK::RefHandlingError).map_err_trace() { + match store.get(id).chain_err(|| MEK::RefHandlingError).map_err_trace() { Ok(Some(fle)) => Mail::from_fle(fle).map_err_trace().ok(), Ok(None) => None, Err(e) => trace_error_exit(&e, 1), diff --git a/doc/src/09000-todos.md b/doc/src/09000-todos.md index 1c86156f..220b4dbd 100644 --- a/doc/src/09000-todos.md +++ b/doc/src/09000-todos.md @@ -72,15 +72,15 @@ Now the modules that are not yet started: ## Libraries -- [ ] Ensure all libraries are implemented as extension traits rather than - wrapping store types -- [ ] Rewrite logger to allow config/env-var based module white/blacklisting and - writing log to file -- [ ] Rewrite libimagerror to be based on `chain-error` crate. This basically +- [x] Rewrite libimagerror to be based on `chain-error` crate. This basically removes our error infrastructure, though existing traits and convenience functionality should be kept (for example the `MapErrInto` or the `IntoError` traits), as much as possible). If the switch to `chain-error` would require too much code to be rewritten, reconsider. +- [ ] Ensure all libraries are implemented as extension traits rather than + wrapping store types +- [ ] Rewrite logger to allow config/env-var based module white/blacklisting and + writing log to file ## User Interface diff --git a/doc/src/09020-changelog.md b/doc/src/09020-changelog.md index f0105f4b..13feccdf 100644 --- a/doc/src/09020-changelog.md +++ b/doc/src/09020-changelog.md @@ -26,6 +26,9 @@ This section contains the changelog from the last release to the next release. subdirectories were introduced for different types of crates * The documentation got a major overhaul and was partly rewritten * The logger is now configurable via the config file. + * The error handling of the whole codebase is based on the `error_chain` + now. `libimagerror` only contains convenience functionality, no + error-generating macros or such things anymore. * New * `libimagentrygps` was introduced * Fixed bugs diff --git a/lib/core/libimagerror/src/error_gen.rs b/lib/core/libimagerror/src/error_gen.rs deleted file mode 100644 index eb06692c..00000000 --- a/lib/core/libimagerror/src/error_gen.rs +++ /dev/null @@ -1,440 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 -// - -#[macro_export] -macro_rules! generate_error_imports { - () => { - use std::error::Error; - use std::fmt::Error as FmtError; - use std::fmt::{Display, Formatter}; - - use $crate::into::IntoError; - } -} - -#[macro_export] -macro_rules! generate_error_module { - ( $exprs:item ) => { - pub mod error { - generate_error_imports!(); - $exprs - } - } -} - -#[macro_export] -macro_rules! generate_custom_error_types { - { - $name: ident, - $kindname: ident, - $customMemberTypeName: ident, - $($kind:ident => $string:expr),* - } => { - #[derive(Clone, Copy, Debug, PartialEq)] - pub enum $kindname { - $( $kind ),* - } - - impl Display for $kindname { - - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { - let s = match *self { - $( $kindname::$kind => $string ),* - }; - try!(write!(fmt, "{}", s)); - Ok(()) - } - - } - - impl IntoError for $kindname { - type Target = $name; - - fn into_error(self) -> Self::Target { - $name::new(self, None) - } - - fn into_error_with_cause(self, cause: Box) -> Self::Target { - $name::new(self, Some(cause)) - } - - } - - #[derive(Debug)] - pub struct $name { - err_type: $kindname, - cause: Option>, - custom_data: Option<$customMemberTypeName>, - } - - impl $name { - - pub fn new(errtype: $kindname, cause: Option>) -> $name { - $name { - err_type: errtype, - cause: cause, - custom_data: None, - } - } - - #[allow(dead_code)] - pub fn err_type(&self) -> $kindname { - self.err_type - } - - #[allow(dead_code)] - pub fn with_custom_data(mut self, custom: $customMemberTypeName) -> $name { - self.custom_data = Some(custom); - self - } - - } - - impl Into<$name> for $kindname { - - fn into(self) -> $name { - $name::new(self, None) - } - - } - - impl Display for $name { - - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { - try!(write!(fmt, "[{}]", self.err_type)); - match self.custom_data { - Some(ref c) => write!(fmt, "{}", c), - None => Ok(()), - } - } - - } - - impl Error for $name { - - fn description(&self) -> &str { - match self.err_type { - $( $kindname::$kind => $string ),* - } - } - - fn cause(&self) -> Option<&Error> { - self.cause.as_ref().map(|e| &**e) - } - - } - - } -} - -#[macro_export] -macro_rules! generate_result_helper { - ( - $name: ident, - $kindname: ident - ) => { - /// Trait to replace - /// - /// ```ignore - /// foo.map_err(Box::new).map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(e)) - /// // or: - /// foo.map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(Box::new(e))) - /// ``` - /// - /// with much nicer - /// - /// ```ignore - /// foo.map_err_into(SomeType::SomeErrorKind) - /// ``` - /// - pub trait MapErrInto { - fn map_err_into(self, error_kind: $kindname) -> Result; - } - - impl MapErrInto for Result { - - fn map_err_into(self, error_kind: $kindname) -> Result { - self.map_err(Box::new) - .map_err(|e| error_kind.into_error_with_cause(e)) - } - - } - } -} - -#[macro_export] -macro_rules! generate_option_helper { - ( - $name: ident, - $kindname: ident - ) => { - /// Trait to replace - /// - /// ```ignore - /// foo.ok_or(SomeType::SomeErrorKind.into_error()) - /// ``` - /// - /// with - /// - /// ```ignore - /// foo.ok_or_errkind(SomeType::SomeErrorKind) - /// ``` - pub trait OkOrErr { - fn ok_or_errkind(self, kind: $kindname) -> Result; - } - - impl OkOrErr for Option { - - fn ok_or_errkind(self, kind: $kindname) -> Result { - self.ok_or(kind.into_error()) - } - - } - } -} - -#[macro_export] -macro_rules! generate_error_types { - ( - $name: ident, - $kindname: ident, - $($kind:ident => $string:expr),* - ) => { - #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)] - pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {} - - impl Display for SomeNotExistingTypeWithATypeNameNoOneWillEverChoose { - fn fmt(&self, _: &mut Formatter) -> Result<(), FmtError> { - Ok(()) - } - } - - generate_custom_error_types!($name, $kindname, - SomeNotExistingTypeWithATypeNameNoOneWillEverChoose, - $($kind => $string),*); - - generate_result_helper!($name, $kindname); - generate_option_helper!($name, $kindname); - } -} - - -#[cfg(test)] -#[allow(dead_code)] -mod test { - - generate_error_module!( - generate_error_types!(TestError, TestErrorKind, - TestErrorKindA => "testerrorkind a", - TestErrorKindB => "testerrorkind B"); - ); - - #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)] - pub struct CustomData { - pub test: i32, - pub othr: i64, - } - - impl Display for CustomData { - fn fmt(&self, _: &mut Formatter) -> Result<(), FmtError> { - Ok(()) - } - } - - generate_error_imports!(); - - #[allow(dead_code)] - generate_custom_error_types!(CustomTestError, CustomTestErrorKind, - CustomData, - CustomErrorKindA => "customerrorkind a", - CustomErrorKindB => "customerrorkind B"); - - // Allow dead code here. - // We wrote this to show that custom test types can be implemented. - #[allow(dead_code)] - impl CustomTestError { - pub fn test(&self) -> i32 { - match self.custom_data { - Some(t) => t.test, - None => 0, - } - } - - pub fn bar(&self) -> i64 { - match self.custom_data { - Some(t) => t.othr, - None => 0, - } - } - } - - - #[test] - fn test_a() { - use self::error::{TestError, TestErrorKind}; - - let kind = TestErrorKind::TestErrorKindA; - assert_eq!(String::from("testerrorkind a"), format!("{}", kind)); - - let e = TestError::new(kind, None); - assert_eq!(String::from("[testerrorkind a]"), format!("{}", e)); - } - - #[test] - fn test_b() { - use self::error::{TestError, TestErrorKind}; - - let kind = TestErrorKind::TestErrorKindB; - assert_eq!(String::from("testerrorkind B"), format!("{}", kind)); - - let e = TestError::new(kind, None); - assert_eq!(String::from("[testerrorkind B]"), format!("{}", e)); - - } - - #[test] - fn test_ab() { - use std::error::Error; - use self::error::{TestError, TestErrorKind}; - - let kinda = TestErrorKind::TestErrorKindA; - let kindb = TestErrorKind::TestErrorKindB; - assert_eq!(String::from("testerrorkind a"), format!("{}", kinda)); - assert_eq!(String::from("testerrorkind B"), format!("{}", kindb)); - - let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None)))); - assert_eq!(String::from("[testerrorkind a]"), format!("{}", e)); - assert_eq!(TestErrorKind::TestErrorKindA, e.err_type()); - assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap())); - } - - pub mod anothererrormod { - generate_error_imports!(); - generate_error_types!(TestError, TestErrorKind, - TestErrorKindA => "testerrorkind a", - TestErrorKindB => "testerrorkind B"); - } - - #[test] - fn test_other_a() { - use self::anothererrormod::{TestError, TestErrorKind}; - - let kind = TestErrorKind::TestErrorKindA; - assert_eq!(String::from("testerrorkind a"), format!("{}", kind)); - - let e = TestError::new(kind, None); - assert_eq!(String::from("[testerrorkind a]"), format!("{}", e)); - } - - #[test] - fn test_other_b() { - use self::anothererrormod::{TestError, TestErrorKind}; - - let kind = TestErrorKind::TestErrorKindB; - assert_eq!(String::from("testerrorkind B"), format!("{}", kind)); - - let e = TestError::new(kind, None); - assert_eq!(String::from("[testerrorkind B]"), format!("{}", e)); - - } - - #[test] - fn test_other_ab() { - use std::error::Error; - use self::anothererrormod::{TestError, TestErrorKind}; - - let kinda = TestErrorKind::TestErrorKindA; - let kindb = TestErrorKind::TestErrorKindB; - assert_eq!(String::from("testerrorkind a"), format!("{}", kinda)); - assert_eq!(String::from("testerrorkind B"), format!("{}", kindb)); - - let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None)))); - assert_eq!(String::from("[testerrorkind a]"), format!("{}", e)); - assert_eq!(TestErrorKind::TestErrorKindA, e.err_type()); - assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap())); - } - - #[test] - fn test_error_kind_mapping() { - use std::io::{Error, ErrorKind}; - use self::error::MapErrInto; - use self::error::TestErrorKind; - - let err : Result<(), _> = Err(Error::new(ErrorKind::Other, "")); - let err : Result<(), _> = err.map_err_into(TestErrorKind::TestErrorKindA); - - assert!(err.is_err()); - let err = err.unwrap_err(); - - match err.err_type() { - TestErrorKind::TestErrorKindA => assert!(true), - _ => assert!(false), - } - } - - #[test] - fn test_error_kind_double_mapping() { - use std::io::{Error, ErrorKind}; - use self::error::MapErrInto; - use self::error::TestErrorKind; - - let err : Result<(), _> = Err(Error::new(ErrorKind::Other, "")); - let err : Result<(), _> = err.map_err_into(TestErrorKind::TestErrorKindA) - .map_err_into(TestErrorKind::TestErrorKindB); - - assert!(err.is_err()); - let err = err.unwrap_err(); - match err.err_type() { - TestErrorKind::TestErrorKindB => assert!(true), - _ => assert!(false), - } - - // not sure how to test that the inner error is of TestErrorKindA, actually... - match err.cause() { - Some(_) => assert!(true), - None => assert!(false), - } - - } - - #[test] - fn test_error_option_good() { - use self::error::OkOrErr; - use self::error::TestErrorKind; - - let something = Some(1); - match something.ok_or_errkind(TestErrorKind::TestErrorKindA) { - Ok(1) => assert!(true), - _ => assert!(false), - } - } - - #[test] - fn test_error_option_bad() { - use self::error::OkOrErr; - use self::error::TestErrorKind; - - let something : Option = None; - match something.ok_or_errkind(TestErrorKind::TestErrorKindA) { - Ok(_) => assert!(false), - Err(_) => assert!(true), - } - } - -} diff --git a/lib/core/libimagerror/src/into.rs b/lib/core/libimagerror/src/into.rs deleted file mode 100644 index bc3cfb41..00000000 --- a/lib/core/libimagerror/src/into.rs +++ /dev/null @@ -1,33 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::error::Error; - -/// Trait to help converting Error kinds into Error instances -pub trait IntoError { - type Target: Error; - - /// Convert the type into an error with no cause - fn into_error(self) -> Self::Target; - - /// Convert the type into an error with cause - fn into_error_with_cause(self, cause: Box) -> Self::Target; - -} - diff --git a/lib/core/libimagerror/src/iter.rs b/lib/core/libimagerror/src/iter.rs index 0297bc6a..3de78922 100644 --- a/lib/core/libimagerror/src/iter.rs +++ b/lib/core/libimagerror/src/iter.rs @@ -168,10 +168,10 @@ impl TraceIterator for I where #[cfg(test)] mod test { use super::TraceIterator; - + #[derive(Copy, Clone, Eq, PartialEq, Debug)] struct TestError(i32); - + #[test] fn test_unwrap_with() { let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))]; diff --git a/lib/core/libimagerror/src/lib.rs b/lib/core/libimagerror/src/lib.rs index 0ed1e7f3..73d6ed70 100644 --- a/lib/core/libimagerror/src/lib.rs +++ b/lib/core/libimagerror/src/lib.rs @@ -36,7 +36,5 @@ #[macro_use] extern crate log; extern crate ansi_term; -pub mod into; -pub mod error_gen; pub mod trace; pub mod iter; diff --git a/lib/core/libimagrt/Cargo.toml b/lib/core/libimagrt/Cargo.toml index e557ecd4..5f8fe240 100644 --- a/lib/core/libimagrt/Cargo.toml +++ b/lib/core/libimagrt/Cargo.toml @@ -23,6 +23,7 @@ itertools = "0.5" ansi_term = "0.9" is-match = "0.1" toml-query = "0.3.0" +error-chain = "0.10" handlebars = "0.29.0" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/core/libimagrt/src/configuration.rs b/lib/core/libimagrt/src/configuration.rs index bc3b52b4..87eb86c8 100644 --- a/lib/core/libimagrt/src/configuration.rs +++ b/lib/core/libimagrt/src/configuration.rs @@ -18,29 +18,45 @@ // use std::path::PathBuf; -use std::result::Result as RResult; use std::ops::Deref; use toml::Value; use clap::App; -generate_error_module!( - generate_error_types!(ConfigError, ConfigErrorKind, - TOMLParserError => "TOML Parsing error", - NoConfigFileFound => "No config file found", +error_chain! { + types { + ConfigError, ConfigErrorKind, ResultExt, Result; + } - ConfigOverrideError => "Config override error", - ConfigOverrideKeyNotAvailable => "Key not available", - ConfigOverrideTypeNotMatching => "Configuration Type not matching" + errors { + TOMLParserError { + description("TOML Parsing error") + display("TOML Parsing error") + } - ); -); + NoConfigFileFound { + description("No config file found") + display("No config file found") + } -pub use self::error::{ConfigError, ConfigErrorKind, MapErrInto}; -use libimagerror::into::IntoError; + ConfigOverrideError { + description("Config override error") + display("Config override error") + } -/// Result type of this module. Either `T` or `ConfigError` -pub type Result = RResult; + ConfigOverrideKeyNotAvailable { + description("Key not available") + display("Key not available") + } + + ConfigOverrideTypeNotMatching { + description("Configuration Type not matching") + display("Configuration Type not matching") + } + } +} +use self::ConfigErrorKind as CEK; +use self::ConfigError as CE; /// `Configuration` object /// @@ -130,9 +146,6 @@ impl Configuration { pub fn override_config(&mut self, v: Vec) -> Result<()> { use libimagutil::key_value_split::*; use libimagutil::iter::*; - use self::error::ConfigErrorKind as CEK; - use self::error::MapErrInto; - use libimagerror::into::IntoError; use toml_query::read::TomlValueReadExt; @@ -148,21 +161,20 @@ impl Configuration { .map(|(k, v)| self .config .read(&k[..]) - .map_err_into(CEK::TOMLParserError) + .chain_err(|| CEK::TOMLParserError) .map(|toml| match toml { Some(value) => match into_value(value, v) { Some(v) => { info!("Successfully overridden: {} = {}", k, v); Ok(v) }, - None => Err(CEK::ConfigOverrideTypeNotMatching.into_error()), + None => Err(CE::from_kind(CEK::ConfigOverrideTypeNotMatching)), }, - None => Err(CEK::ConfigOverrideKeyNotAvailable.into_error()), + None => Err(CE::from_kind(CEK::ConfigOverrideKeyNotAvailable)), }) ) .fold_result(|i| i) - .map_err(Box::new) - .map_err(|e| CEK::ConfigOverrideError.into_error_with_cause(e)) + .chain_err(|| CEK::ConfigOverrideError) } } @@ -282,13 +294,13 @@ fn fetch_config(searchpath: &PathBuf) -> Result { .unwrap_or_else(|| String::from("Line unknown, Column unknown")); let _ = write!(stderr(), "Config file parser error at {}", line_col); - trace_error(&ConfigErrorKind::TOMLParserError.into_error_with_cause(Box::new(e))); + trace_error(&e); None } } }) .nth(0) - .ok_or(ConfigErrorKind::NoConfigFileFound.into()) + .ok_or(CE::from_kind(ConfigErrorKind::NoConfigFileFound)) } pub trait InternalConfiguration { diff --git a/lib/core/libimagrt/src/error.rs b/lib/core/libimagrt/src/error.rs index ba2a34bc..3ecca79e 100644 --- a/lib/core/libimagrt/src/error.rs +++ b/lib/core/libimagrt/src/error.rs @@ -17,33 +17,92 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_imports!(); -use std::io::Error as IOError; - -generate_error_types!(RuntimeError, RuntimeErrorKind, - Instantiate => "Could not instantiate", - IOError => "IO Error", - IOLogFileOpenError => "IO Error: Could not open logfile", - ProcessExitFailure => "Process exited with failure", - ConfigReadError => "Error while reading the configuration", - ConfigTypeError => "Error while reading the configuration: Type Error", - GlobalLogLevelConfigMissing => "Global config 'imag.logging.level' missing", - GlobalDestinationConfigMissing => "Global config 'imag.logging.destinations' missing", - InvalidLogLevelSpec => "Invalid log level specification: Only 'trace', 'debug', 'info', 'warn', 'error' are allowed", - TomlReadError => "Error while reading in TOML document", - TemplateStringRegistrationError => "Error while registering logging template string", - ConfigMissingLoggingFormatTrace => "Missing config for logging format for trace logging", - ConfigMissingLoggingFormatDebug => "Missing config for logging format for debug logging", - ConfigMissingLoggingFormatInfo => "Missing config for logging format for info logging", - ConfigMissingLoggingFormatWarn => "Missing config for logging format for warn logging", - ConfigMissingLoggingFormatError => "Missing config for logging format for error logging" -); - -impl From for RuntimeError { - - fn from(ioe: IOError) -> RuntimeError { - RuntimeErrorKind::IOError.into_error_with_cause(Box::new(ioe)) +error_chain! { + types { + RuntimeError, RuntimeErrorKind, ResultExt, Result; } + errors { + Instantiate { + description("Could not instantiate") + display("Could not instantiate") + } + + IOError { + description("IO Error") + display("IO Error") + } + + ProcessExitFailure { + description("Process exited with failure") + display("Process exited with failure") + } + + IOLogFileOpenError { + description("IO Error: Could not open logfile") + display("IO Error: Could not open logfile") + } + + ConfigReadError { + description("Error while reading the configuration") + display("Error while reading the configuration") + } + + ConfigTypeError { + description("Error while reading the configuration: Type Error") + display("Error while reading the configuration: Type Error") + } + + GlobalLogLevelConfigMissing { + description("Global config 'imag.logging.level' missing") + display("Global config 'imag.logging.level' missing") + } + + GlobalDestinationConfigMissing { + description("Global config 'imag.logging.destinations' missing") + display("Global config 'imag.logging.destinations' missing") + } + + InvalidLogLevelSpec { + description("Invalid log level specification: Only 'trace', 'debug', 'info', 'warn', 'error' are allowed") + display("Invalid log level specification: Only 'trace', 'debug', 'info', 'warn', 'error' are allowed") + } + + TomlReadError { + description("Error while reading in TOML document") + display("Error while reading in TOML document") + } + + TemplateStringRegistrationError { + description("Error while registering logging template string") + display("Error while registering logging template string") + } + + ConfigMissingLoggingFormatTrace { + description("Missing config for logging format for trace logging") + display("Missing config for logging format for trace logging") + } + + ConfigMissingLoggingFormatDebug { + description("Missing config for logging format for debug logging") + display("Missing config for logging format for debug logging") + } + + ConfigMissingLoggingFormatInfo { + description("Missing config for logging format for info logging") + display("Missing config for logging format for info logging") + } + + ConfigMissingLoggingFormatWarn { + description("Missing config for logging format for warn logging") + display("Missing config for logging format for warn logging") + } + + ConfigMissingLoggingFormatError { + description("Missing config for logging format for error logging") + display("Missing config for logging format for error logging") + } + + } } diff --git a/lib/core/libimagrt/src/lib.rs b/lib/core/libimagrt/src/lib.rs index addce7b0..486435ed 100644 --- a/lib/core/libimagrt/src/lib.rs +++ b/lib/core/libimagrt/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -34,6 +36,7 @@ )] #[macro_use] extern crate log; +#[macro_use] extern crate error_chain; extern crate itertools; #[cfg(unix)] extern crate xdg_basedir; extern crate env_logger; @@ -47,7 +50,7 @@ extern crate toml_query; extern crate libimagstore; extern crate libimagutil; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; pub mod error; pub mod configuration; diff --git a/lib/core/libimagrt/src/logger.rs b/lib/core/libimagrt/src/logger.rs index 2dc361d8..8785e27b 100644 --- a/lib/core/libimagrt/src/logger.rs +++ b/lib/core/libimagrt/src/logger.rs @@ -23,12 +23,10 @@ use std::collections::BTreeMap; use configuration::Configuration; use error::RuntimeErrorKind as EK; -use error::RuntimeError; -use error::MapErrInto; +use error::RuntimeError as RE; +use error::ResultExt; use runtime::Runtime; -use libimagerror::into::IntoError; - use clap::ArgMatches; use log::{Log, LogLevel, LogRecord, LogMetadata}; use toml::Value; @@ -36,7 +34,7 @@ use toml_query::read::TomlValueReadExt; use handlebars::Handlebars; type ModuleName = String; -type Result = ::std::result::Result; +type Result = ::std::result::Result; enum LogDestination { Stderr, @@ -96,27 +94,27 @@ impl ImagLogger { { let fmt = try!(aggregate_global_format_trace(matches, config)); try!(handlebars.register_template_string("TRACE", fmt) // name must be uppercase - .map_err_into(EK::TemplateStringRegistrationError)); + .chain_err(|| EK::TemplateStringRegistrationError)); } { let fmt = try!(aggregate_global_format_debug(matches, config)); try!(handlebars.register_template_string("DEBUG", fmt) // name must be uppercase - .map_err_into(EK::TemplateStringRegistrationError)); + .chain_err(|| EK::TemplateStringRegistrationError)); } { let fmt = try!(aggregate_global_format_info(matches, config)); try!(handlebars.register_template_string("INFO", fmt) // name must be uppercase - .map_err_into(EK::TemplateStringRegistrationError)); + .chain_err(|| EK::TemplateStringRegistrationError)); } { let fmt = try!(aggregate_global_format_warn(matches, config)); try!(handlebars.register_template_string("WARN", fmt) // name must be uppercase - .map_err_into(EK::TemplateStringRegistrationError)); + .chain_err(|| EK::TemplateStringRegistrationError)); } { let fmt = try!(aggregate_global_format_error(matches, config)); try!(handlebars.register_template_string("ERROR", fmt) // name must be uppercase - .map_err_into(EK::TemplateStringRegistrationError)); + .chain_err(|| EK::TemplateStringRegistrationError)); } Ok(ImagLogger { @@ -194,7 +192,7 @@ fn match_log_level_str(s: &str) -> Result { "info" => Ok(LogLevel::Info), "warn" => Ok(LogLevel::Warn), "error" => Ok(LogLevel::Error), - _ => return Err(EK::InvalidLogLevelSpec.into_error()), + _ => return Err(RE::from_kind(EK::InvalidLogLevelSpec)), } } @@ -204,11 +202,11 @@ fn aggregate_global_loglevel(matches: &ArgMatches, config: Option<&Configuration match config { Some(cfg) => match cfg .read("imag.logging.level") - .map_err_into(EK::ConfigReadError) + .chain_err(|| EK::ConfigReadError) { Ok(Some(&Value::String(ref s))) => match_log_level_str(s), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Ok(None) => Err(EK::GlobalLogLevelConfigMissing.into_error()), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Ok(None) => Err(RE::from_kind(EK::GlobalLogLevelConfigMissing)), Err(e) => Err(e) }, None => { @@ -235,7 +233,7 @@ fn translate_destination(raw: &str) -> Result { .create(true) .open(other) .map(LogDestination::File) - .map_err_into(EK::IOLogFileOpenError) + .chain_err(|| EK::IOLogFileOpenError) } } } @@ -247,7 +245,7 @@ fn translate_destinations(raw: &Vec) -> Result> { acc.and_then(|mut v| { let dest = match *val { Value::String(ref s) => try!(translate_destination(s)), - _ => return Err(EK::ConfigTypeError.into_error()), + _ => return Err(RE::from_kind(EK::ConfigTypeError)), }; v.push(dest); Ok(v) @@ -262,11 +260,11 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Configura match config { Some(cfg) => match cfg .read("imag.logging.destinations") - .map_err_into(EK::ConfigReadError) + .chain_err(|| EK::ConfigReadError) { Ok(Some(&Value::Array(ref a))) => translate_destinations(a), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Ok(None) => Err(EK::GlobalDestinationConfigMissing.into_error()), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Ok(None) => Err(RE::from_kind(EK::GlobalDestinationConfigMissing)), Err(e) => Err(e) }, None => { @@ -300,16 +298,16 @@ fn aggregate_global_format( match config { Some(cfg) => match cfg .read(read_str) - .map_err_into(EK::ConfigReadError) + .chain_err(|| EK::ConfigReadError) { Ok(Some(&Value::String(ref s))) => Ok(s.clone()), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Ok(None) => Err(error_kind_if_missing.into_error()), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Ok(None) => Err(RE::from_kind(error_kind_if_missing)), Err(e) => Err(e) }, None => match matches.value_of(cli_match_name).map(String::from) { Some(s) => Ok(s), - None => Err(error_kind_if_missing.into_error()) + None => Err(RE::from_kind(error_kind_if_missing)) } } } @@ -370,7 +368,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Configuratio match config { Some(cfg) => match cfg .read("imag.logging.modules") - .map_err_into(EK::ConfigReadError) + .chain_err(|| EK::ConfigReadError) { Ok(Some(&Value::Table(ref t))) => { // translate the module settings from the table `t` @@ -380,22 +378,22 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Configuratio let destinations = try!(match v.read("destinations") { Ok(Some(&Value::Array(ref a))) => translate_destinations(a).map(Some), Ok(None) => Ok(None), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Err(e) => Err(e).map_err_into(EK::TomlReadError), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Err(e) => Err(e).chain_err(|| EK::TomlReadError), }); let level = try!(match v.read("level") { Ok(Some(&Value::String(ref s))) => match_log_level_str(s).map(Some), Ok(None) => Ok(None), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Err(e) => Err(e).map_err_into(EK::TomlReadError), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Err(e) => Err(e).chain_err(|| EK::TomlReadError), }); let enabled = try!(match v.read("enabled") { Ok(Some(&Value::Boolean(b))) => Ok(b), Ok(None) => Ok(false), - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), - Err(e) => Err(e).map_err_into(EK::TomlReadError), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), + Err(e) => Err(e).chain_err(|| EK::TomlReadError), }); let module_settings = ModuleSettings { @@ -410,7 +408,7 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Configuratio Ok(settings) }, - Ok(Some(_)) => Err(EK::ConfigTypeError.into_error()), + Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError)), Ok(None) => { // No modules configured. This is okay! Ok(BTreeMap::new()) diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index 43c12904..ffb27b51 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -30,7 +30,7 @@ use log; use configuration::{Configuration, InternalConfiguration}; use error::RuntimeError; use error::RuntimeErrorKind; -use error::MapErrInto; +use error::ResultExt; use logger::ImagLogger; use libimagerror::trace::*; @@ -60,9 +60,8 @@ impl<'a> Runtime<'a> { where C: Clone + CliSpec<'a> + InternalConfiguration { use libimagerror::trace::trace_error; - use libimagerror::into::IntoError; - use configuration::error::ConfigErrorKind; + use configuration::ConfigErrorKind; let matches = cli_app.clone().matches(); @@ -74,8 +73,8 @@ impl<'a> Runtime<'a> { debug!("Config path = {:?}", configpath); let config = match Configuration::new(&configpath) { - Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound { - return Err(RuntimeErrorKind::Instantiate.into_error_with_cause(Box::new(e))); + Err(e) => if !is_match!(e.kind(), &ConfigErrorKind::NoConfigFileFound) { + return Err(e).chain_err(|| RuntimeErrorKind::Instantiate); } else { println!("No config file found."); println!("Continuing without configuration file"); @@ -165,7 +164,7 @@ impl<'a> Runtime<'a> { store: store, } }) - .map_err_into(RuntimeErrorKind::Instantiate) + .chain_err(|| RuntimeErrorKind::Instantiate) } /// @@ -485,11 +484,11 @@ impl<'a> Runtime<'a> { let mapper = JsonMapper::new(); StdIoFileAbstraction::new(&mut input, output, mapper) - .map_err_into(RuntimeErrorKind::Instantiate) + .chain_err(|| RuntimeErrorKind::Instantiate) .and_then(|backend| { self.store .reset_backend(Box::new(backend)) - .map_err_into(RuntimeErrorKind::Instantiate) + .chain_err(|| RuntimeErrorKind::Instantiate) }) } @@ -504,11 +503,11 @@ impl<'a> Runtime<'a> { let mapper = JsonMapper::new(); StdoutFileAbstraction::new(output, mapper) - .map_err_into(RuntimeErrorKind::Instantiate) + .chain_err(|| RuntimeErrorKind::Instantiate) .and_then(|backend| { self.store .reset_backend(Box::new(backend)) - .map_err_into(RuntimeErrorKind::Instantiate) + .chain_err(|| RuntimeErrorKind::Instantiate) }) } diff --git a/lib/core/libimagstore/Cargo.toml b/lib/core/libimagstore/Cargo.toml index 589d2bf1..94af976e 100644 --- a/lib/core/libimagstore/Cargo.toml +++ b/lib/core/libimagstore/Cargo.toml @@ -26,6 +26,7 @@ is-match = "0.1" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" +error-chain = "0.10" libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } libimagutil = { version = "0.4.0", path = "../../../lib/etc/libimagutil" } diff --git a/lib/core/libimagstore/src/configuration.rs b/lib/core/libimagstore/src/configuration.rs index 0dfc0490..dc60311d 100644 --- a/lib/core/libimagstore/src/configuration.rs +++ b/lib/core/libimagstore/src/configuration.rs @@ -19,9 +19,8 @@ use toml::Value; -use libimagerror::into::IntoError; - use store::Result; +use error::StoreError as SE; /// Check whether the configuration is valid for the store pub fn config_is_valid(config: &Option) -> Result<()> { @@ -35,7 +34,7 @@ pub fn config_is_valid(config: &Option) -> Result<()> { Some(Value::Table(_)) => Ok(()), _ => { warn!("Store config is no table"); - Err(SEK::ConfigTypeError.into_error()) + Err(SE::from_kind(SEK::ConfigTypeError)) }, } } diff --git a/lib/core/libimagstore/src/error.rs b/lib/core/libimagstore/src/error.rs index 00e47681..2f172e34 100644 --- a/lib/core/libimagstore/src/error.rs +++ b/lib/core/libimagstore/src/error.rs @@ -17,99 +17,283 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_imports!(); -use std::convert::From; - -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)] -pub struct CustomErrorData {} - -impl Display for CustomErrorData { - fn fmt(&self, _: &mut Formatter) -> Result<(), FmtError> { - Ok(()) // Do nothing here, we don't need to print smth +error_chain! { + types { + StoreError, StoreErrorKind, ResultExt, Result; } -} -generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData, - ConfigurationError => "Store Configuration Error", - ConfigTypeError => "Store configuration type error", - ConfigKeyMissingError => "Configuration Key missing", + foreign_links { + Io(::std::io::Error); + TomlDeserError(::toml::de::Error); + } - VersionError => "Incompatible store versions detected", + errors { - CreateStoreDirDenied => "Creating store directory implicitely denied", - FileError => "File Error", - IoError => "IO Error", - IdLocked => "ID locked", - IdNotFound => "ID not found", - OutOfMemory => "Out of Memory", - FileNotFound => "File corresponding to ID not found", - FileNotCreated => "File corresponding to ID could not be created", - FileNotWritten => "File corresponding to ID could not be written to", - FileNotSeeked => "File corresponding to ID could not be seeked", - FileNotRemoved => "File corresponding to ID could not be removed", - FileNotRenamed => "File corresponding to ID could not be renamed", - FileNotCopied => "File could not be copied", - DirNotCreated => "Directory/Directories could not be created", - StorePathExists => "Store path exists", - StorePathCreate => "Store path create", - LockError => "Error locking datastructure", - LockPoisoned => "The internal Store Lock has been poisoned", - EntryAlreadyBorrowed => "Entry is already borrowed", - EntryAlreadyExists => "Entry already exists", - MalformedEntry => "Entry has invalid formatting, missing header", - HeaderPathSyntaxError => "Syntax error in accessor string", - HeaderPathTypeFailure => "Header has wrong type for path", - HeaderKeyNotFound => "Header Key not found", - HeaderTypeFailure => "Header type is wrong", - StorePathLacksVersion => "The supplied store path has no version part", - GlobError => "glob() error", - EncodingError => "Encoding error", - StorePathError => "Store Path error", - EntryRenameError => "Entry rename error", - StoreIdHandlingError => "StoreId handling error", - StoreIdLocalPartAbsoluteError => "StoreId 'id' part is absolute (starts with '/') which is not allowed", - StoreIdBuildFromFullPathError => "Building StoreId from full file path failed", - StoreIdHasNoBaseError => "StoreId has no 'base' part", + ConfigurationError { + description("Store Configuration Error") + display("Store Configuration Error") + } - CreateCallError => "Error when calling create()", - RetrieveCallError => "Error when calling retrieve()", - GetCallError => "Error when calling get()", - GetAllVersionsCallError => "Error when calling get_all_versions()", - RetrieveForModuleCallError => "Error when calling retrieve_for_module()", - UpdateCallError => "Error when calling update()", - RetrieveCopyCallError => "Error when calling retrieve_copy()", - DeleteCallError => "Error when calling delete()", - MoveCallError => "Error when calling move()", - MoveByIdCallError => "Error when calling move_by_id()" -); + ConfigTypeError { + description("Store configuration type error") + display("Store configuration type error") + } -generate_result_helper!(StoreError, StoreErrorKind); -generate_option_helper!(StoreError, StoreErrorKind); + ConfigKeyMissingError { + description("Configuration Key missing") + display("Configuration Key missing") + } -generate_custom_error_types!(ParserError, ParserErrorKind, CustomErrorData, - TOMLParserErrors => "Several TOML-Parser-Errors", - MissingMainSection => "Missing main section", - MissingVersionInfo => "Missing version information in main section", - NonTableInBaseTable => "A non-table was found in the base table", - HeaderInconsistency => "The header is inconsistent" -); + VersionError { + description("Incompatible store versions detected") + display("Incompatible store versions detected") + } -impl From for StoreError { - fn from(ps: ParserError) -> StoreError { - StoreError { - err_type: StoreErrorKind::MalformedEntry, - cause: Some(Box::new(ps)), - custom_data: None, - } - } -} - -impl From<::std::io::Error> for StoreError { - fn from(ps: ::std::io::Error) -> StoreError { - StoreError { - err_type: StoreErrorKind::IoError, - cause: Some(Box::new(ps)), - custom_data: None, + CreateStoreDirDenied { + description("Creating store directory implicitely denied") + display("Creating store directory implicitely denied") + } + + FileError { + description("File Error") + display("File Error") + } + + IoError { + description("IO Error") + display("IO Error") + } + + IdLocked { + description("ID locked") + display("ID locked") + } + + IdNotFound { + description("ID not found") + display("ID not found") + } + + OutOfMemory { + description("Out of Memory") + display("Out of Memory") + } + + FileNotFound { + description("File corresponding to ID not found") + display("File corresponding to ID not found") + } + + FileNotCreated { + description("File corresponding to ID could not be created") + display("File corresponding to ID could not be created") + } + + FileNotWritten { + description("File corresponding to ID could not be written to") + display("File corresponding to ID could not be written to") + } + + FileNotSeeked { + description("File corresponding to ID could not be seeked") + display("File corresponding to ID could not be seeked") + } + + FileNotRemoved { + description("File corresponding to ID could not be removed") + display("File corresponding to ID could not be removed") + } + + FileNotRenamed { + description("File corresponding to ID could not be renamed") + display("File corresponding to ID could not be renamed") + } + + FileNotCopied { + description("File could not be copied") + display("File could not be copied") + } + + DirNotCreated { + description("Directory/Directories could not be created") + display("Directory/Directories could not be created") + } + + StorePathExists { + description("Store path exists") + display("Store path exists") + } + + StorePathCreate { + description("Store path create") + display("Store path create") + } + + LockError { + description("Error locking datastructure") + display("Error locking datastructure") + } + + LockPoisoned { + description("The internal Store Lock has been poisoned") + display("The internal Store Lock has been poisoned") + } + + EntryAlreadyBorrowed { + description("Entry is already borrowed") + display("Entry is already borrowed") + } + + EntryAlreadyExists { + description("Entry already exists") + display("Entry already exists") + } + + MalformedEntry { + description("Entry has invalid formatting, missing header") + display("Entry has invalid formatting, missing header") + } + + HeaderPathSyntaxError { + description("Syntax error in accessor string") + display("Syntax error in accessor string") + } + + HeaderPathTypeFailure { + description("Header has wrong type for path") + display("Header has wrong type for path") + } + + HeaderKeyNotFound { + description("Header Key not found") + display("Header Key not found") + } + + HeaderTypeFailure { + description("Header type is wrong") + display("Header type is wrong") + } + + StorePathLacksVersion { + description("The supplied store path has no version part") + display("The supplied store path has no version part") + } + + GlobError { + description("glob() error") + display("glob() error") + } + + EncodingError { + description("Encoding error") + display("Encoding error") + } + + StorePathError { + description("Store Path error") + display("Store Path error") + } + + EntryRenameError { + description("Entry rename error") + display("Entry rename error") + } + + StoreIdHandlingError { + description("StoreId handling error") + display("StoreId handling error") + } + + StoreIdLocalPartAbsoluteError { + description("StoreId 'id' part is absolute (starts with '/') which is not allowed") + display("StoreId 'id' part is absolute (starts with '/') which is not allowed") + } + + StoreIdBuildFromFullPathError { + description("Building StoreId from full file path failed") + display("Building StoreId from full file path failed") + } + + StoreIdHasNoBaseError { + description("StoreId has no 'base' part") + display("StoreId has no 'base' part") + } + + CreateCallError { + description("Error when calling create()") + display("Error when calling create()") + } + + RetrieveCallError { + description("Error when calling retrieve()") + display("Error when calling retrieve()") + } + + GetCallError { + description("Error when calling get()") + display("Error when calling get()") + } + + GetAllVersionsCallError { + description("Error when calling get_all_versions()") + display("Error when calling get_all_versions()") + } + + RetrieveForModuleCallError { + description("Error when calling retrieve_for_module()") + display("Error when calling retrieve_for_module()") + } + + UpdateCallError { + description("Error when calling update()") + display("Error when calling update()") + } + + RetrieveCopyCallError { + description("Error when calling retrieve_copy()") + display("Error when calling retrieve_copy()") + } + + DeleteCallError { + description("Error when calling delete()") + display("Error when calling delete()") + } + + MoveCallError { + description("Error when calling move()") + display("Error when calling move()") + } + + MoveByIdCallError { + description("Error when calling move_by_id()") + display("Error when calling move_by_id()") + } + + // Parser-related errors + + TOMLParserErrors { + description("Several TOML-Parser-Errors") + display("Several TOML-Parser-Errors") + } + + MissingMainSection { + description("Missing main section") + display("Missing main section") + } + + MissingVersionInfo { + description("Missing version information in main section") + display("Missing version information in main section") + } + + NonTableInBaseTable { + description("A non-table was found in the base table") + display("A non-table was found in the base table") + } + + HeaderInconsistency { + description("The header is inconsistent") + display("The header is inconsistent") } } } diff --git a/lib/core/libimagstore/src/file_abstraction/fs.rs b/lib/core/libimagstore/src/file_abstraction/fs.rs index 9fd14456..bb47f275 100644 --- a/lib/core/libimagstore/src/file_abstraction/fs.rs +++ b/lib/core/libimagstore/src/file_abstraction/fs.rs @@ -21,7 +21,8 @@ use std::fs::{File, OpenOptions, create_dir_all, remove_file, copy, rename}; use std::io::{Seek, SeekFrom, Read}; use std::path::{Path, PathBuf}; -use error::{MapErrInto, StoreError as SE, StoreErrorKind as SEK}; +use error::{StoreError as SE, StoreErrorKind as SEK}; +use error::ResultExt; use super::FileAbstraction; use super::FileAbstractionInstance; @@ -47,22 +48,22 @@ impl FileAbstractionInstance for FSFileAbstractionInstance { // We seek to the beginning of the file since we expect each // access to the file to be in a different context try!(f.seek(SeekFrom::Start(0)) - .map_err_into(SEK::FileNotSeeked)); + .chain_err(|| SEK::FileNotSeeked)); let mut s = String::new(); f.read_to_string(&mut s) - .map_err_into(SEK::IoError) + .chain_err(|| SEK::IoError) .map(|_| s) .and_then(|s| Entry::from_str(id, &s)) }, FSFileAbstractionInstance::Absent(ref p) => - (try!(open_file(p).map_err_into(SEK::FileNotFound)), p.clone()), + (try!(open_file(p).chain_err(|| SEK::FileNotFound)), p.clone()), }; *self = FSFileAbstractionInstance::File(file, path); if let FSFileAbstractionInstance::File(ref mut f, _) = *self { let mut s = String::new(); f.read_to_string(&mut s) - .map_err_into(SEK::IoError) + .chain_err(|| SEK::IoError) .map(|_| s) .and_then(|s| Entry::from_str(id, &s)) } else { @@ -83,18 +84,18 @@ impl FileAbstractionInstance for FSFileAbstractionInstance { // We seek to the beginning of the file since we expect each // access to the file to be in a different context try!(f.seek(SeekFrom::Start(0)) - .map_err_into(SEK::FileNotCreated)); + .chain_err(|| SEK::FileNotCreated)); - try!(f.set_len(buf.len() as u64).map_err_into(SEK::FileNotWritten)); + try!(f.set_len(buf.len() as u64).chain_err(|| SEK::FileNotWritten)); - f.write_all(&buf).map_err_into(SEK::FileNotWritten) + f.write_all(&buf).chain_err(|| SEK::FileNotWritten) }, FSFileAbstractionInstance::Absent(ref p) => - (try!(create_file(p).map_err_into(SEK::FileNotCreated)), p.clone()), + (try!(create_file(p).chain_err(|| SEK::FileNotCreated)), p.clone()), }; *self = FSFileAbstractionInstance::File(file, path); if let FSFileAbstractionInstance::File(ref mut f, _) = *self { - return f.write_all(&buf).map_err_into(SEK::FileNotWritten); + return f.write_all(&buf).chain_err(|| SEK::FileNotWritten); } unreachable!(); } @@ -117,19 +118,19 @@ impl FSFileAbstraction { impl FileAbstraction for FSFileAbstraction { fn remove_file(&self, path: &PathBuf) -> Result<(), SE> { - remove_file(path).map_err_into(SEK::FileNotRemoved) + remove_file(path).chain_err(|| SEK::FileNotRemoved) } fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { - copy(from, to).map_err_into(SEK::FileNotCopied).map(|_| ()) + copy(from, to).chain_err(|| SEK::FileNotCopied).map(|_| ()) } fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { - rename(from, to).map_err_into(SEK::FileNotRenamed) + rename(from, to).chain_err(|| SEK::FileNotRenamed) } fn create_dir_all(&self, path: &PathBuf) -> Result<(), SE> { - create_dir_all(path).map_err_into(SEK::DirNotCreated) + create_dir_all(path).chain_err(|| SEK::DirNotCreated) } fn new_instance(&self, p: PathBuf) -> Box { diff --git a/lib/core/libimagstore/src/file_abstraction/inmemory.rs b/lib/core/libimagstore/src/file_abstraction/inmemory.rs index 4f318fe1..42ebf319 100644 --- a/lib/core/libimagstore/src/file_abstraction/inmemory.rs +++ b/lib/core/libimagstore/src/file_abstraction/inmemory.rs @@ -17,17 +17,16 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use std::path::PathBuf; + use error::StoreError as SE; use error::StoreErrorKind as SEK; -use std::path::PathBuf; use std::collections::HashMap; use std::sync::Mutex; use std::cell::RefCell; use std::sync::Arc; use std::ops::Deref; -use libimagerror::into::IntoError; - use super::FileAbstraction; use super::FileAbstractionInstance; use super::Drain; @@ -64,16 +63,15 @@ impl FileAbstractionInstance for InMemoryFileAbstractionInstance { fn get_file_content(&mut self, _: StoreId) -> Result { debug!("Getting lazy file: {:?}", self); - match self.fs_abstraction.lock() { - Ok(mut mtx) => { + self.fs_abstraction + .lock() + .map_err(|_| SE::from_kind(SEK::LockError)) + .and_then(|mut mtx| { mtx.get_mut() .get(&self.absent_path) .cloned() - .ok_or(SEK::FileNotFound.into_error()) - } - - Err(_) => Err(SEK::LockError.into_error()) - } + .ok_or(SE::from_kind(SEK::FileNotFound)) + }) } fn write_file_content(&mut self, buf: &Entry) -> Result<(), SE> { @@ -108,7 +106,7 @@ impl InMemoryFileAbstraction { fn backend_cloned<'a>(&'a self) -> Result, SE> { self.virtual_filesystem .lock() - .map_err(|_| SEK::LockError.into_error()) + .map_err(|_| SE::from_kind(SEK::LockError)) .map(|mtx| mtx.deref().borrow().clone()) } @@ -124,7 +122,7 @@ impl FileAbstraction for InMemoryFileAbstraction { .get_mut() .remove(path) .map(|_| ()) - .ok_or(SEK::FileNotFound.into_error()) + .ok_or(SE::from_kind(SEK::FileNotFound)) } fn copy(&self, from: &PathBuf, to: &PathBuf) -> Result<(), SE> { @@ -132,7 +130,7 @@ impl FileAbstraction for InMemoryFileAbstraction { let mut mtx = self.backend().lock().expect("Locking Mutex failed"); let backend = mtx.get_mut(); - let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error())); + let a = try!(backend.get(from).cloned().ok_or(SE::from_kind(SEK::FileNotFound))); backend.insert(to.clone(), a); debug!("Copying: {:?} -> {:?} worked", from, to); Ok(()) @@ -143,7 +141,7 @@ impl FileAbstraction for InMemoryFileAbstraction { let mut mtx = self.backend().lock().expect("Locking Mutex failed"); let backend = mtx.get_mut(); - let a = try!(backend.get(from).cloned().ok_or(SEK::FileNotFound.into_error())); + let a = try!(backend.get(from).cloned().ok_or(SE::from_kind(SEK::FileNotFound))); backend.insert(to.clone(), a); debug!("Renaming: {:?} -> {:?} worked", from, to); Ok(()) @@ -163,7 +161,7 @@ impl FileAbstraction for InMemoryFileAbstraction { fn fill<'a>(&'a mut self, mut d: Drain) -> Result<(), SE> { debug!("Draining into : {:?}", self); - let mut mtx = try!(self.backend().lock().map_err(|_| SEK::LockError.into_error())); + let mut mtx = try!(self.backend().lock().map_err(|_| SEK::LockError)); let backend = mtx.get_mut(); for (path, element) in d.iter() { diff --git a/lib/core/libimagstore/src/file_abstraction/stdio/mapper/json.rs b/lib/core/libimagstore/src/file_abstraction/stdio/mapper/json.rs index 0b66f91c..4af44a31 100644 --- a/lib/core/libimagstore/src/file_abstraction/stdio/mapper/json.rs +++ b/lib/core/libimagstore/src/file_abstraction/stdio/mapper/json.rs @@ -25,14 +25,13 @@ use serde_json; use toml; use error::StoreErrorKind as SEK; -use error::MapErrInto; +use error::StoreError as SE; +use error::ResultExt; use super::Mapper; use store::Result; use store::Entry; use storeid::StoreId; -use libimagerror::into::IntoError; - #[derive(Debug, Deserialize, Serialize)] struct BackendEntry { header: serde_json::Value, @@ -43,7 +42,7 @@ impl BackendEntry { fn to_string(self) -> Result { toml::to_string(&self.header) - .map_err_into(SEK::IoError) + .chain_err(|| SEK::IoError) .map(|hdr| { format!("---\n{header}---\n{content}", header = hdr, @@ -74,16 +73,16 @@ impl Mapper for JsonMapper { let mut document = { debug!("Reading Document"); let mut s = String::new(); - try!(r.read_to_string(&mut s).map_err_into(SEK::IoError)); + try!(r.read_to_string(&mut s).chain_err(|| SEK::IoError)); debug!("Document = {:?}", s); debug!("Parsing Document"); - let doc : Document = try!(serde_json::from_str(&s).map_err_into(SEK::IoError)); + let doc : Document = try!(serde_json::from_str(&s).chain_err(|| SEK::IoError)); debug!("Document = {:?}", doc); doc }; let _ = try!(::semver::Version::parse(&document.version) - .map_err_into(SEK::VersionError) + .chain_err(|| SEK::VersionError) .and_then(|doc_vers| { // safe because cargo does not compile if crate version is not valid let crate_version = ::semver::Version::parse(version!()).unwrap(); @@ -93,7 +92,7 @@ impl Mapper for JsonMapper { crate_vers = crate_version); if doc_vers > crate_version { - Err(SEK::VersionError.into_error()) + Err(SE::from_kind(SEK::VersionError)) } else { Ok(()) } @@ -150,9 +149,9 @@ impl Mapper for JsonMapper { }; serde_json::to_string(&doc) - .map_err_into(SEK::IoError) - .and_then(|json| out.write(&json.into_bytes()).map_err_into(SEK::IoError)) - .and_then(|_| out.flush().map_err_into(SEK::IoError)) + .chain_err(|| SEK::IoError) + .and_then(|json| out.write(&json.into_bytes()).chain_err(|| SEK::IoError)) + .and_then(|_| out.flush().chain_err(|| SEK::IoError)) .map(|_| ()) } } diff --git a/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs b/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs index e2ac5ec4..4ed0b067 100644 --- a/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs +++ b/lib/core/libimagstore/src/file_abstraction/stdio/mod.rs @@ -29,8 +29,6 @@ use std::fmt::Debug; use std::fmt::Error as FmtError; use std::fmt::Formatter; -use libimagerror::into::IntoError; - use error::StoreErrorKind as SEK; use error::StoreError as SE; use super::FileAbstraction; @@ -57,11 +55,11 @@ impl StdIoFileAbstraction pub fn new(in_stream: &mut R, out_stream: Rc>, mapper: M) -> Result, SE> { StdoutFileAbstraction::new(out_stream, mapper) .and_then(|out| { - let fill_res = match out.backend().lock() { - Err(_) => Err(SEK::LockError.into_error()), - Ok(mut mtx) => out.mapper().read_to_fs(in_stream, mtx.get_mut()) - }; - let _ = try!(fill_res); + let _ = try!(out + .backend() + .lock() + .map_err(|_| SE::from_kind(SEK::LockError)) + .map(|mut mtx| out.mapper().read_to_fs(in_stream, mtx.get_mut()))); Ok(StdIoFileAbstraction(out)) }) diff --git a/lib/core/libimagstore/src/file_abstraction/stdio/out.rs b/lib/core/libimagstore/src/file_abstraction/stdio/out.rs index 37ccab62..950947f2 100644 --- a/lib/core/libimagstore/src/file_abstraction/stdio/out.rs +++ b/lib/core/libimagstore/src/file_abstraction/stdio/out.rs @@ -31,7 +31,6 @@ use std::sync::Arc; use std::sync::Mutex; use std::ops::Deref; -use libimagerror::into::IntoError; use libimagerror::trace::*; use error::StoreErrorKind as SEK; @@ -74,7 +73,7 @@ impl StdoutFileAbstraction self.mem .backend() .lock() - .map_err(|_| SEK::LockError.into_error()) + .map_err(|_| SE::from_kind(SEK::LockError)) .map(|mtx| mtx.deref().borrow().clone()) } @@ -101,7 +100,7 @@ impl Drop for StdoutFileAbstraction use std::ops::DerefMut; let fill_res = match self.mem.backend().lock() { - Err(_) => Err(SEK::LockError.into_error()), + Err(_) => Err(SE::from_kind(SEK::LockError)), Ok(mut mtx) => { self.mapper.fs_to_write(mtx.get_mut(), self.out.borrow_mut().deref_mut()) }, @@ -142,7 +141,7 @@ impl FileAbstraction for StdoutFileAbstraction { fn fill(&mut self, mut d: Drain) -> Result<(), SE> { debug!("Draining into : {:?}", self); - let mut mtx = try!(self.backend().lock().map_err(|_| SEK::IoError.into_error())); + let mut mtx = try!(self.backend().lock().map_err(|_| SE::from_kind(SEK::IoError))); let backend = mtx.get_mut(); for (path, element) in d.iter() { diff --git a/lib/core/libimagstore/src/lib.rs b/lib/core/libimagstore/src/lib.rs index 96147ef2..891eb841 100644 --- a/lib/core/libimagstore/src/lib.rs +++ b/lib/core/libimagstore/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -45,8 +47,9 @@ extern crate walkdir; #[macro_use] extern crate is_match; extern crate serde_json; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate error_chain; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagutil; #[macro_use] mod util; diff --git a/lib/core/libimagstore/src/store.rs b/lib/core/libimagstore/src/store.rs index ba66641a..fed4ca0b 100644 --- a/lib/core/libimagstore/src/store.rs +++ b/lib/core/libimagstore/src/store.rs @@ -38,8 +38,8 @@ use glob::glob; use walkdir::WalkDir; use walkdir::Iter as WalkDirIter; -use error::{StoreError as SE, StoreErrorKind as SEK, ParserError, ParserErrorKind}; -use error::MapErrInto; +use error::{StoreError as SE, StoreErrorKind as SEK}; +use error::ResultExt; use storeid::{IntoStoreId, StoreId, StoreIdIterator}; use file_abstraction::FileAbstractionInstance; @@ -48,7 +48,6 @@ pub use file_abstraction::FileAbstraction; pub use file_abstraction::FSFileAbstraction; pub use file_abstraction::InMemoryFileAbstraction; -use libimagerror::into::IntoError; use libimagerror::trace::trace_error; use libimagutil::debug_result::*; @@ -147,8 +146,8 @@ impl StoreEntry { #[cfg(feature = "fs-lock")] { try!(open_file(pb.clone()) - .and_then(|f| f.lock_exclusive().map_err_into(SEK::FileError)) - .map_err_into(SEK::IoError)); + .and_then(|f| f.lock_exclusive().chain_err(|| SEK::FileError)) + .chain_err(|| SEK::IoError)); } Ok(StoreEntry { @@ -168,13 +167,13 @@ impl StoreEntry { if !self.is_borrowed() { self.file .get_file_content(self.id.clone()) - .or_else(|err| if err.err_type() == SEK::FileNotFound { + .or_else(|err| if is_match!(err.kind(), &SEK::FileNotFound) { Ok(Entry::new(self.id.clone())) } else { Err(err) }) } else { - Err(SE::new(SEK::EntryAlreadyBorrowed, None)) + Err(SE::from_kind(SEK::EntryAlreadyBorrowed)) } } @@ -182,7 +181,7 @@ impl StoreEntry { if self.is_borrowed() { assert_eq!(self.id, entry.location); self.file.write_file_content(entry) - .map_err_into(SEK::FileError) + .chain_err(|| SEK::FileError) .map(|_| ()) } else { Ok(()) @@ -195,9 +194,9 @@ impl Drop for StoreEntry { fn drop(self) { self.get_entry() - .and_then(|entry| open_file(entry.get_location().clone()).map_err_into(SEK::IoError)) - .and_then(|f| f.unlock().map_err_into(SEK::FileError)) - .map_err_into(SEK::IoError) + .and_then(|entry| open_file(entry.get_location().clone()).chain_err(|| SEK::IoError)) + .and_then(|f| f.unlock().chain_err(|| SEK::FileError)) + .chain_err(|| SEK::IoError) } } @@ -266,7 +265,7 @@ impl Store { use configuration::*; debug!("Validating Store configuration"); - let _ = try!(config_is_valid(&store_config).map_err_into(SEK::ConfigurationError)); + let _ = try!(config_is_valid(&store_config).chain_err(|| SEK::ConfigurationError)); debug!("Building new Store object"); if !location.exists() { @@ -274,17 +273,17 @@ impl Store { warn!("Implicitely creating store directory is denied"); warn!(" -> Either because configuration does not allow it"); warn!(" -> or because there is no configuration"); - return Err(SEK::CreateStoreDirDenied.into_error()) - .map_err_into(SEK::FileError) - .map_err_into(SEK::IoError); + return Err(SE::from_kind(SEK::CreateStoreDirDenied)) + .chain_err(|| SEK::FileError) + .chain_err(|| SEK::IoError); } try!(backend.create_dir_all(&location) - .map_err_into(SEK::StorePathCreate) + .chain_err(|| SEK::StorePathCreate) .map_dbg_err_str("Failed")); } else if location.is_file() { debug!("Store path exists as file"); - return Err(SEK::StorePathExists.into_error()); + return Err(SE::from_kind(SEK::StorePathExists)); } let store = Store { @@ -408,13 +407,13 @@ impl Store { { let mut hsmap = match self.entries.write() { - Err(_) => return Err(SEK::LockPoisoned.into_error()).map_err_into(SEK::CreateCallError), + Err(_) => return Err(SE::from_kind(SEK::LockPoisoned)).chain_err(|| SEK::CreateCallError), Ok(s) => s, }; if hsmap.contains_key(&id) { debug!("Cannot create, internal cache already contains: '{}'", id); - return Err(SEK::EntryAlreadyExists.into_error()).map_err_into(SEK::CreateCallError); + return Err(SE::from_kind(SEK::EntryAlreadyExists)).chain_err(|| SEK::CreateCallError); } hsmap.insert(id.clone(), { debug!("Creating: '{}'", id); @@ -449,7 +448,7 @@ impl Store { let entry = try!({ self.entries .write() - .map_err(|_| SE::new(SEK::LockPoisoned, None)) + .map_err(|_| SE::from_kind(SEK::LockPoisoned)) .and_then(|mut es| { let new_se = try!(StoreEntry::new(id.clone(), &self.backend)); let se = es.entry(id.clone()).or_insert(new_se); @@ -457,7 +456,7 @@ impl Store { se.status = StoreEntryStatus::Borrowed; entry }) - .map_err_into(SEK::RetrieveCallError) + .chain_err(|| SEK::RetrieveCallError) }); debug!("Constructing FileLockEntry: '{}'", id); @@ -482,8 +481,8 @@ impl Store { let exists = try!(id.exists()) || try!(self.entries .read() .map(|map| map.contains_key(&id)) - .map_err(|_| SE::new(SEK::LockPoisoned, None)) - .map_err_into(SEK::GetCallError) + .map_err(|_| SE::from_kind(SEK::LockPoisoned)) + .chain_err(|| SEK::GetCallError) ); if !exists { @@ -491,7 +490,7 @@ impl Store { return Ok(None); } - self.retrieve(id).map(Some).map_err_into(SEK::GetCallError) + self.retrieve(id).map(Some).chain_err(|| SEK::GetCallError) } /// Iterate over all StoreIds for one module name @@ -512,15 +511,15 @@ impl Store { debug!("Retrieving for module: '{}'", mod_name); path.to_str() - .ok_or(SE::new(SEK::EncodingError, None)) + .ok_or(SE::from_kind(SEK::EncodingError)) .and_then(|path| { let path = [ path, "/**/*" ].join(""); debug!("glob()ing with '{}'", path); - glob(&path[..]).map_err_into(SEK::GlobError) + glob(&path[..]).chain_err(|| SEK::GlobError) }) .map(|paths| GlobStoreIdIterator::new(paths, self.path().clone()).into()) - .map_err_into(SEK::GlobError) - .map_err_into(SEK::RetrieveForModuleCallError) + .chain_err(|| SEK::GlobError) + .chain_err(|| SEK::RetrieveForModuleCallError) } /// Walk the store tree for the module @@ -538,7 +537,7 @@ impl Store { /// pub fn update<'a>(&'a self, entry: &mut FileLockEntry<'a>) -> Result<()> { debug!("Updating FileLockEntry at '{}'", entry.get_location()); - self._update(entry, false).map_err_into(SEK::UpdateCallError) + self._update(entry, false).chain_err(|| SEK::UpdateCallError) } /// Internal method to write to the filesystem store. @@ -560,11 +559,11 @@ impl Store { /// fn _update<'a>(&'a self, entry: &mut FileLockEntry<'a>, modify_presence: bool) -> Result<()> { let mut hsmap = match self.entries.write() { - Err(_) => return Err(SE::new(SEK::LockPoisoned, None)), + Err(_) => return Err(SE::from_kind(SEK::LockPoisoned)), Ok(e) => e, }; - let se = try!(hsmap.get_mut(&entry.location).ok_or(SE::new(SEK::IdNotFound, None))); + let se = try!(hsmap.get_mut(&entry.location).ok_or(SE::from_kind(SEK::IdNotFound))); assert!(se.is_borrowed(), "Tried to update a non borrowed entry."); @@ -597,15 +596,15 @@ impl Store { debug!("Retrieving copy of '{}'", id); let entries = match self.entries.write() { Err(_) => { - return Err(SE::new(SEK::LockPoisoned, None)) - .map_err_into(SEK::RetrieveCopyCallError); + return Err(SE::from_kind(SEK::LockPoisoned)) + .chain_err(|| SEK::RetrieveCopyCallError); }, Ok(e) => e, }; // if the entry is currently modified by the user, we cannot drop it if entries.get(&id).map(|e| e.is_borrowed()).unwrap_or(false) { - return Err(SE::new(SEK::IdLocked, None)).map_err_into(SEK::RetrieveCopyCallError); + return Err(SE::from_kind(SEK::IdLocked)).chain_err(|| SEK::RetrieveCopyCallError); } try!(StoreEntry::new(id, &self.backend)).get_entry() @@ -629,18 +628,18 @@ impl Store { { let mut entries = match self.entries.write() { - Err(_) => return Err(SE::new(SEK::LockPoisoned, None)) - .map_err_into(SEK::DeleteCallError), + Err(_) => return Err(SE::from_kind(SEK::LockPoisoned)) + .chain_err(|| SEK::DeleteCallError), Ok(e) => e, }; // if the entry is currently modified by the user, we cannot drop it match entries.get(&id) { None => { - return Err(SEK::FileNotFound.into_error()).map_err_into(SEK::DeleteCallError) + return Err(SE::from_kind(SEK::FileNotFound)).chain_err(|| SEK::DeleteCallError) }, Some(e) => if e.is_borrowed() { - return Err(SE::new(SEK::IdLocked, None)).map_err_into(SEK::DeleteCallError) + return Err(SE::from_kind(SEK::IdLocked)).chain_err(|| SEK::DeleteCallError) } } @@ -648,8 +647,9 @@ impl Store { entries.remove(&id); let pb = try!(id.clone().with_base(self.path().clone()).into_pathbuf()); if let Err(e) = self.backend.remove_file(&pb) { - return Err(SEK::FileError.into_error_with_cause(Box::new(e))) - .map_err_into(SEK::DeleteCallError); + return Err(e) + .chain_err(|| SEK::FileError) + .chain_err(|| SEK::DeleteCallError); } } @@ -677,12 +677,12 @@ impl Store { let hsmap = try!( self.entries .write() - .map_err(|_| SEK::LockPoisoned.into_error()) - .map_err_into(SEK::MoveCallError) + .map_err(|_| SE::from_kind(SEK::LockPoisoned)) + .chain_err(|| SEK::MoveCallError) ); if hsmap.contains_key(&new_id) { - return Err(SEK::EntryAlreadyExists.into_error()).map_err_into(SEK::MoveCallError) + return Err(SE::from_kind(SEK::EntryAlreadyExists)).chain_err(|| SEK::MoveCallError) } let old_id = entry.get_location().clone(); @@ -698,8 +698,8 @@ impl Store { Ok(()) } }) - .map_err_into(SEK::FileError) - .map_err_into(SEK::MoveCallError) + .chain_err(|| SEK::FileError) + .chain_err(|| SEK::MoveCallError) } /// Move an entry without loading @@ -743,26 +743,26 @@ impl Store { { let mut hsmap = match self.entries.write() { - Err(_) => return Err(SE::new(SEK::LockPoisoned, None)), + Err(_) => return Err(SE::from_kind(SEK::LockPoisoned)), Ok(m) => m, }; if hsmap.contains_key(&new_id) { - return Err(SEK::EntryAlreadyExists.into_error()); + return Err(SE::from_kind(SEK::EntryAlreadyExists)); } // if we do not have an entry here, we fail in `FileAbstraction::rename()` below. // if we have one, but it is borrowed, we really should not rename it, as this might // lead to strange errors if hsmap.get(&old_id).map(|e| e.is_borrowed()).unwrap_or(false) { - return Err(SEK::EntryAlreadyBorrowed.into_error()); + return Err(SE::from_kind(SEK::EntryAlreadyBorrowed)); } let old_id_pb = try!(old_id.clone().with_base(self.path().clone()).into_pathbuf()); let new_id_pb = try!(new_id.clone().with_base(self.path().clone()).into_pathbuf()); match self.backend.rename(&old_id_pb, &new_id_pb) { - Err(e) => return Err(SEK::EntryRenameError.into_error_with_cause(Box::new(e))), + Err(e) => return Err(e).chain_err(|| SEK::EntryRenameError), Ok(_) => { debug!("Rename worked on filesystem"); @@ -1035,7 +1035,7 @@ mod glob_store_iter { use storeid::StoreIdIterator; use error::StoreErrorKind as SEK; - use error::MapErrInto; + use error::ResultExt; use libimagerror::trace::trace_error; @@ -1088,7 +1088,7 @@ mod glob_store_iter { fn next(&mut self) -> Option { while let Some(o) = self.paths.next() { debug!("GlobStoreIdIterator::next() => {:?}", o); - match o.map_err_into(SEK::StoreIdHandlingError) { + match o.chain_err(|| SEK::StoreIdHandlingError) { Ok(path) => { if path.exists() && path.is_file() { return match StoreId::from_full_path(&self.store_path, path) { @@ -1121,7 +1121,7 @@ mod glob_store_iter { /// top-level Value::Table, but not on intermediate tables. pub trait Header { fn verify(&self) -> Result<()>; - fn parse(s: &str) -> RResult; + fn parse(s: &str) -> Result; fn default_header() -> Value; } @@ -1130,15 +1130,15 @@ impl Header for Value { fn verify(&self) -> Result<()> { match *self { Value::Table(ref t) => verify_header(&t), - _ => Err(SE::new(SEK::HeaderTypeFailure, None)), + _ => Err(SE::from_kind(SEK::HeaderTypeFailure)), } } - fn parse(s: &str) -> RResult { + fn parse(s: &str) -> Result { use toml::de::from_str; from_str(s) - .map_err(|_| ParserErrorKind::TOMLParserErrors.into()) + .chain_err(|| SEK::TOMLParserErrors) .and_then(verify_header_consistency) .map(Value::Table) } @@ -1160,21 +1160,18 @@ impl Header for Value { } -fn verify_header_consistency(t: Table) -> RResult { - verify_header(&t) - .map_err(Box::new) - .map_err(|e| ParserErrorKind::HeaderInconsistency.into_error_with_cause(e)) - .map(|_| t) +fn verify_header_consistency(t: Table) -> Result { + verify_header(&t).chain_err(|| SEK::HeaderInconsistency).map(|_| t) } fn verify_header(t: &Table) -> Result<()> { if !has_main_section(t) { - Err(SE::from(ParserErrorKind::MissingMainSection.into_error())) + Err(SE::from_kind(SEK::MissingMainSection)) } else if !has_imag_version_in_main_section(t) { - Err(SE::from(ParserErrorKind::MissingVersionInfo.into_error())) + Err(SE::from_kind(SEK::MissingVersionInfo)) } else if !has_only_tables(t) { debug!("Could not verify that it only has tables in its base table"); - Err(SE::from(ParserErrorKind::NonTableInBaseTable.into_error())) + Err(SE::from_kind(SEK::NonTableInBaseTable)) } else { Ok(()) } @@ -1518,7 +1515,7 @@ mod store_tests { for n in 1..100 { let s = format!("test-{}", n % 50); store.create(PathBuf::from(s.clone())) - .map_err(|e| assert!(is_match!(e.err_type(), SEK::CreateCallError) && n >= 50)) + .map_err(|e| assert!(is_match!(e.kind(), &SEK::CreateCallError) && n >= 50)) .ok() .map(|entry| { assert!(entry.verify().is_ok()); diff --git a/lib/core/libimagstore/src/storeid.rs b/lib/core/libimagstore/src/storeid.rs index 211efbe8..50dd0bc7 100644 --- a/lib/core/libimagstore/src/storeid.rs +++ b/lib/core/libimagstore/src/storeid.rs @@ -26,10 +26,9 @@ use std::fmt::Error as FmtError; use std::result::Result as RResult; use std::path::Components; -use libimagerror::into::IntoError; - use error::StoreErrorKind as SEK; -use error::MapErrInto; +use error::StoreError as SE; +use error::ResultExt; use store::Result; /// The Index into the Store @@ -61,7 +60,7 @@ impl StoreId { where D: Deref { let p = try!( - full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError) + full_path.strip_prefix(store_part).chain_err(|| SEK::StoreIdBuildFromFullPathError) ); StoreId::new(Some(store_part.clone()), PathBuf::from(p)) } @@ -69,7 +68,7 @@ impl StoreId { pub fn new_baseless(id: PathBuf) -> Result { debug!("Trying to get a new baseless id from: {:?}", id); if id.is_absolute() { - Err(SEK::StoreIdLocalPartAbsoluteError.into_error()) + Err(SE::from_kind(SEK::StoreIdLocalPartAbsoluteError)) } else { Ok(StoreId { base: None, @@ -91,7 +90,7 @@ impl StoreId { /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not /// specified. pub fn into_pathbuf(self) -> Result { - let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError.into_error())); + let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError)); base.push(self.id); Ok(base) } @@ -108,7 +107,7 @@ impl StoreId { .unwrap_or_else(|| self.id.clone()) .to_str() .map(String::from) - .ok_or(SEK::StoreIdHandlingError.into_error()) + .ok_or(SE::from_kind(SEK::StoreIdHandlingError)) } /// Returns the components of the `id` part of the StoreId object. @@ -347,7 +346,7 @@ mod test { let pb = id.unwrap().into_pathbuf(); assert!(pb.is_err()); - assert_eq!(pb.unwrap_err().err_type(), SEK::StoreIdHasNoBaseError); + assert!(is_match!(pb.unwrap_err().kind(), &SEK::StoreIdHasNoBaseError)); } #[test] diff --git a/lib/core/libimagstore/src/util.rs b/lib/core/libimagstore/src/util.rs index 97b7cb74..e77e8eb3 100644 --- a/lib/core/libimagstore/src/util.rs +++ b/lib/core/libimagstore/src/util.rs @@ -20,11 +20,10 @@ use regex::Regex; use toml::Value; -use libimagerror::into::IntoError; - use store::Result; use store::Header; use error::StoreErrorKind as SEK; +use error::StoreError as SE; #[cfg(feature = "early-panic")] #[macro_export] @@ -54,12 +53,12 @@ pub fn entry_buffer_to_header_content(buf: &str) -> Result<(Value, String)> { } let matches = match RE.captures(buf) { - None => return Err(SEK::MalformedEntry.into_error()), + None => return Err(SE::from_kind(SEK::MalformedEntry)), Some(s) => s, }; let header = match matches.name("header") { - None => return Err(SEK::MalformedEntry.into_error()), + None => return Err(SE::from_kind(SEK::MalformedEntry)), Some(s) => s }; diff --git a/lib/domain/libimagbookmark/Cargo.toml b/lib/domain/libimagbookmark/Cargo.toml index 8c3da73c..179cff7f 100644 --- a/lib/domain/libimagbookmark/Cargo.toml +++ b/lib/domain/libimagbookmark/Cargo.toml @@ -16,6 +16,7 @@ homepage = "http://imag-pim.org" [dependencies] url = "1.2" regex = "0.1" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 206e31cd..858460d0 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -29,8 +29,9 @@ use std::ops::DerefMut; use regex::Regex; use error::BookmarkErrorKind as BEK; -use error::MapErrInto; -use result::Result; +use error::BookmarkError as BE; +use error::ResultExt; +use error::Result; use module_path::ModuleEntryPath; use libimagstore::store::Store; @@ -40,7 +41,6 @@ use libimagentrylink::external::ExternalLinker; use libimagentrylink::external::iter::UrlIter; use libimagentrylink::internal::InternalLinker; use libimagentrylink::internal::Link as StoreLink; -use libimagerror::into::IntoError; use link::Link; @@ -81,17 +81,17 @@ impl<'a> BookmarkCollection<'a> { store: store, } }) - .map_err_into(BEK::StoreReadError) + .chain_err(|| BEK::StoreReadError) } pub fn get(store: &'a Store, name: &str) -> Result> { ModuleEntryPath::new(name) .into_storeid() .and_then(|id| store.get(id)) - .map_err_into(BEK::StoreReadError) + .chain_err(|| BEK::StoreReadError) .and_then(|fle| { match fle { - None => Err(BEK::CollectionNotFound.into_error()), + None => Err(BE::from_kind(BEK::CollectionNotFound)), Some(e) => Ok(BookmarkCollection { fle: e, store: store, @@ -104,11 +104,11 @@ impl<'a> BookmarkCollection<'a> { ModuleEntryPath::new(name) .into_storeid() .and_then(|id| store.delete(id)) - .map_err_into(BEK::StoreReadError) + .chain_err(|| BEK::StoreReadError) } pub fn links(&self) -> Result { - self.fle.get_external_links(&self.store).map_err_into(BEK::LinkError) + self.fle.get_external_links(&self.store).chain_err(|| BEK::LinkError) } pub fn link_entries(&self) -> Result> { @@ -117,22 +117,22 @@ impl<'a> BookmarkCollection<'a> { self.fle .get_internal_links() .map(|v| v.filter(|id| is_external_link_storeid(id)).collect()) - .map_err_into(BEK::StoreReadError) + .chain_err(|| BEK::StoreReadError) } pub fn add_link(&mut self, l: Link) -> Result<()> { use link::IntoUrl; l.into_url() - .and_then(|url| self.add_external_link(self.store, url).map_err_into(BEK::LinkingError)) - .map_err_into(BEK::LinkError) + .and_then(|url| self.add_external_link(self.store, url).chain_err(|| BEK::LinkingError)) + .chain_err(|| BEK::LinkError) } pub fn get_links_matching(&self, r: Regex) -> Result> { use self::iter::IntoLinksMatchingRegexIter; self.get_external_links(self.store) - .map_err_into(BEK::LinkError) + .chain_err(|| BEK::LinkError) .map(|iter| iter.matching_regex(r)) } @@ -141,17 +141,17 @@ impl<'a> BookmarkCollection<'a> { l.into_url() .and_then(|url| { - self.remove_external_link(self.store, url).map_err_into(BEK::LinkingError) + self.remove_external_link(self.store, url).chain_err(|| BEK::LinkingError) }) - .map_err_into(BEK::LinkError) + .chain_err(|| BEK::LinkError) } } pub mod iter { use link::Link; - use result::Result; - use error::{MapErrInto, BookmarkErrorKind as BEK}; + use error::Result; + use error::{ResultExt, BookmarkErrorKind as BEK}; pub struct LinkIter(I) where I: Iterator; @@ -194,7 +194,7 @@ pub mod iter { loop { let n = match self.0.next() { Some(Ok(n)) => n, - Some(Err(e)) => return Some(Err(e).map_err_into(BEK::LinkError)), + Some(Err(e)) => return Some(Err(e).chain_err(|| BEK::LinkError)), None => return None, }; diff --git a/lib/domain/libimagbookmark/src/error.rs b/lib/domain/libimagbookmark/src/error.rs index 9b52a169..0001e76a 100644 --- a/lib/domain/libimagbookmark/src/error.rs +++ b/lib/domain/libimagbookmark/src/error.rs @@ -17,17 +17,37 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(BookmarkError, BookmarkErrorKind, - StoreReadError => "Store read error", - LinkError => "Link error", - LinkParsingError => "Link parsing error", - LinkingError => "Error while linking", - CollectionNotFound => "Link-Collection not found" - ); -); +error_chain! { + types { + BookmarkError, BookmarkErrorKind, ResultExt, Result; + } -pub use self::error::BookmarkError; -pub use self::error::BookmarkErrorKind; -pub use self::error::MapErrInto; + errors { + StoreReadError { + description("Store read error") + display("Store read error") + } + + LinkError { + description("Link error") + display("Link error") + } + + LinkParsingError { + description("Link parsing error") + display("Link parsing error") + } + + LinkingError { + description("Error while linking") + display("Error while linking") + } + + CollectionNotFound { + description("Link-Collection not found") + display("Link-Collection not found") + } + + } +} diff --git a/lib/domain/libimagbookmark/src/lib.rs b/lib/domain/libimagbookmark/src/lib.rs index 0a864121..6567cbf1 100644 --- a/lib/domain/libimagbookmark/src/lib.rs +++ b/lib/domain/libimagbookmark/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -35,9 +37,10 @@ extern crate url; extern crate regex; +#[macro_use] extern crate error_chain; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagentrylink; module_entry_path_mod!("bookmark"); @@ -45,4 +48,3 @@ module_entry_path_mod!("bookmark"); pub mod collection; pub mod error; pub mod link; -pub mod result; diff --git a/lib/domain/libimagbookmark/src/link.rs b/lib/domain/libimagbookmark/src/link.rs index 1da91c8a..038fea7f 100644 --- a/lib/domain/libimagbookmark/src/link.rs +++ b/lib/domain/libimagbookmark/src/link.rs @@ -19,7 +19,7 @@ use std::ops::{Deref, DerefMut}; -use result::Result; +use error::Result; use url::Url; @@ -67,9 +67,9 @@ impl IntoUrl for Link { fn into_url(self) -> Result { use error::BookmarkErrorKind as BEK; - use error::MapErrInto; + use error::ResultExt; - Url::parse(&self[..]).map_err_into(BEK::LinkParsingError) + Url::parse(&self[..]).chain_err(|| BEK::LinkParsingError) } } diff --git a/lib/domain/libimagbookmark/src/result.rs b/lib/domain/libimagbookmark/src/result.rs deleted file mode 100644 index 780a8035..00000000 --- a/lib/domain/libimagbookmark/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::BookmarkError; - -pub type Result = RResult; - diff --git a/lib/domain/libimagcounter/Cargo.toml b/lib/domain/libimagcounter/Cargo.toml index 16d5e1b4..c6c61abb 100644 --- a/lib/domain/libimagcounter/Cargo.toml +++ b/lib/domain/libimagcounter/Cargo.toml @@ -17,6 +17,7 @@ homepage = "http://imag-pim.org" log = "0.3" toml = "0.4.*" toml-query = "0.3.*" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagcounter/src/counter.rs b/lib/domain/libimagcounter/src/counter.rs index b34219a0..855ee5a1 100644 --- a/lib/domain/libimagcounter/src/counter.rs +++ b/lib/domain/libimagcounter/src/counter.rs @@ -32,13 +32,12 @@ use libimagstore::storeid::StoreIdIterator; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; -use libimagerror::into::IntoError; use module_path::ModuleEntryPath; -use result::Result; +use error::Result; use error::CounterError as CE; use error::CounterErrorKind as CEK; -use error::error::MapErrInto; +use error::ResultExt; pub type CounterName = String; @@ -71,25 +70,25 @@ impl<'a> Counter<'a> { let fle = { let id = try!(ModuleEntryPath::new(name.clone()) .into_storeid() - .map_err_into(CEK::StoreWriteError)); - let mut lockentry = try!(store.create(id).map_err_into(CEK::StoreWriteError)); + .chain_err(|| CEK::StoreWriteError)); + let mut lockentry = try!(store.create(id).chain_err(|| CEK::StoreWriteError)); { let entry = lockentry.deref_mut(); let header = entry.get_header_mut(); let setres = header.set(&String::from("counter"), Value::Table(BTreeMap::new())); if setres.is_err() { - return Err(CEK::StoreWriteError.into_error()); + return Err(CE::from_kind(CEK::StoreWriteError)); } let setres = header.set(&String::from("counter.name"), Value::String(name)); if setres.is_err() { - return Err(CEK::StoreWriteError.into_error()) + return Err(CE::from_kind(CEK::StoreWriteError)) } let setres = header.set(&String::from("counter.value"), Value::Integer(init)); if setres.is_err() { - return Err(CEK::StoreWriteError.into_error()) + return Err(CE::from_kind(CEK::StoreWriteError)) } } @@ -107,7 +106,7 @@ impl<'a> Counter<'a> { let setres = header.set(&String::from("counter.unit"), Value::String(u.0)); if setres.is_err() { self.unit = None; - return Err(CEK::StoreWriteError.into_error()) + return Err(CE::from_kind(CEK::StoreWriteError)) } }; Ok(self) @@ -116,26 +115,26 @@ impl<'a> Counter<'a> { pub fn inc(&mut self) -> Result<()> { let header = self.fle.deref_mut().get_header_mut(); let query = String::from("counter.value"); - match try!(header.read(&query).map_err_into(CEK::StoreReadError)) { + match try!(header.read(&query).chain_err(|| CEK::StoreReadError)) { Some(&Value::Integer(i)) => { header.set(&query, Value::Integer(i + 1)) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError) .map(|_| ()) }, - _ => Err(CE::new(CEK::StoreReadError, None)), + _ => Err(CE::from_kind(CEK::StoreReadError)), } } pub fn dec(&mut self) -> Result<()> { let header = self.fle.deref_mut().get_header_mut(); let query = String::from("counter.value"); - match try!(header.read(&query).map_err_into(CEK::StoreReadError)) { + match try!(header.read(&query).chain_err(|| CEK::StoreReadError)) { Some(&Value::Integer(i)) => { header.set(&query, Value::Integer(i - 1)) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError) .map(|_| ()) }, - _ => Err(CE::new(CEK::StoreReadError, None)), + _ => Err(CE::from_kind(CEK::StoreReadError)), } } @@ -148,23 +147,23 @@ impl<'a> Counter<'a> { .deref_mut() .get_header_mut() .set(&String::from("counter.value"), Value::Integer(v)) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError) .map(|_| ()) } pub fn name(&self) -> Result { self.read_header_at("counter.name", |v| match v { Some(&Value::String(ref s)) => Ok(s.clone()), - Some(_) => Err(CEK::HeaderTypeError.into_error()), - _ => Err(CEK::StoreReadError.into_error()), + Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)), + _ => Err(CE::from_kind(CEK::StoreReadError)), }) } pub fn value(&self) -> Result { self.read_header_at("counter.value", |v| match v { Some(&Value::Integer(i)) => Ok(i), - Some(_) => Err(CEK::HeaderTypeError.into_error()), - _ => Err(CEK::StoreReadError.into_error()), + Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)), + _ => Err(CE::from_kind(CEK::StoreReadError)), }) } @@ -175,8 +174,8 @@ impl<'a> Counter<'a> { pub fn read_unit(&self) -> Result> { self.read_header_at("counter.unit", |s| match s { Some(&Value::String(ref s)) => Ok(Some(CounterUnit::new(s.clone()))), - Some(_) => Err(CEK::HeaderTypeError.into_error()), - _ => Err(CEK::StoreReadError.into_error()), + Some(_) => Err(CE::from_kind(CEK::HeaderTypeError)), + _ => Err(CE::from_kind(CEK::StoreReadError)), }) } @@ -187,7 +186,7 @@ impl<'a> Counter<'a> { self.fle .get_header() .read(&String::from(name)) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError) .and_then(f) } @@ -195,7 +194,7 @@ impl<'a> Counter<'a> { debug!("Loading counter: '{}'", name); let id = try!(ModuleEntryPath::new(name) .into_storeid() - .map_err_into(CEK::StoreWriteError)); + .chain_err(|| CEK::StoreWriteError)); Counter::from_storeid(store, id) } @@ -203,14 +202,14 @@ impl<'a> Counter<'a> { debug!("Deleting counter: '{}'", name); let id = try!(ModuleEntryPath::new(name) .into_storeid() - .map_err_into(CEK::StoreWriteError)); - store.delete(id).map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError)); + store.delete(id).chain_err(|| CEK::StoreWriteError) } pub fn all_counters(store: &Store) -> Result { store.retrieve_for_module("counter") .map(|iter| CounterIterator::new(store, iter)) - .map_err_into(CEK::StoreReadError) + .chain_err(|| CEK::StoreReadError) } } @@ -224,11 +223,11 @@ impl<'a> FromStoreId for Counter<'a> { fn from_storeid(store: &Store, id: StoreId) -> Result { debug!("Loading counter from storeid: '{:?}'", id); match store.retrieve(id) { - Err(e) => Err(CE::new(CEK::StoreReadError, Some(Box::new(e)))), + Err(e) => Err(e).chain_err(|| CEK::StoreReadError), Ok(c) => { let mut counter = Counter { fle: c, unit: None }; counter.read_unit() - .map_err_into(CEK::StoreReadError) + .chain_err(|| CEK::StoreReadError) .and_then(|u| { counter.unit = u; Ok(counter) diff --git a/lib/domain/libimagcounter/src/error.rs b/lib/domain/libimagcounter/src/error.rs index c886d901..c16c3f4d 100644 --- a/lib/domain/libimagcounter/src/error.rs +++ b/lib/domain/libimagcounter/src/error.rs @@ -17,16 +17,37 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(CounterError, CounterErrorKind, - StoreIdError => "StoreId error", - StoreReadError => "Store read error", - StoreWriteError => "Store write error", - HeaderTypeError => "Header type error", - HeaderFieldMissingError => "Header field missing error" - ); -); +error_chain! { + types { + CounterError, CounterErrorKind, ResultExt, Result; + } -pub use self::error::CounterError; -pub use self::error::CounterErrorKind; + errors { + StoreIdError { + description("StoreId error") + display("StoreId error") + } + + StoreReadError { + description("Store read error") + display("Store read error") + } + + StoreWriteError { + description("Store write error") + display("Store write error") + } + + HeaderTypeError { + description("Header type error") + display("Header type error") + } + + HeaderFieldMissingError { + description("Header field missing error") + display("Header field missing error") + } + + } +} diff --git a/lib/domain/libimagcounter/src/lib.rs b/lib/domain/libimagcounter/src/lib.rs index cbbd043c..41db759d 100644 --- a/lib/domain/libimagcounter/src/lib.rs +++ b/lib/domain/libimagcounter/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -36,13 +38,13 @@ extern crate toml; extern crate toml_query; #[macro_use] extern crate log; +#[macro_use] extern crate error_chain; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; module_entry_path_mod!("counter"); pub mod counter; pub mod error; -pub mod result; diff --git a/lib/domain/libimagcounter/src/result.rs b/lib/domain/libimagcounter/src/result.rs deleted file mode 100644 index e24b90c9..00000000 --- a/lib/domain/libimagcounter/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::CounterError; - -pub type Result = RResult; - diff --git a/lib/domain/libimagdiary/Cargo.toml b/lib/domain/libimagdiary/Cargo.toml index bdd65d36..55a5fce4 100644 --- a/lib/domain/libimagdiary/Cargo.toml +++ b/lib/domain/libimagdiary/Cargo.toml @@ -19,6 +19,7 @@ log = "0.3" toml = "0.4.*" toml-query = "0.3.*" itertools = "0.5" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagdiary/src/diary.rs b/lib/domain/libimagdiary/src/diary.rs index c67467cc..f8eecded 100644 --- a/lib/domain/libimagdiary/src/diary.rs +++ b/lib/domain/libimagdiary/src/diary.rs @@ -32,8 +32,8 @@ use chrono::Timelike; use entry::DiaryEntry; use diaryid::DiaryId; use error::DiaryErrorKind as DEK; -use error::MapErrInto; -use result::Result; +use error::ResultExt; +use error::Result; use iter::DiaryEntryIterator; use iter::DiaryNameIterator; @@ -63,28 +63,27 @@ impl Diary for Store { let ndt = dt.naive_local(); let id = DiaryId::new(String::from(diary_name), ndt.year(), ndt.month(), ndt.day(), 0, 0); - self.retrieve(id).map_err_into(DEK::StoreReadError) + self.retrieve(id).chain_err(|| DEK::StoreReadError) } - // create or get a new entry for today fn new_entry_now(&self, diary_name: &str) -> Result { let dt = Local::now(); let ndt = dt.naive_local(); let id = DiaryId::new(String::from(diary_name), - ndt.year(), - ndt.month(), - ndt.day(), - ndt.minute(), - ndt.second()); + ndt.year(), + ndt.month(), + ndt.day(), + ndt.hour(), + ndt.minute()); - self.retrieve(id).map_err_into(DEK::StoreReadError) + self.retrieve(id).chain_err(|| DEK::StoreReadError) } // Get an iterator for iterating over all entries fn entries(&self, diary_name: &str) -> Result { self.retrieve_for_module("diary") .map(|iter| DiaryEntryIterator::new(self, String::from(diary_name), iter)) - .map_err_into(DEK::StoreReadError) + .chain_err(|| DEK::StoreReadError) } fn get_youngest_entry_id(&self, diary_name: &str) -> Option> { @@ -127,7 +126,7 @@ impl Diary for Store { /// Get all diary names fn diary_names(&self) -> Result { self.retrieve_for_module("diary") - .map_err_into(DEK::StoreReadError) + .chain_err(|| DEK::StoreReadError) .map(DiaryNameIterator::new) } diff --git a/lib/domain/libimagdiary/src/diaryid.rs b/lib/domain/libimagdiary/src/diaryid.rs index da1afc42..0d47002e 100644 --- a/lib/domain/libimagdiary/src/diaryid.rs +++ b/lib/domain/libimagdiary/src/diaryid.rs @@ -32,8 +32,7 @@ use libimagstore::store::Result as StoreResult; use error::DiaryError as DE; use error::DiaryErrorKind as DEK; -use error::MapErrInto; -use libimagerror::into::IntoError; +use error::ResultExt; use module_path::ModuleEntryPath; @@ -191,7 +190,7 @@ fn component_to_str<'a>(com: Component<'a>) -> Result<&'a str, DE> { Component::Normal(s) => Some(s), _ => None, }.and_then(|s| s.to_str()) - .ok_or(DEK::IdParseError.into_error()) + .ok_or(DE::from_kind(DEK::IdParseError)) } impl FromStoreId for DiaryId { @@ -204,7 +203,7 @@ impl FromStoreId for DiaryId { fn next_component<'a>(components: &'a mut Rev) -> Result<&'a str, DE> { components.next() - .ok_or(DEK::IdParseError.into_error()) + .ok_or(DE::from_kind(DEK::IdParseError)) .and_then(component_to_str) } @@ -222,21 +221,21 @@ impl FromStoreId for DiaryId { match (hour, minute) { (Some(h), Some(m)) => Ok((h, m)), - _ => return Err(DE::new(DEK::IdParseError, None)), + _ => return Err(DE::from_kind(DEK::IdParseError)), } })); let day: Result = next_component(&mut cmps) .and_then(|s| s.parse::() - .map_err_into(DEK::IdParseError)); + .chain_err(|| DEK::IdParseError)); let month: Result = next_component(&mut cmps) .and_then(|s| s.parse::() - .map_err_into(DEK::IdParseError)); + .chain_err(|| DEK::IdParseError)); let year: Result = next_component(&mut cmps) .and_then(|s| s.parse::() - .map_err_into(DEK::IdParseError)); + .chain_err(|| DEK::IdParseError)); let name = next_component(&mut cmps).map(String::from); diff --git a/lib/domain/libimagdiary/src/entry.rs b/lib/domain/libimagdiary/src/entry.rs index 2da96199..40206404 100644 --- a/lib/domain/libimagdiary/src/entry.rs +++ b/lib/domain/libimagdiary/src/entry.rs @@ -21,7 +21,7 @@ use libimagstore::store::Entry; use diaryid::DiaryId; use diaryid::FromStoreId; -use result::Result; +use error::Result; pub trait DiaryEntry { fn diary_id(&self) -> Result; diff --git a/lib/domain/libimagdiary/src/error.rs b/lib/domain/libimagdiary/src/error.rs index 1164f806..07975b9e 100644 --- a/lib/domain/libimagdiary/src/error.rs +++ b/lib/domain/libimagdiary/src/error.rs @@ -17,23 +17,67 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(DiaryError, DiaryErrorKind, - StoreWriteError => "Error writing store", - StoreReadError => "Error reading store", - CannotFindDiary => "Cannot find diary", - CannotCreateNote => "Cannot create Note object for diary entry", - DiaryEditError => "Cannot edit diary entry", - PathConversionError => "Error while converting paths internally", - EntryNotInDiary => "Entry not in Diary", - IOError => "IO Error", - ViewError => "Error viewing diary entry", - IdParseError => "Error while parsing ID", - DiaryNameFindingError => "Error while finding a diary name" - ); -); +error_chain! { + types { + DiaryError, DiaryErrorKind, ResultExt, Result; + } -pub use self::error::DiaryError; -pub use self::error::DiaryErrorKind; -pub use self::error::MapErrInto; + errors { + StoreWriteError { + description("Error writing store") + display("Error writing store") + } + + StoreReadError { + description("Error reading store") + display("Error reading store") + } + + CannotFindDiary { + description("Cannot find diary") + display("Cannot find diary") + } + + CannotCreateNote { + description("Cannot create Note object for diary entry") + display("Cannot create Note object for diary entry") + } + + DiaryEditError { + description("Cannot edit diary entry") + display("Cannot edit diary entry") + } + + PathConversionError { + description("Error while converting paths internally") + display("Error while converting paths internally") + } + + EntryNotInDiary { + description("Entry not in Diary") + display("Entry not in Diary") + } + + IOError { + description("IO Error") + display("IO Error") + } + + ViewError { + description("Error viewing diary entry") + display("Error viewing diary entry") + } + + IdParseError { + description("Error while parsing ID") + display("Error while parsing ID") + } + + DiaryNameFindingError { + description("Error while finding a diary name") + display("Error while finding a diary name") + } + + } +} diff --git a/lib/domain/libimagdiary/src/iter.rs b/lib/domain/libimagdiary/src/iter.rs index 32fe407c..8d22aff8 100644 --- a/lib/domain/libimagdiary/src/iter.rs +++ b/lib/domain/libimagdiary/src/iter.rs @@ -24,15 +24,14 @@ use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreIdIterator; use libimagerror::trace::trace_error; -use libimagerror::into::IntoError; use diaryid::DiaryId; use diaryid::FromStoreId; -use error::DiaryError as DE; -use error::DiaryErrorKind as DEK; -use error::MapErrInto; -use result::Result; use is_in_diary::IsInDiary; +use error::DiaryErrorKind as DEK; +use error::DiaryError as DE; +use error::ResultExt; +use error::Result; /// A iterator for iterating over diary entries pub struct DiaryEntryIterator<'a> { @@ -120,8 +119,7 @@ impl<'a> Iterator for DiaryEntryIterator<'a> { return Some(self .store .retrieve(next) - .map_err(|e| DE::new(DEK::StoreReadError, Some(Box::new(e)))) - ); + .chain_err(|| DEK::StoreReadError)); } } else { debug!("Not in the requested diary ({}): {:?}", self.name, next); @@ -153,12 +151,12 @@ impl Iterator for DiaryNameIterator { .next() .map(|s| { s.to_str() - .map_err_into(DEK::DiaryNameFindingError) + .chain_err(|| DEK::DiaryNameFindingError) .and_then(|s| { s.split("diary/") .nth(1) .and_then(|n| n.split("/").nth(0).map(String::from)) - .ok_or(DEK::DiaryNameFindingError.into_error()) + .ok_or(DE::from_kind(DEK::DiaryNameFindingError)) }) }) } diff --git a/lib/domain/libimagdiary/src/lib.rs b/lib/domain/libimagdiary/src/lib.rs index ca54f902..b9c9697b 100644 --- a/lib/domain/libimagdiary/src/lib.rs +++ b/lib/domain/libimagdiary/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -38,9 +40,10 @@ extern crate chrono; extern crate toml; extern crate toml_query; extern crate itertools; +#[macro_use] extern crate error_chain; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagentryedit; extern crate libimagentryview; extern crate libimagrt; @@ -54,6 +57,5 @@ pub mod diary; pub mod is_in_diary; pub mod entry; pub mod iter; -pub mod result; pub mod viewer; diff --git a/lib/domain/libimagdiary/src/result.rs b/lib/domain/libimagdiary/src/result.rs deleted file mode 100644 index b4f5f382..00000000 --- a/lib/domain/libimagdiary/src/result.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::DiaryError; - -pub type Result = RResult; diff --git a/lib/domain/libimagdiary/src/viewer.rs b/lib/domain/libimagdiary/src/viewer.rs index c0c03fc6..b37061b1 100644 --- a/lib/domain/libimagdiary/src/viewer.rs +++ b/lib/domain/libimagdiary/src/viewer.rs @@ -21,8 +21,8 @@ use entry::DiaryEntry; use error::DiaryErrorKind as DEK; -use error::MapErrInto; -use result::Result; +use error::ResultExt; +use error::Result; use libimagstore::store::FileLockEntry; use libimagentryview::viewer::Viewer; @@ -56,8 +56,8 @@ impl DiaryViewer { } let _ = try!(self.0 .view_entry(&entry) - .map_err_into(DEK::ViewError) - .map_err_into(DEK::IOError)); + .chain_err(|| DEK::ViewError) + .chain_err(|| DEK::IOError)); println!("\n---\n"); } diff --git a/lib/domain/libimagmail/Cargo.toml b/lib/domain/libimagmail/Cargo.toml index ccfb6c53..f1c67aa3 100644 --- a/lib/domain/libimagmail/Cargo.toml +++ b/lib/domain/libimagmail/Cargo.toml @@ -17,6 +17,7 @@ homepage = "http://imag-pim.org" log = "0.3" email = "0.0.17" filters = "0.1.*" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagmail/src/error.rs b/lib/domain/libimagmail/src/error.rs index 8c616fba..1a986e0b 100644 --- a/lib/domain/libimagmail/src/error.rs +++ b/lib/domain/libimagmail/src/error.rs @@ -17,19 +17,44 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(MailError, MailErrorKind, - RefCreationError => "Error creating a reference to a file/directory", - RefHandlingError => "Error while handling the internal reference object", - MailParsingError => "Error while parsing mail", +error_chain! { + types { + MailError, MailErrorKind, ResultExt, Result; + } - FetchByHashError => "Error fetching mail from Store by hash", - FetchError => "Error fetching mail from Store", - IOError => "IO Error" - ); -); + links { + RefError(::libimagentryref::error::RefError, ::libimagentryref::error::RefErrorKind); + } -pub use self::error::MailError; -pub use self::error::MailErrorKind; -pub use self::error::MapErrInto; + + errors { + RefCreationError { + description("Error creating a reference to a file/directory") + display("Error creating a reference to a file/directory") + } + + RefHandlingError { + description("Error handling a reference") + display("Error handling a reference") + } + + MailParsingError { + description("Failed to parse mail") + display("Failed to parse mail") + } + + FetchByHashError { + description("Error fetching mail from Store by hash") + display("Error fetching mail from Store by hash") + } + FetchError { + description("Error fetching mail from Store") + display("Error fetching mail from Store") + } + IOError { + description("IO Error") + display("IO Error") + } + } +} diff --git a/lib/domain/libimagmail/src/hasher.rs b/lib/domain/libimagmail/src/hasher.rs index cc68d9a8..07817602 100644 --- a/lib/domain/libimagmail/src/hasher.rs +++ b/lib/domain/libimagmail/src/hasher.rs @@ -25,11 +25,8 @@ use email::MimeMessage; use libimagentryref::hasher::Hasher; use libimagentryref::hasher::DefaultHasher; use libimagentryref::error::RefErrorKind as REK; -use libimagentryref::error::MapErrInto; -use libimagentryref::result::Result as RResult; -use libimagerror::into::IntoError; - -use error::MailErrorKind as MEK; +use libimagentryref::error::ResultExt; +use libimagentryref::error::Result as RResult; pub struct MailHasher { defaulthasher: DefaultHasher, @@ -54,12 +51,10 @@ impl Hasher for MailHasher { use email::Header; let mut s = String::new(); - try!(c.read_to_string(&mut s).map_err_into(REK::UTF8Error).map_err_into(REK::IOError)); + try!(c.read_to_string(&mut s).chain_err(|| REK::UTF8Error).chain_err(|| REK::IOError)); MimeMessage::parse(&s) - .map_err(Box::new) - .map_err(|e| MEK::MailParsingError.into_error_with_cause(e)) - .map_err_into(REK::RefHashingError) + .chain_err(|| REK::RefHashingError) .and_then(|mail| { let has_key = |hdr: &Header, exp: &str| hdr.name == exp; @@ -73,8 +68,7 @@ impl Hasher for MailHasher { for hdr in mail.headers.iter().filter(|item| filter.filter(item)) { let s = try!(hdr .get_value() - .map_err(Box::new) - .map_err(|e| REK::RefHashingError.into_error_with_cause(e))); + .chain_err(|| REK::RefHashingError)); v.push(s); } diff --git a/lib/domain/libimagmail/src/iter.rs b/lib/domain/libimagmail/src/iter.rs index ee418765..89a84539 100644 --- a/lib/domain/libimagmail/src/iter.rs +++ b/lib/domain/libimagmail/src/iter.rs @@ -25,7 +25,7 @@ //! use mail::Mail; -use result::Result; +use error::Result; use libimagstore::store::FileLockEntry; diff --git a/lib/domain/libimagmail/src/lib.rs b/lib/domain/libimagmail/src/lib.rs index 14200eaf..9a6b9413 100644 --- a/lib/domain/libimagmail/src/lib.rs +++ b/lib/domain/libimagmail/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -36,8 +38,9 @@ #[macro_use] extern crate log; extern crate email; extern crate filters; +#[macro_use] extern crate error_chain; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagstore; extern crate libimagentryref; @@ -45,5 +48,4 @@ pub mod error; pub mod hasher; pub mod iter; pub mod mail; -pub mod result; diff --git a/lib/domain/libimagmail/src/mail.rs b/lib/domain/libimagmail/src/mail.rs index 8f2e05c5..201bceee 100644 --- a/lib/domain/libimagmail/src/mail.rs +++ b/lib/domain/libimagmail/src/mail.rs @@ -32,8 +32,8 @@ use email::MimeMessage; use email::results::ParsingResult as EmailParsingResult; use hasher::MailHasher; -use result::Result; -use error::{MapErrInto, MailErrorKind as MEK}; +use error::Result; +use error::{ResultExt, MailErrorKind as MEK}; struct Buffer(String); @@ -61,17 +61,17 @@ impl<'a> Mail<'a> { let p = PathBuf::from(p.as_ref()); store.create_with_hasher(p, f, h) - .map_err_into(MEK::RefCreationError) + .chain_err(|| MEK::RefCreationError) .and_then(|reference| { debug!("Build reference file: {:?}", reference); reference.fs_file() - .map_err_into(MEK::RefHandlingError) - .and_then(|path| File::open(path).map_err_into(MEK::IOError)) + .chain_err(|| MEK::RefHandlingError) + .and_then(|path| File::open(path).chain_err(|| MEK::IOError)) .and_then(|mut file| { let mut s = String::new(); file.read_to_string(&mut s) .map(|_| s) - .map_err_into(MEK::IOError) + .chain_err(|| MEK::IOError) }) .map(Buffer::from) .map(|buffer| Mail(reference, buffer)) @@ -82,8 +82,8 @@ impl<'a> Mail<'a> { pub fn open>(store: &Store, hash: S) -> Result> { debug!("Opening Mail by Hash"); store.get_by_hash(String::from(hash.as_ref())) - .map_err_into(MEK::FetchByHashError) - .map_err_into(MEK::FetchError) + .chain_err(|| MEK::FetchByHashError) + .chain_err(|| MEK::FetchError) .and_then(|o| match o { Some(r) => Mail::from_fle(r).map(Some), None => Ok(None), @@ -94,13 +94,13 @@ impl<'a> Mail<'a> { /// Implement me as TryFrom as soon as it is stable pub fn from_fle(fle: FileLockEntry<'a>) -> Result> { fle.fs_file() - .map_err_into(MEK::RefHandlingError) - .and_then(|path| File::open(path).map_err_into(MEK::IOError)) + .chain_err(|| MEK::RefHandlingError) + .and_then(|path| File::open(path).chain_err(|| MEK::IOError)) .and_then(|mut file| { let mut s = String::new(); file.read_to_string(&mut s) .map(|_| s) - .map_err_into(MEK::IOError) + .chain_err(|| MEK::IOError) }) .map(Buffer::from) .map(|buffer| Mail(fle, buffer)) @@ -110,7 +110,7 @@ impl<'a> Mail<'a> { debug!("Getting field in mail: {:?}", field); self.1 .parsed() - .map_err_into(MEK::MailParsingError) + .chain_err(|| MEK::MailParsingError) .map(|parsed| { parsed.headers .iter() diff --git a/lib/domain/libimagmail/src/result.rs b/lib/domain/libimagmail/src/result.rs deleted file mode 100644 index 7f745eda..00000000 --- a/lib/domain/libimagmail/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::MailError; - -pub type Result = RResult; - diff --git a/lib/domain/libimagnotes/Cargo.toml b/lib/domain/libimagnotes/Cargo.toml index 6cb7526a..d9f05e75 100644 --- a/lib/domain/libimagnotes/Cargo.toml +++ b/lib/domain/libimagnotes/Cargo.toml @@ -17,6 +17,7 @@ homepage = "http://imag-pim.org" log = "0.3" toml = "^0.4" toml-query = "0.3.0" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagnotes/src/error.rs b/lib/domain/libimagnotes/src/error.rs index 9fd51218..6359edb2 100644 --- a/lib/domain/libimagnotes/src/error.rs +++ b/lib/domain/libimagnotes/src/error.rs @@ -17,16 +17,32 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(NoteError, NoteErrorKind, - StoreWriteError => "Error writing store", - StoreReadError => "Error reading store", - HeaderTypeError => "Header type error", - NoteToEntryConversion => "Error converting Note instance to Entry instance" - ); -); +error_chain! { + types { + NoteError, NoteErrorKind, ResultExt, Result; + } -pub use self::error::NoteError; -pub use self::error::NoteErrorKind; -pub use self::error::MapErrInto; + errors { + StoreWriteError { + description("Error writing store") + display("Error writing store") + } + + StoreReadError { + description("Error reading store") + display("Error reading store") + } + + HeaderTypeError { + description("Header type error") + display("Header type error") + } + + NoteToEntryConversion { + description("Error converting Note instance to Entry instance") + display("Error converting Note instance to Entry instance") + } + + } +} diff --git a/lib/domain/libimagnotes/src/lib.rs b/lib/domain/libimagnotes/src/lib.rs index 699701ac..6d2fbba4 100644 --- a/lib/domain/libimagnotes/src/lib.rs +++ b/lib/domain/libimagnotes/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -36,15 +38,15 @@ #[macro_use] extern crate log; extern crate toml; extern crate toml_query; +#[macro_use] extern crate error_chain; extern crate libimagrt; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagentryedit; module_entry_path_mod!("notes"); pub mod error; pub mod note; -pub mod result; diff --git a/lib/domain/libimagnotes/src/note.rs b/lib/domain/libimagnotes/src/note.rs index feaa8818..599a0db6 100644 --- a/lib/domain/libimagnotes/src/note.rs +++ b/lib/domain/libimagnotes/src/note.rs @@ -24,7 +24,7 @@ use toml::Value; use libimagrt::runtime::Runtime; use libimagentryedit::edit::Edit; -use libimagentryedit::result::Result as EditResult; +use libimagentryedit::error::Result as EditResult; use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreIdIterator; @@ -35,10 +35,10 @@ use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; use module_path::ModuleEntryPath; -use result::Result; -use error::NoteError as NE; +use error::Result; use error::NoteErrorKind as NEK; -use error::MapErrInto; +use error::NoteError as NE; +use error::ResultExt; #[derive(Debug)] pub struct Note<'a> { @@ -55,24 +55,20 @@ impl<'a> Note<'a> { let mut lockentry = try!(ModuleEntryPath::new(name.clone()) .into_storeid() .and_then(|id| store.create(id)) - .map_err_into(NEK::StoreWriteError)); + .chain_err(|| NEK::StoreWriteError)); { let entry = lockentry.deref_mut(); { let header = entry.get_header_mut(); - let setres = header.set("note", Value::Table(BTreeMap::new())); - if setres.is_err() { - let kind = NEK::StoreWriteError; - return Err(NE::new(kind, Some(Box::new(setres.unwrap_err())))); - } + let _ = header + .set("note", Value::Table(BTreeMap::new())) + .chain_err(|| NEK::StoreWriteError); - let setres = header.set("note.name", Value::String(name)); - if setres.is_err() { - let kind = NEK::StoreWriteError; - return Err(NE::new(kind, Some(Box::new(setres.unwrap_err())))); - } + let _ = header + .set("note.name", Value::String(name)) + .chain_err(|| NEK::StoreWriteError); } *entry.get_content_mut() = text; @@ -88,7 +84,7 @@ impl<'a> Note<'a> { self.entry .get_header_mut() .set("note.name", Value::String(n)) - .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e)))) + .chain_err(|| NEK::StoreWriteError) .map(|_| ()) } @@ -96,11 +92,10 @@ impl<'a> Note<'a> { let header = self.entry.get_header(); match header.read("note.name") { Ok(Some(&Value::String(ref s))) => Ok(s.clone()), - Ok(_) => { - let e = NE::new(NEK::HeaderTypeError, None); - Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))) + Ok(_) => { + Err(NE::from_kind(NEK::HeaderTypeError)).chain_err(|| NEK::StoreReadError) }, - Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))) + Err(e) => Err(e).chain_err(|| NEK::StoreReadError) } } @@ -116,14 +111,14 @@ impl<'a> Note<'a> { ModuleEntryPath::new(name) .into_storeid() .and_then(|id| store.delete(id)) - .map_err_into(NEK::StoreWriteError) + .chain_err(|| NEK::StoreWriteError) } pub fn retrieve(store: &Store, name: String) -> Result { ModuleEntryPath::new(name) .into_storeid() .and_then(|id| store.retrieve(id)) - .map_err_into(NEK::StoreWriteError) + .chain_err(|| NEK::StoreWriteError) .map(|entry| Note { entry: entry }) } @@ -131,14 +126,14 @@ impl<'a> Note<'a> { ModuleEntryPath::new(name) .into_storeid() .and_then(|id| store.get(id)) - .map_err_into(NEK::StoreWriteError) + .chain_err(|| NEK::StoreWriteError) .map(|o| o.map(|entry| Note { entry: entry })) } pub fn all_notes(store: &Store) -> Result { store.retrieve_for_module("notes") .map(|iter| NoteIterator::new(store, iter)) - .map_err(|e| NE::new(NEK::StoreReadError, Some(Box::new(e)))) + .chain_err(|| NEK::StoreReadError) } } @@ -160,7 +155,7 @@ impl<'a> FromStoreId for Note<'a> { fn from_storeid(store: &Store, id: StoreId) -> Result { debug!("Loading note from storeid: '{:?}'", id); match store.retrieve(id) { - Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))), + Err(e) => Err(e).chain_err(|| NEK::StoreReadError), Ok(entry) => Ok(Note { entry: entry }), } } diff --git a/lib/domain/libimagnotes/src/result.rs b/lib/domain/libimagnotes/src/result.rs deleted file mode 100644 index a11ba895..00000000 --- a/lib/domain/libimagnotes/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::NoteError; - -pub type Result = RResult; - diff --git a/lib/domain/libimagtimetrack/Cargo.toml b/lib/domain/libimagtimetrack/Cargo.toml index 6b29fa95..8660b85f 100644 --- a/lib/domain/libimagtimetrack/Cargo.toml +++ b/lib/domain/libimagtimetrack/Cargo.toml @@ -20,6 +20,7 @@ toml = "0.4" toml-query = "0.3" lazy_static = "0.2" is-match = "0.1" +error-chain = "0.10" libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/domain/libimagtimetrack/src/error.rs b/lib/domain/libimagtimetrack/src/error.rs index 3ac4a11a..bb5885ae 100644 --- a/lib/domain/libimagtimetrack/src/error.rs +++ b/lib/domain/libimagtimetrack/src/error.rs @@ -17,23 +17,48 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(TimeTrackError, TimeTrackErrorKind, - StoreReadError => "Store read error", - StoreWriteError => "Store write error", +error_chain! { + types { + TimeTrackError, TimeTrackErrorKind, ResultExt, Result; + } - StoreIdError => "Error while handling StoreId", + errors { + StoreReadError { + description("Error while writing Store") + display("Error while writing Store") + } - TagFormat => "Tag has invalid format", + StoreWriteError { + description("Error while reading Store") + display("Error while reading Store") + } - HeaderReadError => "Error writing header", - HeaderWriteError => "Error writing header", - HeaderFieldTypeError => "Type error in header", - DateTimeParserError => "Error while parsing DateTime" - ); -); + StoreIdError { + description("Error while handling StoreId") + display("Error while handling StoreId") + } -pub use self::error::TimeTrackError; -pub use self::error::TimeTrackErrorKind; -pub use self::error::MapErrInto; + TagFormat { + description("Tag has invalid format") + display("Tag has invalid format") + } + + HeaderReadError { + description("Error writing header") + display("Error writing header") + } + HeaderWriteError { + description("Error writing header") + display("Error writing header") + } + HeaderFieldTypeError { + description("Type error in header") + display("Type error in header") + } + DateTimeParserError { + description("Error while parsing DateTime") + display("Error while parsing DateTime") + } + } +} diff --git a/lib/domain/libimagtimetrack/src/iter/create.rs b/lib/domain/libimagtimetrack/src/iter/create.rs index 0c471aa8..03047c76 100644 --- a/lib/domain/libimagtimetrack/src/iter/create.rs +++ b/lib/domain/libimagtimetrack/src/iter/create.rs @@ -24,7 +24,7 @@ use chrono::naive::NaiveDateTime as NDT; use constants::*; use error::TimeTrackError as TTE; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; +use error::ResultExt; use iter::storeid::TagStoreIdIter; use iter::setendtime::SetEndTimeIter; @@ -61,12 +61,12 @@ impl<'a> Iterator for CreateTimeTrackIter<'a> res.and_then(|(id, starttime)| { self.store .create(id) - .map_err_into(TTEK::StoreWriteError) + .chain_err(|| TTEK::StoreWriteError) .and_then(|mut entry| { let v = Value::String(starttime.format(DATE_TIME_FORMAT).to_string()); entry.get_header_mut() .insert(DATE_TIME_START_HEADER_PATH, v) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| entry) }) }) diff --git a/lib/domain/libimagtimetrack/src/iter/get.rs b/lib/domain/libimagtimetrack/src/iter/get.rs index 62e0a85d..526c1c97 100644 --- a/lib/domain/libimagtimetrack/src/iter/get.rs +++ b/lib/domain/libimagtimetrack/src/iter/get.rs @@ -19,12 +19,11 @@ use error::TimeTrackError as TTE; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; +use error::ResultExt; use libimagstore::store::FileLockEntry; use libimagstore::store::Store; use libimagstore::storeid::StoreIdIterator; -use libimagerror::into::IntoError; pub struct GetTimeTrackIter<'a>{ inner: StoreIdIterator, @@ -46,8 +45,8 @@ impl<'a> Iterator for GetTimeTrackIter<'a> { fn next(&mut self) -> Option { self.inner.next().map(|sid| { - match self.store.get(sid).map_err_into(TTEK::StoreReadError) { - Ok(None) => Err(TTEK::StoreReadError.into_error()), + match self.store.get(sid).chain_err(|| TTEK::StoreReadError) { + Ok(None) => Err(TTE::from_kind(TTEK::StoreReadError)), Ok(Some(s)) => Ok(s), Err(e) => Err(e) } diff --git a/lib/domain/libimagtimetrack/src/iter/setendtime.rs b/lib/domain/libimagtimetrack/src/iter/setendtime.rs index 89eb382b..778877b0 100644 --- a/lib/domain/libimagtimetrack/src/iter/setendtime.rs +++ b/lib/domain/libimagtimetrack/src/iter/setendtime.rs @@ -24,7 +24,7 @@ use chrono::naive::NaiveDateTime as NDT; use constants::*; use error::TimeTrackError as TTE; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; +use error::ResultExt; use iter::create::CreateTimeTrackIter; use libimagstore::store::FileLockEntry; @@ -55,7 +55,7 @@ impl<'a> Iterator for SetEndTimeIter<'a> { let v = Value::String(self.datetime.format(DATE_TIME_FORMAT).to_string()); fle.get_header_mut() .insert(DATE_TIME_END_HEADER_PATH, v) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| fle) }) }) diff --git a/lib/domain/libimagtimetrack/src/iter/storeid.rs b/lib/domain/libimagtimetrack/src/iter/storeid.rs index a3071908..0a68e92c 100644 --- a/lib/domain/libimagtimetrack/src/iter/storeid.rs +++ b/lib/domain/libimagtimetrack/src/iter/storeid.rs @@ -22,7 +22,7 @@ use chrono::naive::NaiveDateTime as NDT; use constants::*; use error::TimeTrackError; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; +use error::ResultExt; use iter::tag::TagIter; use iter::create::CreateTimeTrackIter; @@ -64,7 +64,7 @@ impl Iterator for TagStoreIdIter { let id_str = format!("{}-{}", dt, tag.as_str()); ModuleEntryPath::new(id_str) .into_storeid() - .map_err_into(TTEK::StoreIdError) + .chain_err(|| TTEK::StoreIdError) .map(|id| (id, self.datetime.clone())) }) }) diff --git a/lib/domain/libimagtimetrack/src/iter/tag.rs b/lib/domain/libimagtimetrack/src/iter/tag.rs index da006d8b..1fa21027 100644 --- a/lib/domain/libimagtimetrack/src/iter/tag.rs +++ b/lib/domain/libimagtimetrack/src/iter/tag.rs @@ -21,11 +21,11 @@ use chrono::naive::NaiveDateTime as NDT; use error::TimeTrackError; use error::TimeTrackErrorKind as TTEK; +use error::TimeTrackError as TTE; use tag::TimeTrackingTag as TTT; use iter::storeid::TagStoreIdIter; use libimagentrytag::tag::is_tag_str; -use libimagerror::into::IntoError; pub struct TagIter(Box>); @@ -48,7 +48,7 @@ impl Iterator for TagIter { .map(|t| if is_tag_str(&t).is_ok() { Ok(TTT::from(t)) } else { - Err(TTEK::TagFormat.into_error()) + Err(TTE::from_kind(TTEK::TagFormat)) }) } } diff --git a/lib/domain/libimagtimetrack/src/lib.rs b/lib/domain/libimagtimetrack/src/lib.rs index 0e92d2e8..cabe0ef2 100644 --- a/lib/domain/libimagtimetrack/src/lib.rs +++ b/lib/domain/libimagtimetrack/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -41,20 +43,19 @@ extern crate toml_query; extern crate lazy_static; #[macro_use] extern crate is_match; +#[macro_use] extern crate error_chain; -#[macro_use] -extern crate libimagerror; #[macro_use] extern crate libimagstore; extern crate libimagentrydatetime; extern crate libimagentrytag; +extern crate libimagerror; mod constants; pub mod error; pub mod timetracking; pub mod timetrackingstore; pub mod iter; -pub mod result; pub mod tag; module_entry_path_mod!("timetrack"); diff --git a/lib/domain/libimagtimetrack/src/result.rs b/lib/domain/libimagtimetrack/src/result.rs deleted file mode 100644 index 8ea8173f..00000000 --- a/lib/domain/libimagtimetrack/src/result.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::TimeTrackError; - -pub type Result = RResult; - - diff --git a/lib/domain/libimagtimetrack/src/timetracking.rs b/lib/domain/libimagtimetrack/src/timetracking.rs index ba40ac65..7c3bf11d 100644 --- a/lib/domain/libimagtimetrack/src/timetracking.rs +++ b/lib/domain/libimagtimetrack/src/timetracking.rs @@ -27,12 +27,12 @@ use chrono::naive::NaiveDateTime; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use tag::TimeTrackingTag as TTT; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; -use result::Result; +use error::TimeTrackError as TTE; +use error::ResultExt; +use error::Result; use constants::*; use toml::Value; @@ -65,11 +65,11 @@ impl TimeTracking for Entry { fn get_timetrack_tag(&self) -> Result { self.get_header() .read(DATE_TIME_TAG_HEADER_PATH) - .map_err_into(TTEK::HeaderReadError) + .chain_err(|| TTEK::HeaderReadError) .and_then(|value| match value { Some(&Value::String(ref s)) => Ok(s.clone().into()), - Some(_) => Err(TTEK::HeaderFieldTypeError.into_error()), - _ => Err(TTEK::HeaderReadError.into_error()) + Some(_) => Err(TTE::from_kind(TTEK::HeaderFieldTypeError)), + _ => Err(TTE::from_kind(TTEK::HeaderReadError)) }) } @@ -78,21 +78,21 @@ impl TimeTracking for Entry { self.get_header_mut() .insert(DATE_TIME_START_HEADER_PATH, Value::String(s)) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| ()) } fn get_start_datetime(&self) -> Result> { self.get_header() .read(DATE_TIME_START_HEADER_PATH) - .map_err_into(TTEK::HeaderReadError) + .chain_err(|| TTEK::HeaderReadError) .and_then(header_value_to_dt) } fn delete_start_datetime(&mut self) -> Result<()> { self.get_header_mut() .delete(DATE_TIME_START_HEADER_PATH) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| ()) } @@ -101,21 +101,21 @@ impl TimeTracking for Entry { self.get_header_mut() .insert(DATE_TIME_END_HEADER_PATH, Value::String(s)) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| ()) } fn get_end_datetime(&self) -> Result> { self.get_header() .read(DATE_TIME_END_HEADER_PATH) - .map_err_into(TTEK::HeaderReadError) + .chain_err(|| TTEK::HeaderReadError) .and_then(header_value_to_dt) } fn delete_end_datetime(&mut self) -> Result<()> { self.get_header_mut() .delete(DATE_TIME_END_HEADER_PATH) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| ()) } @@ -141,11 +141,11 @@ fn header_value_to_dt(val: Option<&Value>) -> Result> { match val { Some(&Value::String(ref s)) => { NaiveDateTime::parse_from_str(s, DATE_TIME_FORMAT) - .map_err_into(TTEK::DateTimeParserError) + .chain_err(|| TTEK::DateTimeParserError) .map(Some) }, - Some(_) => Err(TTEK::HeaderFieldTypeError.into_error()), + Some(_) => Err(TTE::from_kind(TTEK::HeaderFieldTypeError)), None => Ok(None), } } diff --git a/lib/domain/libimagtimetrack/src/timetrackingstore.rs b/lib/domain/libimagtimetrack/src/timetrackingstore.rs index 94e993ac..669862b5 100644 --- a/lib/domain/libimagtimetrack/src/timetrackingstore.rs +++ b/lib/domain/libimagtimetrack/src/timetrackingstore.rs @@ -30,10 +30,10 @@ use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagentrydatetime::datepath::compiler::DatePathCompiler; -use result::Result; +use error::Result; use constants::*; use error::TimeTrackErrorKind as TTEK; -use error::MapErrInto; +use error::ResultExt; use iter::get::GetTimeTrackIter; use tag::TimeTrackingTag as TTT; @@ -71,24 +71,24 @@ impl<'a> TimeTrackStore<'a> for Store { use std::path::PathBuf; COMPILER.compile(CRATE_NAME, start) - .map_err_into(TTEK::StoreIdError) + .chain_err(|| TTEK::StoreIdError) .map(|mut id| { id.local_push(PathBuf::from(ts.as_str())); id }) - .and_then(|id| self.create(id).map_err_into(TTEK::StoreWriteError)) + .and_then(|id| self.create(id).chain_err(|| TTEK::StoreWriteError)) .and_then(|mut fle| { let v = Value::String(ts.as_str().to_owned()); fle.get_header_mut() .insert(DATE_TIME_TAG_HEADER_PATH, v) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| fle) }) .and_then(|mut fle| { let v = Value::String(start.format(DATE_TIME_FORMAT).to_string()); fle.get_header_mut() .insert(DATE_TIME_START_HEADER_PATH, v) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| fle) }) } @@ -99,14 +99,14 @@ impl<'a> TimeTrackStore<'a> for Store { let v = Value::String(end.format(DATE_TIME_FORMAT).to_string()); fle.get_header_mut() .insert(DATE_TIME_END_HEADER_PATH, v) - .map_err_into(TTEK::HeaderWriteError) + .chain_err(|| TTEK::HeaderWriteError) .map(|_| fle) }) } fn get_timetrackings(&'a self) -> Result> { self.retrieve_for_module(CRATE_NAME) - .map_err_into(TTEK::StoreReadError) + .chain_err(|| TTEK::StoreReadError) .map(|iter| GetTimeTrackIter::new(iter, self)) } diff --git a/lib/domain/libimagtodo/Cargo.toml b/lib/domain/libimagtodo/Cargo.toml index 656b4d5f..a1f6e435 100644 --- a/lib/domain/libimagtodo/Cargo.toml +++ b/lib/domain/libimagtodo/Cargo.toml @@ -20,6 +20,7 @@ toml = "0.4.*" toml-query = "0.3.*" log = "0.3" serde_json = "0.8" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/domain/libimagtodo/src/error.rs b/lib/domain/libimagtodo/src/error.rs index de39049f..a65bba8a 100644 --- a/lib/domain/libimagtodo/src/error.rs +++ b/lib/domain/libimagtodo/src/error.rs @@ -17,20 +17,51 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(TodoError, TodoErrorKind, - ConversionError => "Conversion Error", - StoreError => "Store Error", - StoreIdError => "Store Id handling error", - ImportError => "Error importing", - UTF8Error => "Encountered non-UTF8 characters while reading input", - HeaderFieldMissing => "Header field missing", - HeaderTypeError => "Header field type error", - UuidParserError => "Uuid parser error" - ); -); +error_chain! { + types { + TodoError, TodoErrorKind, ResultExt, Result; + } -pub use self::error::TodoError; -pub use self::error::TodoErrorKind; -pub use self::error::MapErrInto; + errors { + ConversionError { + description("Conversion Error") + display("Conversion Error") + } + + StoreError { + description("Store Error") + display("Store Error") + } + + StoreIdError { + description("Store Id handling error") + display("Store Id handling error") + } + + ImportError { + description("Error importing") + display("Error importing") + } + + UTF8Error { + description("Encountered non-UTF8 characters while reading input") + display("Encountered non-UTF8 characters while reading input") + } + + HeaderFieldMissing { + description("Header field missing") + display("Header field missing") + } + + HeaderTypeError { + description("Header field type error") + display("Header field type error") + } + + UuidParserError { + description("Uuid parser error") + display("Uuid parser error") + } + } +} diff --git a/lib/domain/libimagtodo/src/lib.rs b/lib/domain/libimagtodo/src/lib.rs index 6c0c482e..2da11610 100644 --- a/lib/domain/libimagtodo/src/lib.rs +++ b/lib/domain/libimagtodo/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -38,15 +40,15 @@ extern crate toml; extern crate toml_query; #[macro_use] extern crate log; extern crate serde_json; +#[macro_use] extern crate error_chain; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate task_hookrs; module_entry_path_mod!("todo"); pub mod error; -pub mod result; pub mod task; pub mod taskstore; diff --git a/lib/domain/libimagtodo/src/result.rs b/lib/domain/libimagtodo/src/result.rs deleted file mode 100644 index 7962851c..00000000 --- a/lib/domain/libimagtodo/src/result.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 error::TodoError; - -use std::result::Result as RResult; - -pub type Result = RResult; diff --git a/lib/domain/libimagtodo/src/task.rs b/lib/domain/libimagtodo/src/task.rs index b2b70696..039bdbfb 100644 --- a/lib/domain/libimagtodo/src/task.rs +++ b/lib/domain/libimagtodo/src/task.rs @@ -17,12 +17,12 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use error::TodoError as TE; use error::TodoErrorKind as TEK; -use error::MapErrInto; -use result::Result; +use error::ResultExt; +use error::Result; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use uuid::Uuid; use toml::Value; @@ -36,11 +36,11 @@ impl Task for Entry { fn get_uuid(&self) -> Result { match self.get_header().read("todo.uuid") { Ok(Some(&Value::String(ref uuid))) => { - Uuid::parse_str(uuid).map_err_into(TEK::UuidParserError) + Uuid::parse_str(uuid).chain_err(|| TEK::UuidParserError) }, - Ok(Some(_)) => Err(TEK::HeaderTypeError.into_error()), - Ok(None) => Err(TEK::HeaderFieldMissing.into_error()), - Err(e) => Err(e).map_err_into(TEK::StoreError), + Ok(Some(_)) => Err(TE::from_kind(TEK::HeaderTypeError)), + Ok(None) => Err(TE::from_kind(TEK::HeaderFieldMissing)), + Err(e) => Err(e).chain_err(|| TEK::StoreError), } } } diff --git a/lib/domain/libimagtodo/src/taskstore.rs b/lib/domain/libimagtodo/src/taskstore.rs index 8e8cd9a5..4a1dc2fe 100644 --- a/lib/domain/libimagtodo/src/taskstore.rs +++ b/lib/domain/libimagtodo/src/taskstore.rs @@ -31,8 +31,10 @@ use libimagstore::store::{FileLockEntry, Store}; use libimagstore::storeid::{IntoStoreId, StoreIdIterator}; use module_path::ModuleEntryPath; -use error::{TodoErrorKind as TEK, MapErrInto}; -use result::Result; +use error::TodoErrorKind as TEK; +use error::TodoError as TE; +use error::Result; +use error::ResultExt; /// Task struct containing a `FileLockEntry` pub trait TaskStore<'a> { @@ -52,9 +54,9 @@ impl<'a> TaskStore<'a> for Store { fn import_task_from_reader(&'a self, mut r: R) -> Result<(FileLockEntry<'a>, String, Uuid)> { let mut line = String::new(); - try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); + try!(r.read_line(&mut line).map_err(|_| TE::from_kind(TEK::UTF8Error))); import_task(&line.as_str()) - .map_err_into(TEK::ImportError) + .map_err(|_| TE::from_kind(TEK::ImportError)) .and_then(|t| { let uuid = t.uuid().clone(); self.new_from_twtask(t).map(|t| (t, line, uuid)) @@ -72,7 +74,7 @@ impl<'a> TaskStore<'a> for Store { /// fn get_task_from_import(&'a self, mut r: R) -> Result, String>> { let mut line = String::new(); - try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); + try!(r.read_line(&mut line).chain_err(|| TEK::UTF8Error)); self.get_task_from_string(line) } @@ -82,7 +84,7 @@ impl<'a> TaskStore<'a> for Store { /// For an explanation on the return values see `Task::get_from_import()`. fn get_task_from_string(&'a self, s: String) -> Result, String>> { import_task(s.as_str()) - .map_err_into(TEK::ImportError) + .map_err(|_| TE::from_kind(TEK::ImportError)) .map(|t| t.uuid().clone()) .and_then(|uuid| self.get_task_from_uuid(uuid)) .and_then(|o| match o { @@ -98,14 +100,14 @@ impl<'a> TaskStore<'a> for Store { ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() .and_then(|store_id| self.get(store_id)) - .map_err_into(TEK::StoreError) + .chain_err(|| TEK::StoreError) } /// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to /// implicitely create the task if it does not exist. fn retrieve_task_from_import(&'a self, mut r: R) -> Result> { let mut line = String::new(); - try!(r.read_line(&mut line).map_err_into(TEK::UTF8Error)); + try!(r.read_line(&mut line).chain_err(|| TEK::UTF8Error)); self.retrieve_task_from_string(line) } @@ -116,7 +118,7 @@ impl<'a> TaskStore<'a> for Store { .and_then(|opt| match opt { Ok(task) => Ok(task), Err(string) => import_task(string.as_str()) - .map_err_into(TEK::ImportError) + .map_err(|_| TE::from_kind(TEK::ImportError)) .and_then(|t| self.new_from_twtask(t)), }) } @@ -133,7 +135,7 @@ impl<'a> TaskStore<'a> for Store { // task before the change, and the second one after // the change. The (maybe modified) second one is // expected by taskwarrior. - match serde_to_string(&ttask).map_err_into(TEK::ImportError) { + match serde_to_string(&ttask).chain_err(|| TEK::ImportError) { // use println!() here, as we talk with TW Ok(val) => println!("{}", val), Err(e) => return Err(e), @@ -152,7 +154,7 @@ impl<'a> TaskStore<'a> for Store { } } // end if c % 2 }, - Err(e) => return Err(e).map_err_into(TEK::ImportError), + Err(e) => return Err(TE::from_kind(TEK::ImportError)), } } Ok(()) @@ -162,12 +164,12 @@ impl<'a> TaskStore<'a> for Store { ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() .and_then(|id| self.delete(id)) - .map_err_into(TEK::StoreError) + .chain_err(|| TEK::StoreError) } fn all_tasks(&self) -> Result { self.retrieve_for_module("todo/taskwarrior") - .map_err_into(TEK::StoreError) + .chain_err(|| TEK::StoreError) } fn new_from_twtask(&'a self, task: TTask) -> Result> { @@ -177,21 +179,21 @@ impl<'a> TaskStore<'a> for Store { let uuid = task.uuid(); ModuleEntryPath::new(format!("taskwarrior/{}", uuid)) .into_storeid() - .map_err_into(TEK::StoreIdError) + .chain_err(|| TEK::StoreIdError) .and_then(|id| { self.retrieve(id) - .map_err_into(TEK::StoreError) + .chain_err(|| TEK::StoreError) .and_then(|mut fle| { { let hdr = fle.get_header_mut(); - if try!(hdr.read("todo").map_err_into(TEK::StoreError)).is_none() { + if try!(hdr.read("todo").chain_err(|| TEK::StoreError)).is_none() { try!(hdr .set("todo", Value::Table(BTreeMap::new())) - .map_err_into(TEK::StoreError)); + .chain_err(|| TEK::StoreError)); } try!(hdr.set("todo.uuid", Value::String(format!("{}",uuid))) - .map_err_into(TEK::StoreError)); + .chain_err(|| TEK::StoreError)); } // If none of the errors above have returned the function, everything is fine diff --git a/lib/entry/libimagentryannotation/Cargo.toml b/lib/entry/libimagentryannotation/Cargo.toml index d4720dc4..ec992855 100644 --- a/lib/entry/libimagentryannotation/Cargo.toml +++ b/lib/entry/libimagentryannotation/Cargo.toml @@ -13,6 +13,7 @@ license = "LGPL-2.1" lazy_static = "0.1.15" toml = "^0.4" toml-query = "0.3.0" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentryannotation/src/annotateable.rs b/lib/entry/libimagentryannotation/src/annotateable.rs index 4fb3589a..d51380cc 100644 --- a/lib/entry/libimagentryannotation/src/annotateable.rs +++ b/lib/entry/libimagentryannotation/src/annotateable.rs @@ -25,14 +25,14 @@ use libimagstore::store::Entry; use libimagstore::store::FileLockEntry; use libimagstore::store::Store; use libimagentrylink::internal::InternalLinker; -use libimagerror::into::IntoError; use toml_query::read::TomlValueReadExt; use toml_query::insert::TomlValueInsertExt; -use result::Result; +use error::Result; use error::AnnotationErrorKind as AEK; -use error::MapErrInto; +use error::AnnotationError as AE; +use error::ResultExt; pub trait Annotateable { @@ -51,16 +51,16 @@ impl Annotateable for Entry { fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result> { store.retrieve(PathBuf::from(ann_name)) - .map_err_into(AEK::StoreWriteError) + .chain_err(|| AEK::StoreWriteError) .and_then(|mut anno| { anno.get_header_mut() .insert("annotation.is_annotation", Value::Boolean(true)) - .map_err_into(AEK::HeaderWriteError) + .chain_err(|| AEK::HeaderWriteError) .map(|_| anno) }) .and_then(|mut anno| { anno.add_internal_link(self) - .map_err_into(AEK::LinkingError) + .chain_err(|| AEK::LinkingError) .map(|_| anno) }) } @@ -68,11 +68,11 @@ impl Annotateable for Entry { fn is_annotation(&self) -> Result { self.get_header() .read("annotation.is_annotation") - .map_err_into(AEK::StoreReadError) + .chain_err(|| AEK::StoreReadError) .and_then(|res| match res { Some(&Value::Boolean(b)) => Ok(b), None => Ok(false), - _ => Err(AEK::HeaderTypeError.into_error()), + _ => Err(AE::from_kind(AEK::HeaderTypeError)), }) } diff --git a/lib/entry/libimagentryannotation/src/annotation_fetcher.rs b/lib/entry/libimagentryannotation/src/annotation_fetcher.rs index 58b27170..49890550 100644 --- a/lib/entry/libimagentryannotation/src/annotation_fetcher.rs +++ b/lib/entry/libimagentryannotation/src/annotation_fetcher.rs @@ -24,9 +24,9 @@ use libimagnotes::note::Note; use libimagnotes::note::NoteIterator; use libimagstore::storeid::StoreIdIterator; -use result::Result; +use error::Result; use error::AnnotationErrorKind as AEK; -use error::MapErrInto; +use error::ResultExt; use self::iter::*; @@ -45,7 +45,7 @@ impl<'a> AnnotationFetcher<'a> for Store { fn all_annotations(&'a self) -> Result> { Note::all_notes(self) .map(|iter| AnnotationIter::new(iter)) - .map_err_into(AEK::StoreReadError) + .chain_err(|| AEK::StoreReadError) } /// Get all annotations (in an iterator) for an entry @@ -57,7 +57,7 @@ impl<'a> AnnotationFetcher<'a> for Store { /// entry, but should normally be not that heavy. fn annotations_for_entry(&'a self, entry: &Entry) -> Result> { entry.get_internal_links() - .map_err_into(AEK::StoreReadError) + .chain_err(|| AEK::StoreReadError) .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone())))) .map(|iter| NoteIterator::new(self, iter)) .map(|iter| AnnotationIter::new(iter)) @@ -70,13 +70,13 @@ pub mod iter { use toml_query::read::TomlValueReadExt; - use libimagerror::into::IntoError; use libimagnotes::note::Note; use libimagnotes::note::NoteIterator; - use result::Result; + use error::Result; use error::AnnotationErrorKind as AEK; - use error::MapErrInto; + use error::AnnotationError as AE; + use error::ResultExt; #[derive(Debug)] pub struct AnnotationIter<'a>(NoteIterator<'a>); @@ -99,11 +99,11 @@ pub mod iter { match note.get_header().read("annotation.is_annotation") { Ok(None) => continue, // not an annotation Ok(Some(&Value::Boolean(true))) => return Some(Ok(note)), - Ok(Some(_)) => return Some(Err(AEK::HeaderTypeError.into_error())), - Err(e) => return Some(Err(e).map_err_into(AEK::HeaderReadError)), + Ok(Some(_)) => return Some(Err(AE::from_kind(AEK::HeaderTypeError))), + Err(e) => return Some(Err(e).chain_err(|| AEK::HeaderReadError)), } }, - Some(Err(e)) => return Some(Err(e).map_err_into(AEK::StoreReadError)), + Some(Err(e)) => return Some(Err(e).chain_err(|| AEK::StoreReadError)), None => return None, // iterator consumed } } diff --git a/lib/entry/libimagentryannotation/src/error.rs b/lib/entry/libimagentryannotation/src/error.rs index 25fc0048..8a349b71 100644 --- a/lib/entry/libimagentryannotation/src/error.rs +++ b/lib/entry/libimagentryannotation/src/error.rs @@ -17,19 +17,42 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(AnnotationError, AnnotationErrorKind, - StoreReadError => "Store read error", - StoreWriteError => "Store write error", +error_chain! { + types { + AnnotationError, AnnotationErrorKind, ResultExt, Result; + } - LinkingError => "Error while linking", - HeaderWriteError => "Couldn't write Header for annotation", - HeaderReadError => "Couldn't read Header of Entry", - HeaderTypeError => "Header field has unexpected type" - ); -); + errors { + StoreReadError { + description("Store read error") + display("Store read error") + } -pub use self::error::AnnotationError; -pub use self::error::AnnotationErrorKind; -pub use self::error::MapErrInto; + StoreWriteError { + description("Store write error") + display("Store write error") + } + + LinkingError { + description("Error while linking") + display("Error while linking") + } + + HeaderWriteError { + description("Couldn't write Header for annotation") + display("Couldn't write Header for annotation") + } + + HeaderReadError { + description("Couldn't read Header of Entry") + display("Couldn't read Header of Entry") + } + + HeaderTypeError { + description("Header field has unexpected type") + display("Header field has unexpected type") + } + + } +} diff --git a/lib/entry/libimagentryannotation/src/lib.rs b/lib/entry/libimagentryannotation/src/lib.rs index 5b784de4..bd1e9ed5 100644 --- a/lib/entry/libimagentryannotation/src/lib.rs +++ b/lib/entry/libimagentryannotation/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -35,8 +37,9 @@ extern crate toml; extern crate toml_query; +#[macro_use] extern crate error_chain; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagstore; extern crate libimagentrylink; extern crate libimagnotes; @@ -44,5 +47,4 @@ extern crate libimagnotes; pub mod annotateable; pub mod annotation_fetcher; pub mod error; -pub mod result; diff --git a/lib/entry/libimagentryannotation/src/result.rs b/lib/entry/libimagentryannotation/src/result.rs deleted file mode 100644 index 292fc0e5..00000000 --- a/lib/entry/libimagentryannotation/src/result.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::AnnotationError; - -pub type Result = RResult; - - diff --git a/lib/entry/libimagentrycategory/Cargo.toml b/lib/entry/libimagentrycategory/Cargo.toml index e7e54feb..428dcd48 100644 --- a/lib/entry/libimagentrycategory/Cargo.toml +++ b/lib/entry/libimagentrycategory/Cargo.toml @@ -18,6 +18,7 @@ log = "0.3" toml = "0.4" toml-query = "0.3" is-match = "0.1" +error-chain = "0.10" libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index 1e77495e..f2a2b2cf 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -23,11 +23,11 @@ use toml_query::error::ErrorKind as TQEK; use toml::Value; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use error::CategoryErrorKind as CEK; -use error::MapErrInto; -use result::Result; +use error::CategoryError as CE; +use error::ResultExt; +use error::Result; use register::CategoryRegister; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] @@ -64,7 +64,7 @@ impl EntryCategory for Entry { fn set_category(&mut self, s: Category) -> Result<()> { self.get_header_mut() .insert(&String::from("category.value"), Value::String(s.into())) - .map_err_into(CEK::HeaderWriteError) + .chain_err(|| CEK::HeaderWriteError) .map(|_| ()) } @@ -76,7 +76,7 @@ impl EntryCategory for Entry { .and_then(|bl| if bl { self.set_category(s) } else { - Err(CEK::CategoryDoesNotExist.into_error()) + Err(CE::from_kind(CEK::CategoryDoesNotExist)) }) } @@ -86,17 +86,17 @@ impl EntryCategory for Entry { &TQEK::IdentifierNotFoundInDocument(_) => Ok(None), _ => Err(res), } - .map_err_into(CEK::HeaderReadError), + .chain_err(|| CEK::HeaderReadError), Ok(Some(&Value::String(ref s))) => Ok(Some(s.clone().into())), - Ok(None) => Err(CEK::StoreReadError.into_error()).map_err_into(CEK::HeaderReadError), - Ok(_) => Err(CEK::TypeError.into_error()).map_err_into(CEK::HeaderReadError), + Ok(None) => Err(CE::from_kind(CEK::StoreReadError)).chain_err(|| CEK::HeaderReadError), + Ok(_) => Err(CE::from_kind(CEK::TypeError)).chain_err(|| CEK::HeaderReadError), } } fn has_category(&self) -> Result { self.get_header().read(&String::from("category.value")) - .map_err_into(CEK::HeaderReadError) + .chain_err(|| CEK::HeaderReadError) .map(|e| e.is_some()) } diff --git a/lib/entry/libimagentrycategory/src/error.rs b/lib/entry/libimagentrycategory/src/error.rs index 72824337..bd3da1a0 100644 --- a/lib/entry/libimagentrycategory/src/error.rs +++ b/lib/entry/libimagentrycategory/src/error.rs @@ -17,20 +17,46 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(CategoryError, CategoryErrorKind, - StoreReadError => "Store Read error", - StoreWriteError => "Store Write error", - StoreIdHandlingError => "StoreId handling error", - HeaderReadError => "Header read error", - HeaderWriteError => "Header write error", - TypeError => "Found wrong type in header", +error_chain! { + types { + CategoryError, CategoryErrorKind, ResultExt, Result; + } - CategoryDoesNotExist => "Category does not exist" - ); -); + errors { + StoreReadError { + description("Store Read error") + display("Store Read error") + } -pub use self::error::CategoryError; -pub use self::error::CategoryErrorKind; -pub use self::error::MapErrInto; + StoreWriteError { + description("Store Write error") + display("Store Write error") + } + + StoreIdHandlingError { + description("StoreId handling error") + display("StoreId handling error") + } + + HeaderReadError { + description("Header read error") + display("Header read error") + } + + HeaderWriteError { + description("Header write error") + display("Header write error") + } + + CategoryDoesNotExist { + description("Category does not exist") + display("Category does not exist") + } + + TypeError { + description("Type Error") + display("Type Error") + } + } +} diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index c2b4daae..06e13f9c 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -39,8 +41,8 @@ extern crate toml; extern crate is_match; #[macro_use] extern crate log; +#[macro_use] extern crate error_chain; -#[macro_use] extern crate libimagerror; #[macro_use] extern crate libimagstore; @@ -48,7 +50,6 @@ extern crate libimagstore; pub mod category; pub mod error; pub mod register; -pub mod result; module_entry_path_mod!("category"); diff --git a/lib/entry/libimagentrycategory/src/register.rs b/lib/entry/libimagentrycategory/src/register.rs index e8853631..ad4d5b73 100644 --- a/lib/entry/libimagentrycategory/src/register.rs +++ b/lib/entry/libimagentrycategory/src/register.rs @@ -27,12 +27,12 @@ use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreIdIterator; -use libimagerror::into::IntoError; use category::Category; use error::CategoryErrorKind as CEK; -use error::MapErrInto; -use result::Result; +use error::CategoryError as CE; +use error::ResultExt; +use error::Result; pub const CATEGORY_REGISTER_NAME_FIELD_PATH : &'static str = "category.register.name"; @@ -81,13 +81,13 @@ impl CategoryRegister for Store { warn!("Setting category header replaced existing value: {:?}", opt); }) .map(|_| true) - .map_err_into(CEK::HeaderWriteError) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::HeaderWriteError) + .chain_err(|| CEK::StoreWriteError) } - Err(store_error) => if is_match!(store_error.err_type(), SEK::EntryAlreadyExists) { + Err(store_error) => if is_match!(store_error.kind(), &SEK::EntryAlreadyExists) { Ok(false) } else { - Err(store_error).map_err_into(CEK::StoreWriteError) + Err(store_error).chain_err(|| CEK::StoreWriteError) } } } @@ -96,13 +96,13 @@ impl CategoryRegister for Store { fn delete_category(&self, name: &str) -> Result<()> { let sid = try!(mk_category_storeid(self.path().clone(), name)); - self.delete(sid).map_err_into(CEK::StoreWriteError) + self.delete(sid).chain_err(|| CEK::StoreWriteError) } /// Get all category names fn all_category_names(&self) -> Result { self.retrieve_for_module("category") - .map_err_into(CEK::StoreReadError) + .chain_err(|| CEK::StoreReadError) .map(|iter| CategoryNameIter::new(self, iter)) } @@ -114,7 +114,7 @@ impl CategoryRegister for Store { let sid = try!(mk_category_storeid(self.path().clone(), name)); self.get(sid) - .map_err_into(CEK::StoreWriteError) + .chain_err(|| CEK::StoreWriteError) } } @@ -212,26 +212,26 @@ fn mk_category_storeid(base: PathBuf, s: &str) -> Result { ::module_path::ModuleEntryPath::new(s) .into_storeid() .map(|id| id.with_base(base)) - .map_err_into(CEK::StoreIdHandlingError) + .chain_err(|| CEK::StoreIdHandlingError) } #[inline] fn represents_category(store: &Store, sid: StoreId, name: &str) -> Result { sid.exists() - .map_err_into(CEK::StoreIdHandlingError) + .chain_err(|| CEK::StoreIdHandlingError) .and_then(|bl| { if bl { store.get(sid) - .map_err_into(CEK::StoreReadError) + .chain_err(|| CEK::StoreReadError) .and_then(|fle| { if let Some(fle) = fle { match fle.get_header() .read(&String::from(CATEGORY_REGISTER_NAME_FIELD_PATH)) - .map_err_into(CEK::HeaderReadError) + .chain_err(|| CEK::HeaderReadError) { Ok(Some(&Value::String(ref s))) => Ok(s == name), - Ok(_) => Err(CEK::TypeError.into_error()), - Err(e) => Err(e).map_err_into(CEK::HeaderReadError), + Ok(_) => Err(CE::from_kind(CEK::TypeError)), + Err(e) => Err(e).chain_err(|| CEK::HeaderReadError), } } else { Ok(false) @@ -277,12 +277,12 @@ impl<'a> Iterator for CategoryNameIter<'a> { .map(|sid| { self.0 .get(sid) - .map_err_into(CEK::StoreReadError) - .and_then(|fle| fle.ok_or(CEK::StoreReadError.into_error())) + .chain_err(|| CEK::StoreReadError) + .and_then(|fle| fle.ok_or(CE::from_kind(CEK::StoreReadError))) .and_then(|fle| match fle.get_header().read(&query) { Ok(Some(&Value::String(ref s))) => Ok(Category::from(s.clone())), - Ok(_) => Err(CEK::TypeError.into_error()), - Err(e) => Err(e).map_err_into(CEK::HeaderReadError), + Ok(_) => Err(CE::from_kind(CEK::TypeError)), + Err(e) => Err(e).chain_err(|| CEK::HeaderReadError), }) }) } diff --git a/lib/entry/libimagentrycategory/src/result.rs b/lib/entry/libimagentrycategory/src/result.rs deleted file mode 100644 index 517d0e96..00000000 --- a/lib/entry/libimagentrycategory/src/result.rs +++ /dev/null @@ -1,26 +0,0 @@ - -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::CategoryError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrydatetime/Cargo.toml b/lib/entry/libimagentrydatetime/Cargo.toml index 15df2055..c2dc483b 100644 --- a/lib/entry/libimagentrydatetime/Cargo.toml +++ b/lib/entry/libimagentrydatetime/Cargo.toml @@ -18,6 +18,7 @@ chrono = "0.4" toml-query = "0.3" lazy_static = "0.2" toml = "0.4" +error-chain = "0.10" libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/entry/libimagentrydatetime/src/datepath/compiler.rs b/lib/entry/libimagentrydatetime/src/datepath/compiler.rs index 742b594a..7910db7f 100644 --- a/lib/entry/libimagentrydatetime/src/datepath/compiler.rs +++ b/lib/entry/libimagentrydatetime/src/datepath/compiler.rs @@ -27,9 +27,9 @@ use libimagstore::storeid::StoreId; use datepath::accuracy::Accuracy; use datepath::format::Format; -use datepath::result::Result; +use datepath::error::Result; use datepath::error::DatePathCompilerErrorKind as DPCEK; -use datepath::error::MapErrInto; +use datepath::error::ResultExt; pub struct DatePathCompiler { accuracy : Accuracy, @@ -122,7 +122,7 @@ impl DatePathCompiler { } StoreId::new_baseless(PathBuf::from(s)) - .map_err_into(DPCEK::StoreIdBuildFailed) + .chain_err(|| DPCEK::StoreIdBuildFailed) } } diff --git a/lib/entry/libimagentrydatetime/src/datepath/error.rs b/lib/entry/libimagentrydatetime/src/datepath/error.rs index 1a163208..94a0f723 100644 --- a/lib/entry/libimagentrydatetime/src/datepath/error.rs +++ b/lib/entry/libimagentrydatetime/src/datepath/error.rs @@ -17,14 +17,22 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -/// Error module for the DatePathCompiler type -generate_error_module! { - generate_error_types!(DatePathCompilerError, DatePathCompilerErrorKind, - UnknownDatePathCompilerError => "Unknown DatePathCompiler error", - StoreIdBuildFailed => "Failed building StoreId object" - ); -} -pub use self::error::DatePathCompilerError; -pub use self::error::DatePathCompilerErrorKind; -pub use self::error::MapErrInto; +error_chain! { + types { + DatePathCompilerError, DatePathCompilerErrorKind, ResultExt, Result; + } + + errors { + UnknownDatePathCompilerError { + description("Unknown DatePathCompiler error") + display("Unknown DatePathCompiler error") + } + + StoreIdBuildFailed { + description("Failed building StoreId object") + display("Failed building StoreId object") + } + + } +} diff --git a/lib/entry/libimagentrydatetime/src/datepath/mod.rs b/lib/entry/libimagentrydatetime/src/datepath/mod.rs index c964abf9..2fbfc1c4 100644 --- a/lib/entry/libimagentrydatetime/src/datepath/mod.rs +++ b/lib/entry/libimagentrydatetime/src/datepath/mod.rs @@ -21,6 +21,5 @@ pub mod accuracy; pub mod compiler; pub mod error; pub mod format; -pub mod result; pub mod to_store_id; diff --git a/lib/entry/libimagentrydatetime/src/datepath/result.rs b/lib/entry/libimagentrydatetime/src/datepath/result.rs deleted file mode 100644 index 2fc3350a..00000000 --- a/lib/entry/libimagentrydatetime/src/datepath/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 -// - -/// Result type for this module. -use super::error::DatePathCompilerError as DPCE; -use std::result::Result as RResult; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrydatetime/src/datepath/to_store_id.rs b/lib/entry/libimagentrydatetime/src/datepath/to_store_id.rs index c781595b..6f24d517 100644 --- a/lib/entry/libimagentrydatetime/src/datepath/to_store_id.rs +++ b/lib/entry/libimagentrydatetime/src/datepath/to_store_id.rs @@ -20,7 +20,7 @@ use chrono::naive::NaiveDateTime; use libimagstore::storeid::StoreId; -use datepath::result::Result; +use datepath::error::Result; use datepath::compiler::DatePathCompiler; // diff --git a/lib/entry/libimagentrydatetime/src/datetime.rs b/lib/entry/libimagentrydatetime/src/datetime.rs index 73c29622..06d11b07 100644 --- a/lib/entry/libimagentrydatetime/src/datetime.rs +++ b/lib/entry/libimagentrydatetime/src/datetime.rs @@ -24,11 +24,10 @@ use toml_query::read::TomlValueReadExt; use toml::Value; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use error::DateErrorKind as DEK; +use error::DateError as DE; use error::*; -use result::Result; use range::DateTimeRange; pub trait EntryDate { @@ -56,19 +55,19 @@ impl EntryDate for Entry { self.get_header_mut() .delete(&DATE_HEADER_LOCATION) .map(|_| ()) - .map_err_into(DEK::DeleteDateError) + .chain_err(|| DEK::DeleteDateError) } fn read_date(&self) -> Result { self.get_header() .read(&DATE_HEADER_LOCATION) - .map_err_into(DEK::ReadDateError) + .chain_err(|| DEK::ReadDateError) .and_then(|v| { match v { Some(&Value::String(ref s)) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - Some(_) => Err(DEK::DateHeaderFieldTypeError.into_error()), - _ => Err(DEK::ReadDateError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), + _ => Err(DE::from_kind(DEK::ReadDateError)), } }) } @@ -97,11 +96,11 @@ impl EntryDate for Entry { .map(|opt| opt.map(|stri| { match stri { Value::String(ref s) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - _ => Err(DEK::DateHeaderFieldTypeError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), } })) - .map_err_into(DEK::SetDateError) + .chain_err(|| DEK::SetDateError) } @@ -117,43 +116,43 @@ impl EntryDate for Entry { .get_header_mut() .delete(&DATE_RANGE_START_HEADER_LOCATION) .map(|_| ()) - .map_err_into(DEK::DeleteDateTimeRangeError)); + .chain_err(|| DEK::DeleteDateTimeRangeError)); self.get_header_mut() .delete(&DATE_RANGE_END_HEADER_LOCATION) .map(|_| ()) - .map_err_into(DEK::DeleteDateTimeRangeError) + .chain_err(|| DEK::DeleteDateTimeRangeError) } fn read_date_range(&self) -> Result { let start = try!(self .get_header() .read(&DATE_RANGE_START_HEADER_LOCATION) - .map_err_into(DEK::ReadDateTimeRangeError) + .chain_err(|| DEK::ReadDateTimeRangeError) .and_then(|v| { match v { Some(&Value::String(ref s)) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - Some(_) => Err(DEK::DateHeaderFieldTypeError.into_error()), - _ => Err(DEK::ReadDateError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), + _ => Err(DE::from_kind(DEK::ReadDateError)), } })); let end = try!(self .get_header() .read(&DATE_RANGE_START_HEADER_LOCATION) - .map_err_into(DEK::ReadDateTimeRangeError) + .chain_err(|| DEK::ReadDateTimeRangeError) .and_then(|v| { match v { Some(&Value::String(ref s)) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - Some(_) => Err(DEK::DateHeaderFieldTypeError.into_error()), - _ => Err(DEK::ReadDateError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + Some(_) => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), + _ => Err(DE::from_kind(DEK::ReadDateError)), } })); DateTimeRange::new(start, end) - .map_err_into(DEK::DateTimeRangeError) + .chain_err(|| DEK::DateTimeRangeError) } /// Set the date range @@ -175,11 +174,11 @@ impl EntryDate for Entry { .map(|opt| opt.map(|stri| { match stri { Value::String(ref s) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - _ => Err(DEK::DateHeaderFieldTypeError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), } })) - .map_err_into(DEK::SetDateTimeRangeError)); + .chain_err(|| DEK::SetDateTimeRangeError)); let opt_old_end = try!(self .get_header_mut() @@ -187,16 +186,16 @@ impl EntryDate for Entry { .map(|opt| opt.map(|stri| { match stri { Value::String(ref s) => s.parse::() - .map_err_into(DEK::DateTimeParsingError), - _ => Err(DEK::DateHeaderFieldTypeError.into_error()), + .chain_err(|| DEK::DateTimeParsingError), + _ => Err(DE::from_kind(DEK::DateHeaderFieldTypeError)), } })) - .map_err_into(DEK::SetDateTimeRangeError)); + .chain_err(|| DEK::SetDateTimeRangeError)); match (opt_old_start, opt_old_end) { (Some(Ok(old_start)), Some(Ok(old_end))) => { let dr = DateTimeRange::new(old_start, old_end) - .map_err_into(DEK::DateTimeRangeError); + .chain_err(|| DEK::DateTimeRangeError); Ok(Some(dr)) }, diff --git a/lib/entry/libimagentrydatetime/src/error.rs b/lib/entry/libimagentrydatetime/src/error.rs index 0f0166a0..763c133b 100644 --- a/lib/entry/libimagentrydatetime/src/error.rs +++ b/lib/entry/libimagentrydatetime/src/error.rs @@ -17,23 +17,61 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(DateError, DateErrorKind, - DeleteDateError => "Error deleting date", - ReadDateError => "Error reading date", - SetDateError => "Error setting date", - DeleteDateTimeRangeError => "Error deleting date-time range", - ReadDateTimeRangeError => "Error reading date-time range", - SetDateTimeRangeError => "Error setting date-time range", +error_chain! { + types { + DateError, DateErrorKind, ResultExt, Result; + } - DateTimeRangeError => "DateTime Range error", + errors { + DeleteDateError { + description("Error deleting date") + display("Error deleting date") + } - DateHeaderFieldTypeError => "Expected the header field in the entry to have type 'String', but have other type", - DateTimeParsingError => "Error parsing DateTime" - ); -); + ReadDateError { + description("Error reading date") + display("Error reading date") + } -pub use self::error::DateError; -pub use self::error::DateErrorKind; -pub use self::error::MapErrInto; + SetDateError { + description("Error setting date") + display("Error setting date") + } + + DeleteDateTimeRangeError { + description("Error deleting date-time range") + display("Error deleting date-time range") + } + + ReadDateTimeRangeError { + description("Error reading date-time range") + display("Error reading date-time range") + } + + SetDateTimeRangeError { + description("Error setting date-time range") + display("Error setting date-time range") + } + + DateTimeRangeError { + description("DateTime Range error") + display("DateTime Range error") + } + + DateHeaderFieldTypeError { + description("Expected the header field in the entry to have type 'String', but have other type") + display("Expected the header field in the entry to have type 'String', but have other type") + } + + DateTimeParsingError { + description("Error parsing DateTime") + display("Error parsing DateTime") + } + + EndDateTimeBeforeStartDateTime { + description("End datetime is before start datetime") + display("End datetime is before start datetime") + } + } +} diff --git a/lib/entry/libimagentrydatetime/src/lib.rs b/lib/entry/libimagentrydatetime/src/lib.rs index 06cf6f22..fdb8067b 100644 --- a/lib/entry/libimagentrydatetime/src/lib.rs +++ b/lib/entry/libimagentrydatetime/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -37,13 +39,13 @@ extern crate chrono; extern crate toml_query; extern crate toml; +#[macro_use] extern crate error_chain; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagstore; pub mod datepath; pub mod datetime; pub mod error; pub mod range; -pub mod result; diff --git a/lib/entry/libimagentrydatetime/src/range.rs b/lib/entry/libimagentrydatetime/src/range.rs index 8820b7a3..526c0044 100644 --- a/lib/entry/libimagentrydatetime/src/range.rs +++ b/lib/entry/libimagentrydatetime/src/range.rs @@ -17,30 +17,11 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -/// Error types for range module -pub mod error { - generate_error_module!( - generate_error_types!(DateTimeRangeError, DateTimeRangeErrorKind, - EndDateTimeBeforeStartDateTime => "End datetime is before start datetime" - ); - ); - - pub use self::error::DateTimeRangeError; - pub use self::error::DateTimeRangeErrorKind; - pub use self::error::MapErrInto; -} - -/// Result type for range module -pub mod result { - use std::result::Result as RResult; - use super::error::DateTimeRangeError; - - pub type Result = RResult; -} - use chrono::naive::NaiveDateTime; -use libimagerror::into::IntoError; -use self::result::Result; + +use error::DateErrorKind as DEK; +use error::DateError as DE; +use error::Result; /// A Range between two dates #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -56,11 +37,10 @@ impl DateTimeRange { /// else Err(DateTimeRangeError) /// pub fn new(start: NaiveDateTime, end: NaiveDateTime) -> Result { - use self::error::DateTimeRangeErrorKind as DTREK; if start < end { Ok(DateTimeRange(start, end)) } else { - Err(DTREK::EndDateTimeBeforeStartDateTime.into_error()) + Err(DE::from_kind(DEK::EndDateTimeBeforeStartDateTime)) } } diff --git a/lib/entry/libimagentrydatetime/src/result.rs b/lib/entry/libimagentrydatetime/src/result.rs deleted file mode 100644 index d6d0a5af..00000000 --- a/lib/entry/libimagentrydatetime/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::DateError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentryedit/Cargo.toml b/lib/entry/libimagentryedit/Cargo.toml index 98087aa6..f9857133 100644 --- a/lib/entry/libimagentryedit/Cargo.toml +++ b/lib/entry/libimagentryedit/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://github.com/matthiasbeyer/imag" homepage = "http://imag-pim.org" [dependencies] +error-chain = "0.10" libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } libimagrt = { version = "0.4.0", path = "../../../lib/core/libimagrt" } diff --git a/lib/entry/libimagentryedit/src/edit.rs b/lib/entry/libimagentryedit/src/edit.rs index cbd17733..bd2ee190 100644 --- a/lib/entry/libimagentryedit/src/edit.rs +++ b/lib/entry/libimagentryedit/src/edit.rs @@ -17,13 +17,13 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use libimagerror::into::IntoError; use libimagrt::runtime::Runtime; use libimagstore::store::Entry; -use result::Result; +use error::Result; use error::EditErrorKind; -use error::MapErrInto; +use error::EditError as EE; +use error::ResultExt; pub trait Edit { fn edit_content(&mut self, rt: &Runtime) -> Result<()>; @@ -50,10 +50,10 @@ pub fn edit_in_tmpfile(rt: &Runtime, s: &mut String) -> Result<()> { use libimagutil::edit::edit_in_tmpfile_with_command; rt.editor() - .ok_or(EditErrorKind::NoEditor.into_error()) + .ok_or(EE::from_kind(EditErrorKind::NoEditor)) .and_then(|editor| { edit_in_tmpfile_with_command(editor, s) - .map_err_into(EditErrorKind::IOError) + .chain_err(|| EditErrorKind::IOError) .and_then(|worked| { if !worked { Err(EditErrorKind::ProcessExitFailure.into()) diff --git a/lib/entry/libimagentryedit/src/error.rs b/lib/entry/libimagentryedit/src/error.rs index 478d5d2c..5d5425f3 100644 --- a/lib/entry/libimagentryedit/src/error.rs +++ b/lib/entry/libimagentryedit/src/error.rs @@ -17,16 +17,32 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(EditError, EditErrorKind, - IOError => "IO Error", - NoEditor => "No editor set", - ProcessExitFailure => "Process did not exit properly", - InstantiateError => "Instantation error" - ); -); +error_chain! { + types { + EditError, EditErrorKind, ResultExt, Result; + } -pub use self::error::EditError; -pub use self::error::EditErrorKind; -pub use self::error::MapErrInto; + errors { + IOError { + description("IO Error") + display("IO Error") + } + + NoEditor { + description("No editor set") + display("No editor set") + } + + ProcessExitFailure { + description("Process did not exit properly") + display("Process did not exit properly") + } + + InstantiateError { + description("Instantation error") + display("Instantation error") + } + + } +} diff --git a/lib/entry/libimagentryedit/src/lib.rs b/lib/entry/libimagentryedit/src/lib.rs index 9d9187cd..cc385919 100644 --- a/lib/entry/libimagentryedit/src/lib.rs +++ b/lib/entry/libimagentryedit/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -33,11 +35,11 @@ while_true, )] -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagstore; extern crate libimagrt; extern crate libimagutil; +#[macro_use] extern crate error_chain; pub mod edit; pub mod error; -pub mod result; diff --git a/lib/entry/libimagentryedit/src/result.rs b/lib/entry/libimagentryedit/src/result.rs deleted file mode 100644 index 1d917c05..00000000 --- a/lib/entry/libimagentryedit/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::EditError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrygps/Cargo.toml b/lib/entry/libimagentrygps/Cargo.toml index d1fcba28..a8d8c771 100644 --- a/lib/entry/libimagentrygps/Cargo.toml +++ b/lib/entry/libimagentrygps/Cargo.toml @@ -14,6 +14,7 @@ toml = "^0.4" toml-query = "0.3.0" serde_derive = "1" serde = "1" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrygps/src/entry.rs b/lib/entry/libimagentrygps/src/entry.rs index b1d1d198..0a4bcf7d 100644 --- a/lib/entry/libimagentrygps/src/entry.rs +++ b/lib/entry/libimagentrygps/src/entry.rs @@ -17,9 +17,9 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use result::Result; +use error::Result; use error::GPSErrorKind as GPSEK; -use error::MapErrInto; +use error::ResultExt; use types::*; use libimagstore::store::Entry; @@ -40,11 +40,11 @@ impl GPSEntry for Entry { self.get_header_mut() .insert("gps.coordinates", c.into()) .map(|_| ()) - .map_err_into(GPSEK::HeaderWriteError) + .chain_err(|| GPSEK::HeaderWriteError) } fn get_coordinates(&self) -> Result> { - match self.get_header().read("gps.coordinates").map_err_into(GPSEK::HeaderWriteError) { + match self.get_header().read("gps.coordinates").chain_err(|| GPSEK::HeaderWriteError) { Ok(Some(hdr)) => Coordinates::from_value(hdr).map(Some), Ok(None) => Ok(None), Err(e) => Err(e), diff --git a/lib/entry/libimagentrygps/src/error.rs b/lib/entry/libimagentrygps/src/error.rs index 3c52e307..b40f9536 100644 --- a/lib/entry/libimagentrygps/src/error.rs +++ b/lib/entry/libimagentrygps/src/error.rs @@ -17,27 +17,71 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(GPSError, GPSErrorKind, - StoreReadError => "Store read error", - StoreWriteError => "Store write error", +error_chain! { + types { + GPSError, GPSErrorKind, ResultExt, Result; + } - HeaderWriteError => "Couldn't write Header for annotation", - HeaderReadError => "Couldn't read Header of Entry", - HeaderTypeError => "Header field has unexpected type", + errors { + StoreReadError { + description("Store read error") + display("Store read error") + } - TypeError => "Type Error", - DegreeMissing => "'degree' value missing", - MinutesMissing => "'minutes' value missing", - SecondsMissing => "'seconds' value missing", - LongitudeMissing => "'longitude' value missing", - LatitudeMissing => "'latitude' value missing", + StoreWriteError { + description("Store write error") + display("Store write error") + } - NumberConversionError => "Cannot convert number to fit into variable" - ); -); + HeaderWriteError { + description("Couldn't write Header for annotation") + display("Couldn't write Header for annotation") + } -pub use self::error::GPSError; -pub use self::error::GPSErrorKind; -pub use self::error::MapErrInto; + HeaderReadError { + description("Couldn't read Header of Entry") + display("Couldn't read Header of Entry") + } + + HeaderTypeError { + description("Header field has unexpected type") + display("Header field has unexpected type") + } + + TypeError { + description("Type Error") + display("Type Error") + } + + DegreeMissing { + description("'degree' value missing") + display("'degree' value missing") + } + + MinutesMissing { + description("'minutes' value missing") + display("'minutes' value missing") + } + + SecondsMissing { + description("'seconds' value missing") + display("'seconds' value missing") + } + + LongitudeMissing { + description("'longitude' value missing") + display("'longitude' value missing") + } + + LatitudeMissing { + description("'latitude' value missing") + display("'latitude' value missing") + } + + NumberConversionError { + description("Cannot convert number to fit into variable") + display("Cannot convert number to fit into variable") + } + } +} diff --git a/lib/entry/libimagentrygps/src/lib.rs b/lib/entry/libimagentrygps/src/lib.rs index 030b3596..7df3a23a 100644 --- a/lib/entry/libimagentrygps/src/lib.rs +++ b/lib/entry/libimagentrygps/src/lib.rs @@ -20,6 +20,7 @@ extern crate toml; extern crate toml_query; #[macro_use] extern crate serde_derive; +#[macro_use] extern crate error_chain; extern crate libimagstore; #[macro_use] extern crate libimagerror; @@ -29,6 +30,5 @@ extern crate env_logger; pub mod entry; pub mod error; -pub mod result; pub mod types; diff --git a/lib/entry/libimagentrygps/src/result.rs b/lib/entry/libimagentrygps/src/result.rs deleted file mode 100644 index 495798fa..00000000 --- a/lib/entry/libimagentrygps/src/result.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::GPSError; - -pub type Result = RResult; - - diff --git a/lib/entry/libimagentrygps/src/types.rs b/lib/entry/libimagentrygps/src/types.rs index 32412000..587b17b4 100644 --- a/lib/entry/libimagentrygps/src/types.rs +++ b/lib/entry/libimagentrygps/src/types.rs @@ -21,10 +21,10 @@ use std::collections::BTreeMap; use toml::Value; -use libimagerror::into::IntoError; - use error::GPSErrorKind as GPSEK; -use result::Result; +use error::GPSError as GPSE; +use error::Result; +use error::ResultExt; pub trait FromValue : Sized { fn from_value(v: &Value) -> Result; @@ -67,30 +67,30 @@ impl FromValue for GPSValue { Value::Table(ref map) => { Ok(GPSValue::new( map.get("degree") - .ok_or_else(|| GPSEK::DegreeMissing.into_error()) + .ok_or_else(|| GPSE::from_kind(GPSEK::DegreeMissing)) .and_then(|v| match *v { Value::Integer(i) => i64_to_i8(i), - _ => Err(GPSEK::HeaderTypeError.into_error()), + _ => Err(GPSE::from_kind(GPSEK::HeaderTypeError)), })?, map .get("minutes") - .ok_or_else(|| GPSEK::MinutesMissing.into_error()) + .ok_or_else(|| GPSE::from_kind(GPSEK::MinutesMissing)) .and_then(|v| match *v { Value::Integer(i) => i64_to_i8(i), - _ => Err(GPSEK::HeaderTypeError.into_error()), + _ => Err(GPSE::from_kind(GPSEK::HeaderTypeError)), })?, map .get("seconds") - .ok_or_else(|| GPSEK::SecondsMissing.into_error()) + .ok_or_else(|| GPSE::from_kind(GPSEK::SecondsMissing)) .and_then(|v| match *v { Value::Integer(i) => i64_to_i8(i), - _ => Err(GPSEK::HeaderTypeError.into_error()), + _ => Err(GPSE::from_kind(GPSEK::HeaderTypeError)), })? )) } - _ => Err(GPSEK::TypeError.into_error()) + _ => Err(GPSE::from_kind(GPSEK::TypeError)) } } @@ -130,16 +130,16 @@ impl FromValue for Coordinates { Ok(Coordinates::new( match map.get("longitude") { Some(v) => GPSValue::from_value(v), - None => Err(GPSEK::LongitudeMissing.into_error()), + None => Err(GPSE::from_kind(GPSEK::LongitudeMissing)), }?, match map.get("latitude") { Some(v) => GPSValue::from_value(v), - None => Err(GPSEK::LongitudeMissing.into_error()), + None => Err(GPSE::from_kind(GPSEK::LongitudeMissing)), }? )) } - _ => Err(GPSEK::TypeError.into_error()) + _ => Err(GPSE::from_kind(GPSEK::TypeError)) } } @@ -148,7 +148,7 @@ impl FromValue for Coordinates { /// Helper to convert a i64 to i8 or return an error if this doesn't work. fn i64_to_i8(i: i64) -> Result { if i > (::max_value() as i64) { - Err(GPSEK::NumberConversionError.into_error()) + Err(GPSE::from_kind(GPSEK::NumberConversionError)) } else { Ok(i as i8) } diff --git a/lib/entry/libimagentrylink/Cargo.toml b/lib/entry/libimagentrylink/Cargo.toml index 5487c344..ba071fe3 100644 --- a/lib/entry/libimagentrylink/Cargo.toml +++ b/lib/entry/libimagentrylink/Cargo.toml @@ -22,6 +22,7 @@ rust-crypto = "0.2" env_logger = "0.3" is-match = "0.1" toml-query = "0.3.0" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrylink/src/error.rs b/lib/entry/libimagentrylink/src/error.rs index 10d83f94..6f27f92a 100644 --- a/lib/entry/libimagentrylink/src/error.rs +++ b/lib/entry/libimagentrylink/src/error.rs @@ -17,24 +17,88 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(LinkError, LinkErrorKind, - EntryHeaderReadError => "Error while reading an entry header", - EntryHeaderWriteError => "Error while writing an entry header", - ExistingLinkTypeWrong => "Existing link entry has wrong type", - LinkTargetDoesNotExist => "Link target does not exist in the store", - LinkParserError => "Link cannot be parsed", - LinkParserFieldMissingError => "Link cannot be parsed: Field missing", - LinkParserFieldTypeError => "Link cannot be parsed: Field type wrong", - InternalConversionError => "Error while converting values internally", - InvalidUri => "URI is not valid", - StoreReadError => "Store read error", - StoreWriteError => "Store write error", - StoreIdError => "StoreId handling error" - ); -); +use libimagstore::storeid::StoreId; -pub use self::error::LinkError; -pub use self::error::LinkErrorKind; -pub use self::error::MapErrInto; +error_chain! { + types { + LinkError, LinkErrorKind, ResultExt, Result; + } + + 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") + } + + StoreReadError { + description("Store read error") + display("Store read error") + } + + StoreWriteError { + description("Store write error") + display("Store write error") + } + + StoreIdError { + description("StoreId handling error") + display("StoreId handling error") + } + + 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") + } + + StoreError { + description("Error while talking to the store") + display("Error while talking to the store") + } + } +} diff --git a/lib/entry/libimagentrylink/src/external.rs b/lib/entry/libimagentrylink/src/external.rs index 56dcd91d..7da4f345 100644 --- a/lib/entry/libimagentrylink/src/external.rs +++ b/lib/entry/libimagentrylink/src/external.rs @@ -39,17 +39,16 @@ use libimagstore::store::Store; use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; use libimagutil::debug_result::*; -use libimagerror::into::IntoError; use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; -use error::LinkError as LE; use error::LinkErrorKind as LEK; -use error::MapErrInto; -use result::Result; +use error::LinkError as LE; +use error::Result; use internal::InternalLinker; use module_path::ModuleEntryPath; +use error::ResultExt; use self::iter::*; @@ -71,13 +70,13 @@ impl Link for Entry { fn get_link_uri_from_filelockentry(&self) -> Result> { self.get_header() .read("imag.content.url") - .map_err_into(LEK::EntryHeaderReadError) + .chain_err(|| LEK::EntryHeaderReadError) .and_then(|opt| match opt { Some(&Value::String(ref s)) => { debug!("Found url, parsing: {:?}", s); - Url::parse(&s[..]).map_err_into(LEK::InvalidUri).map(Some) + Url::parse(&s[..]).chain_err(|| LEK::InvalidUri).map(Some) }, - Some(_) => Err(LEK::LinkParserFieldTypeError.into_error()), + Some(_) => Err(LE::from_kind(LEK::LinkParserFieldTypeError)), None => Ok(None), }) } @@ -87,10 +86,10 @@ impl Link for Entry { Ok(Some(&Value::String(ref s))) => { Url::parse(&s[..]) .map(Some) - .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e)))) + .chain_err(|| LEK::EntryHeaderReadError) }, Ok(None) => Ok(None), - _ => Err(LE::new(LEK::EntryHeaderReadError, None)) + _ => Err(LE::from_kind(LEK::EntryHeaderReadError)) } } @@ -131,8 +130,8 @@ pub mod iter { use internal::Link; use internal::iter::LinkIter; use error::LinkErrorKind as LEK; - use error::MapErrInto; - use result::Result; + use error::ResultExt; + use error::Result; use url::Url; @@ -265,7 +264,7 @@ pub mod iter { debug!("Retrieving entry for id: '{:?}'", id); self.1 .retrieve(id.clone()) - .map_err_into(LEK::StoreReadError) + .chain_err(|| LEK::StoreReadError) .map_dbg_err(|_| format!("Retrieving entry for id: '{:?}' failed", id)) .and_then(|f| { debug!("Store::retrieve({:?}) succeeded", id); @@ -306,7 +305,7 @@ impl ExternalLinker for Entry { // /link/external/ -> load these files and get the external link from their headers, // put them into the return vector. self.get_internal_links() - .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e)))) + .chain_err(|| LEK::StoreReadError) .map(|iter| { debug!("Getting external links"); iter.only_external_links().urls(store) @@ -328,7 +327,7 @@ impl ExternalLinker for Entry { }; let file_id = try!( ModuleEntryPath::new(format!("external/{}", hash)).into_storeid() - .map_err_into(LEK::StoreWriteError) + .chain_err(|| LEK::StoreWriteError) .map_dbg_err(|_| { format!("Failed to build StoreId for this hash '{:?}'", hash) }) @@ -342,7 +341,7 @@ impl ExternalLinker for Entry { // exist let mut file = try!(store .retrieve(file_id.clone()) - .map_err_into(LEK::StoreWriteError) + .chain_err(|| LEK::StoreWriteError) .map_dbg_err(|_| { format!("Failed to create or retrieve an file for this link '{:?}'", link) })); @@ -359,7 +358,7 @@ impl ExternalLinker for Entry { BTreeMap::new() }, Ok(None) => BTreeMap::new(), - Err(e) => return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))), + Err(e) => return Err(e).chain_err(|| LEK::StoreWriteError), }; let v = Value::String(link.into_string()); @@ -368,7 +367,7 @@ impl ExternalLinker for Entry { table.insert(String::from("url"), v); if let Err(e) = hdr.set("imag.content", Value::Table(table)) { - return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))); + return Err(e).chain_err(|| LEK::StoreWriteError); } else { debug!("Setting URL worked"); } @@ -377,7 +376,7 @@ impl ExternalLinker for Entry { // then add an internal link to the new file or return an error if this fails if let Err(e) = self.add_internal_link(file.deref_mut()) { debug!("Error adding internal link"); - return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))); + return Err(e).chain_err(|| LEK::StoreWriteError); } } debug!("Ready iterating"); diff --git a/lib/entry/libimagentrylink/src/internal.rs b/lib/entry/libimagentrylink/src/internal.rs index 8e33d8d8..b5b0fd37 100644 --- a/lib/entry/libimagentrylink/src/internal.rs +++ b/lib/entry/libimagentrylink/src/internal.rs @@ -25,14 +25,14 @@ use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; use libimagstore::store::Entry; use libimagstore::store::Result as StoreResult; -use libimagerror::into::IntoError; use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; use error::LinkErrorKind as LEK; -use error::MapErrInto; -use result::Result; +use error::LinkError as LE; +use error::ResultExt; +use error::Result; use self::iter::LinkIter; use self::iter::IntoValues; @@ -51,7 +51,7 @@ impl Link { Link::Id { ref link } => link.exists(), Link::Annotated { ref link, .. } => link.exists(), } - .map_err_into(LEK::StoreIdError) + .chain_err(|| LEK::StoreIdError) } pub fn to_str(&self) -> Result { @@ -59,7 +59,7 @@ impl Link { Link::Id { ref link } => link.to_str(), Link::Annotated { ref link, .. } => link.to_str(), } - .map_err_into(LEK::StoreReadError) + .chain_err(|| LEK::StoreReadError) } @@ -100,11 +100,11 @@ impl Link { fn to_value(&self) -> Result { match self { &Link::Id { link: ref s } => - s.to_str().map(Value::String).map_err_into(LEK::InternalConversionError), + s.to_str().map(Value::String).chain_err(|| LEK::InternalConversionError), &Link::Annotated { ref link, annotation: ref anno } => { link.to_str() .map(Value::String) - .map_err_into(LEK::InternalConversionError) + .chain_err(|| LEK::InternalConversionError) .map(|link| { let mut tab = BTreeMap::new(); @@ -187,8 +187,8 @@ pub mod iter { use super::Link; use error::LinkErrorKind as LEK; - use error::MapErrInto; - use result::Result; + use error::ResultExt; + use error::Result; use toml::Value; use itertools::Itertools; @@ -228,7 +228,7 @@ pub mod iter { .unique() .sorted() .into_iter() // Cannot sort toml::Value, hence uglyness here - .map(|link| link.to_value().map_err_into(LEK::InternalConversionError)) + .map(|link| link.to_value().chain_err(|| LEK::InternalConversionError)) .collect() } } @@ -288,7 +288,7 @@ pub mod iter { type Item = Result>; fn next(&mut self) -> Option { - self.0.next().and_then(|id| match self.1.get(id).map_err_into(LEK::StoreReadError) { + self.0.next().and_then(|id| match self.1.get(id).chain_err(|| LEK::StoreReadError) { Ok(None) => None, Ok(Some(x)) => Some(Ok(x)), Err(e) => Some(Err(e)), @@ -318,7 +318,7 @@ pub mod iter { loop { match self.0.next() { Some(Ok(fle)) => { - let links = match fle.get_internal_links().map_err_into(LEK::StoreReadError) + let links = match fle.get_internal_links().chain_err(|| LEK::StoreReadError) { Err(e) => return Some(Err(e)), Ok(links) => links.collect::>(), @@ -358,7 +358,7 @@ pub mod iter { loop { match self.0.next() { Some(Ok(fle)) => { - let links = match fle.get_internal_links().map_err_into(LEK::StoreReadError) + let links = match fle.get_internal_links().chain_err(|| LEK::StoreReadError) { Err(e) => return Some(Err(e)), Ok(links) => links, @@ -367,7 +367,7 @@ pub mod iter { match self.0 .store() .delete(fle.get_location().clone()) - .map_err_into(LEK::StoreWriteError) + .chain_err(|| LEK::StoreWriteError) { Ok(x) => x, Err(e) => return Some(Err(e)), @@ -393,7 +393,7 @@ impl InternalLinker for Entry { let res = self .get_header() .read("imag.links") - .map_err_into(LEK::EntryHeaderReadError) + .chain_err(|| LEK::EntryHeaderReadError) .map(|r| r.cloned()); process_rw_result(res) } @@ -417,7 +417,7 @@ impl InternalLinker for Entry { .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - elem.map_err_into(LEK::InternalConversionError) + elem.chain_err(|| LEK::InternalConversionError) .map(|e| { v.push(e); v @@ -427,7 +427,7 @@ impl InternalLinker for Entry { let res = self .get_header_mut() .set("imag.links", Value::Array(new_links)) - .map_err_into(LEK::EntryHeaderReadError); + .chain_err(|| LEK::EntryHeaderReadError); process_rw_result(res) } @@ -487,7 +487,7 @@ fn rewrite_links>(header: &mut Value, links: I) -> Resu .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - elem.map_err_into(LEK::InternalConversionError) + elem.chain_err(|| LEK::InternalConversionError) .map(|e| { v.push(e); v @@ -498,7 +498,7 @@ fn rewrite_links>(header: &mut Value, links: I) -> Resu debug!("Setting new link array: {:?}", links); let process = header .set("imag.links", Value::Array(links)) - .map_err_into(LEK::EntryHeaderReadError); + .chain_err(|| LEK::EntryHeaderReadError); process_rw_result(process).map(|_| ()) } @@ -514,7 +514,7 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> { .into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(move |mut v| { - elem.map_err_into(LEK::InternalConversionError) + elem.chain_err(|| LEK::InternalConversionError) .map(|e| { v.push(e); v @@ -526,7 +526,7 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> { let res = target .get_header_mut() .set("imag.links", Value::Array(links)) - .map_err_into(LEK::EntryHeaderReadError); + .chain_err(|| LEK::EntryHeaderReadError); process_rw_result(res).map(|_| ()) }) @@ -538,7 +538,7 @@ fn process_rw_result(links: Result>) -> Result { let links = match links { Err(e) => { debug!("RW action on store failed. Generating LinkError"); - return Err(LEK::EntryHeaderReadError.into_error_with_cause(Box::new(e))) + return Err(e).chain_err(|| LEK::EntryHeaderReadError) }, Ok(None) => { debug!("We got no value from the header!"); @@ -562,7 +562,7 @@ fn process_rw_result(links: Result>) -> Result { debug!("Matching the link: {:?}", link); match link { Value::String(s) => StoreId::new_baseless(PathBuf::from(s)) - .map_err_into(LEK::StoreIdError) + .chain_err(|| LEK::StoreIdError) .map(|s| Link::Id { link: s }) , Value::Table(mut tab) => { @@ -570,19 +570,19 @@ fn process_rw_result(links: Result>) -> Result { if !tab.contains_key("link") || !tab.contains_key("annotation") { debug!("Things missing... returning Error instance"); - Err(LEK::LinkParserError.into_error()) + Err(LE::from_kind(LEK::LinkParserError)) } else { let link = try!(tab.remove("link") - .ok_or(LEK::LinkParserFieldMissingError.into_error())); + .ok_or(LE::from_kind(LEK::LinkParserFieldMissingError))); let anno = try!(tab.remove("annotation") - .ok_or(LEK::LinkParserFieldMissingError.into_error())); + .ok_or(LE::from_kind(LEK::LinkParserFieldMissingError))); debug!("Ok, here we go with building a Link::Annotated"); match (link, anno) { (Value::String(link), Value::String(anno)) => { StoreId::new_baseless(PathBuf::from(link)) - .map_err_into(LEK::StoreIdError) + .chain_err(|| LEK::StoreIdError) .map(|link| { Link::Annotated { link: link, @@ -590,7 +590,7 @@ fn process_rw_result(links: Result>) -> Result { } }) }, - _ => Err(LEK::LinkParserFieldTypeError.into_error()), + _ => Err(LE::from_kind(LEK::LinkParserFieldTypeError)), } } } @@ -605,68 +605,8 @@ fn process_rw_result(links: Result>) -> Result { pub mod store_check { use libimagstore::store::Store; - - pub mod error { - generate_error_imports!(); - - use libimagstore::storeid::StoreId; - - #[derive(Debug)] - pub enum StoreLinkConsistencyErrorCustomData { - DeadLink { - target: StoreId - }, - OneDirectionalLink { - source: StoreId, - target: StoreId - }, - } - - impl Display for StoreLinkConsistencyErrorCustomData { - - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { - use self::StoreLinkConsistencyErrorCustomData as SLCECD; - match self { - &SLCECD::DeadLink { ref target } => { - try!(write!(fmt, "Dead Link to '{}'", target)) - }, - - &SLCECD::OneDirectionalLink { ref source, ref target } => { - try!(write!(fmt, - "Link from '{}' to '{}' does exist, but not other way round", - source, target)) - } - }; - Ok(()) - } - - } - - generate_custom_error_types!( - StoreLinkConsistencyError, - StoreLinkConsistencyErrorKind, - StoreLinkConsistencyErrorCustomData, - StoreLinkConsistencyError => "Links in the store are not consistent", - LinkHandlingError => "Error in link handling", - StoreError => "Error while talking to the store" - ); - - generate_result_helper!(StoreLinkConsistencyError, StoreLinkConsistencyErrorKind); - generate_option_helper!(StoreLinkConsistencyError, StoreLinkConsistencyErrorKind); - } - - pub use self::error::StoreLinkConsistencyError; - pub use self::error::StoreLinkConsistencyErrorKind; - pub use self::error::MapErrInto; - - pub mod result { - use std::result::Result as RResult; - use internal::store_check::error::StoreLinkConsistencyError as SLCE; - - pub type Result = RResult; - } - - use self::result::Result; + use error::Result; + use error::ResultExt; pub trait StoreLinkConsistentExt { fn check_link_consistency(&self) -> Result<()>; @@ -676,17 +616,14 @@ pub mod store_check { fn check_link_consistency(&self) -> Result<()> { use std::collections::HashMap; - use self::error::StoreLinkConsistencyErrorKind as SLCEK; - use self::error::StoreLinkConsistencyError as SLCE; - use self::error::StoreLinkConsistencyErrorCustomData as SLCECD; use error::LinkErrorKind as LEK; - use result::Result as LResult; + use error::LinkError as LE; + use error::Result as LResult; use internal::InternalLinker; use libimagstore::store::StoreObject; use libimagstore::storeid::StoreId; use libimagerror::iter::TraceIterator; - use libimagerror::into::IntoError; use libimagutil::iter::FoldResult; // Helper data structure to collect incoming and outgoing links for each StoreId @@ -714,7 +651,7 @@ pub mod store_check { acc.and_then(|mut state| { debug!("Checking entry: '{}'", sid); - match try!(self.get(sid).map_err_into(SLCEK::StoreError)) { + match try!(self.get(sid).chain_err(|| LEK::StoreError)) { Some(fle) => { debug!("Found FileLockEntry"); @@ -722,7 +659,7 @@ pub mod store_check { let internal_links = fle .get_internal_links() - .map_err_into(SLCEK::StoreError)? + .chain_err(|| LEK::StoreError)? .into_getter(self) // get the FLEs from the Store .trace_unwrap(); // trace all Err(e)s and get the Ok(fle)s @@ -765,36 +702,23 @@ pub mod store_check { if is_match!(self.get(id.clone()), Ok(Some(_))) { debug!("Exists in store: {:?}", id); - let exists = { - use error::MapErrInto as MEI; - try!(MEI::map_err_into(id.exists(), LEK::StoreReadError)) - }; - - if !exists { + if !try!(id.exists().chain_err(|| LEK::StoreReadError)) { warn!("Does exist in store but not on FS: {:?}", id); - Err(LEK::LinkTargetDoesNotExist.into_error()) + Err(LE::from_kind(LEK::LinkTargetDoesNotExist)) } else { Ok(()) } } else { warn!("Does not exist in store: {:?}", id); - Err(LEK::LinkTargetDoesNotExist.into_error()) + Err(LE::from_kind(LEK::LinkTargetDoesNotExist)) } }) }; /// Helper function to create a SLCECD::OneDirectionalLink error object #[inline] - let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> SLCE { - // construct the error - let custom = SLCECD::OneDirectionalLink { - source: src, - target: target, - }; - - SLCEK::StoreLinkConsistencyError - .into_error() - .with_custom_data(custom) + let mk_one_directional_link_err = |src: StoreId, target: StoreId| -> LE { + LE::from_kind(LEK::DeadLink(src, target)) }; /// Helper lambda to check whether the _incoming_ links of each entry actually also @@ -847,7 +771,7 @@ pub mod store_check { .and_then(|nw| { all_collected_storeids_exist(&nw) .map(|_| nw) - .map_err_into(SLCEK::LinkHandlingError) + .chain_err(|| LEK::LinkHandlingError) }) .and_then(|nw| { nw.iter().fold_result(|(id, linking)| { diff --git a/lib/entry/libimagentrylink/src/lib.rs b/lib/entry/libimagentrylink/src/lib.rs index 4df88cc7..5c24ee34 100644 --- a/lib/entry/libimagentrylink/src/lib.rs +++ b/lib/entry/libimagentrylink/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -40,12 +42,13 @@ extern crate toml_query; extern crate url; extern crate crypto; #[macro_use] extern crate is_match; +#[macro_use] extern crate error_chain; #[cfg(test)] extern crate env_logger; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagutil; module_entry_path_mod!("links"); @@ -53,5 +56,4 @@ module_entry_path_mod!("links"); pub mod error; pub mod external; pub mod internal; -pub mod result; diff --git a/lib/entry/libimagentrylink/src/result.rs b/lib/entry/libimagentrylink/src/result.rs deleted file mode 100644 index 23e50363..00000000 --- a/lib/entry/libimagentrylink/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::LinkError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrylist/Cargo.toml b/lib/entry/libimagentrylist/Cargo.toml index 9775dc41..7746d216 100644 --- a/lib/entry/libimagentrylist/Cargo.toml +++ b/lib/entry/libimagentrylist/Cargo.toml @@ -17,6 +17,7 @@ homepage = "http://imag-pim.org" clap = ">=2.17" log = "0.3" prettytable-rs = "0.6.*" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrylist/src/cli.rs b/lib/entry/libimagentrylist/src/cli.rs index b52a92fd..e54deba0 100644 --- a/lib/entry/libimagentrylist/src/cli.rs +++ b/lib/entry/libimagentrylist/src/cli.rs @@ -21,11 +21,12 @@ use clap::{Arg, ArgMatches, App, SubCommand}; use libimagstore::store::FileLockEntry; -use result::Result; +use error::Result; use listers::line::LineLister; use listers::path::PathLister; use lister::Lister; -use error::{ListError, ListErrorKind}; +use error::ListErrorKind; +use error::ListError as LE; pub fn build_list_cli_component<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name(list_subcommand_name()) @@ -96,6 +97,6 @@ pub fn list_entries_with_lister<'a, I>(m: &ArgMatches, entries: I) -> Result<()> Ok(()) } else { - Err(ListError::new(ListErrorKind::CLIError, None)) + Err(LE::from_kind(ListErrorKind::CLIError)) } } diff --git a/lib/entry/libimagentrylist/src/error.rs b/lib/entry/libimagentrylist/src/error.rs index 9c3b1ccc..877d1d71 100644 --- a/lib/entry/libimagentrylist/src/error.rs +++ b/lib/entry/libimagentrylist/src/error.rs @@ -17,17 +17,37 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(ListError, ListErrorKind, - IOError => "IO Error", - FormatError => "FormatError", - EntryError => "EntryError", - IterationError => "IterationError", - CLIError => "No CLI subcommand for listing entries" - ); -); +error_chain! { + types { + ListError, ListErrorKind, ResultExt, Result; + } -pub use self::error::ListError; -pub use self::error::ListErrorKind; -pub use self::error::MapErrInto; + errors { + IOError { + description("IO Error") + display("IO Error") + } + + FormatError { + description("FormatError") + display("FormatError") + } + + EntryError { + description("EntryError") + display("EntryError") + } + + IterationError { + description("IterationError") + display("IterationError") + } + + CLIError { + description("No CLI subcommand for listing entries") + display("No CLI subcommand for listing entries") + } + + } +} diff --git a/lib/entry/libimagentrylist/src/lib.rs b/lib/entry/libimagentrylist/src/lib.rs index 8fb0186e..0f4748a4 100644 --- a/lib/entry/libimagentrylist/src/lib.rs +++ b/lib/entry/libimagentrylist/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -36,14 +38,14 @@ extern crate clap; #[macro_use] extern crate log; extern crate prettytable; +#[macro_use] extern crate error_chain; extern crate libimagstore; extern crate libimagutil; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; pub mod cli; pub mod error; pub mod lister; pub mod listers; -pub mod result; diff --git a/lib/entry/libimagentrylist/src/lister.rs b/lib/entry/libimagentrylist/src/lister.rs index 798061b8..3bb64786 100644 --- a/lib/entry/libimagentrylist/src/lister.rs +++ b/lib/entry/libimagentrylist/src/lister.rs @@ -19,7 +19,7 @@ use libimagstore::store::FileLockEntry; -use result::Result; +use error::Result; pub trait Lister : Sized { diff --git a/lib/entry/libimagentrylist/src/listers/core.rs b/lib/entry/libimagentrylist/src/listers/core.rs index 733ba719..d653c7bb 100644 --- a/lib/entry/libimagentrylist/src/listers/core.rs +++ b/lib/entry/libimagentrylist/src/listers/core.rs @@ -21,7 +21,8 @@ use std::io::stdout; use std::io::Write; use lister::Lister; -use result::Result; +use error::Result; +use error::ResultExt; use libimagstore::store::FileLockEntry; use libimagstore::store::Entry; @@ -43,7 +44,6 @@ impl String> CoreLister { impl String> Lister for CoreLister { fn list<'b, I: Iterator>>(&self, entries: I) -> Result<()> { - use error::ListError as LE; use error::ListErrorKind as LEK; debug!("Called list()"); @@ -53,7 +53,7 @@ impl String> Lister for CoreLister { let r = accu.and_then(|_| { debug!("Listing Entry: {:?}", entry); write!(stdout(), "{:?}\n", (self.lister)(&entry)) - .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) + .chain_err(|| LEK::FormatError) }); (r, i + 1) }); diff --git a/lib/entry/libimagentrylist/src/listers/line.rs b/lib/entry/libimagentrylist/src/listers/line.rs index 8c439934..69cef86e 100644 --- a/lib/entry/libimagentrylist/src/listers/line.rs +++ b/lib/entry/libimagentrylist/src/listers/line.rs @@ -21,7 +21,8 @@ use std::io::stdout; use std::io::Write; use lister::Lister; -use result::Result; +use error::Result; +use error::ResultExt; use libimagstore::store::FileLockEntry; use libimagutil::iter::FoldResult; @@ -43,12 +44,11 @@ impl<'a> LineLister<'a> { impl<'a> Lister for LineLister<'a> { fn list<'b, I: Iterator>>(&self, entries: I) -> Result<()> { - use error::ListError as LE; use error::ListErrorKind as LEK; entries.fold_result(|entry| { let s = entry.get_location().to_str().unwrap_or(String::from(self.unknown_output)); - write!(stdout(), "{:?}\n", s).map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) + write!(stdout(), "{:?}\n", s).chain_err(| | LEK::FormatError) }) } diff --git a/lib/entry/libimagentrylist/src/listers/path.rs b/lib/entry/libimagentrylist/src/listers/path.rs index 15a2df5b..d359226c 100644 --- a/lib/entry/libimagentrylist/src/listers/path.rs +++ b/lib/entry/libimagentrylist/src/listers/path.rs @@ -21,8 +21,8 @@ use std::io::stdout; use std::io::Write; use lister::Lister; -use result::Result; -use error::MapErrInto; +use error::Result; +use error::ResultExt; use libimagstore::store::FileLockEntry; use libimagutil::iter::FoldResult; @@ -44,30 +44,19 @@ impl PathLister { impl Lister for PathLister { fn list<'a, I: Iterator>>(&self, entries: I) -> Result<()> { - use error::ListError as LE; use error::ListErrorKind as LEK; entries.fold_result(|entry| { Ok(entry.get_location().clone()) - .and_then(|pb| pb.into_pathbuf().map_err_into(LEK::FormatError)) + .and_then(|pb| pb.into_pathbuf().chain_err(|| LEK::FormatError)) .and_then(|pb| { if self.absolute { - pb.canonicalize().map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) + pb.canonicalize().chain_err(|| LEK::FormatError) } else { Ok(pb.into()) } }) - .and_then(|pb| { - write!(stdout(), "{:?}\n", pb) - .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e)))) - }) - .map_err(|e| { - if e.err_type() == LEK::FormatError { - e - } else { - LE::new(LEK::FormatError, Some(Box::new(e))) - } - }) + .and_then(|pb| write!(stdout(), "{:?}\n", pb).chain_err(|| LEK::FormatError)) }) } diff --git a/lib/entry/libimagentrylist/src/listers/table.rs b/lib/entry/libimagentrylist/src/listers/table.rs index e9358ce3..3bb58b95 100644 --- a/lib/entry/libimagentrylist/src/listers/table.rs +++ b/lib/entry/libimagentrylist/src/listers/table.rs @@ -20,11 +20,10 @@ use std::io::stdout; use lister::Lister; -use result::Result; -use error::MapErrInto; +use error::Result; +use error::ResultExt; use libimagstore::store::FileLockEntry; -use libimagerror::into::IntoError; use prettytable::Table; use prettytable::cell::Cell; @@ -63,6 +62,7 @@ impl Vec> Lister for TableLister { fn list<'b, I: Iterator>>(&self, entries: I) -> Result<()> { use error::ListErrorKind as LEK; + use error::ListError as LE; let mut table = Table::new(); let mut header_len : Option = None; @@ -90,7 +90,7 @@ impl Vec> Lister for TableLister { header_len = Some(v_len); } if header_len.map(|l| v_len > l).unwrap_or(false) { - return Err(LEK::FormatError.into_error()); + return Err(LE::from_kind(LEK::FormatError)); } while header_len.map(|l| v.len() != l).unwrap_or(false) { v.push(String::from("")); @@ -103,7 +103,7 @@ impl Vec> Lister for TableLister { }) .and_then(|tbl| { let mut io = stdout(); - tbl.print(&mut io).map_err_into(LEK::IOError) + tbl.print(&mut io).chain_err(|| LEK::IOError) }) } diff --git a/lib/entry/libimagentrylist/src/result.rs b/lib/entry/libimagentrylist/src/result.rs deleted file mode 100644 index e29d7d34..00000000 --- a/lib/entry/libimagentrylist/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::ListError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrymarkdown/Cargo.toml b/lib/entry/libimagentrymarkdown/Cargo.toml index 5f8364fe..3b962eac 100644 --- a/lib/entry/libimagentrymarkdown/Cargo.toml +++ b/lib/entry/libimagentrymarkdown/Cargo.toml @@ -17,6 +17,7 @@ homepage = "http://imag-pim.org" log = "0.3" hoedown = "5.0.0" url = "1.2" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrymarkdown/src/error.rs b/lib/entry/libimagentrymarkdown/src/error.rs index 1186d5f3..4df464ec 100644 --- a/lib/entry/libimagentrymarkdown/src/error.rs +++ b/lib/entry/libimagentrymarkdown/src/error.rs @@ -17,14 +17,22 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(MarkdownError, MarkdownErrorKind, - MarkdownRenderError => "Markdown render error", - LinkParsingError => "Link parsing error" - ); -); +error_chain! { + types { + MarkdownError, MarkdownErrorKind, ResultExt, Result; + } -pub use self::error::MarkdownError; -pub use self::error::MarkdownErrorKind; + errors { + MarkdownRenderError { + description("Markdown render error") + display("Markdown render error") + } + LinkParsingError { + description("Link parsing error") + display("Link parsing error") + } + + } +} diff --git a/lib/entry/libimagentrymarkdown/src/html.rs b/lib/entry/libimagentrymarkdown/src/html.rs index 1fcd12c7..9322dcfd 100644 --- a/lib/entry/libimagentrymarkdown/src/html.rs +++ b/lib/entry/libimagentrymarkdown/src/html.rs @@ -21,9 +21,9 @@ use hoedown::{Markdown, Html as MdHtml}; use hoedown::renderer::html::Flags as HtmlFlags; use hoedown::renderer::Render; -use result::Result; +use error::Result; use error::MarkdownErrorKind; -use libimagerror::into::IntoError; +use error::ResultExt; pub type HTML = String; @@ -33,12 +33,11 @@ pub fn to_html(buffer: &str) -> Result { html.render(&md) .to_str() .map(String::from) - .map_err(Box::new) - .map_err(|e| MarkdownErrorKind::MarkdownRenderError.into_error_with_cause(e)) + .chain_err(|| MarkdownErrorKind::MarkdownRenderError) } pub mod iter { - use result::Result; + use error::Result; use libimagstore::store::Entry; use super::HTML; use super::to_html; diff --git a/lib/entry/libimagentrymarkdown/src/lib.rs b/lib/entry/libimagentrymarkdown/src/lib.rs index 4cd31d0a..e17751dc 100644 --- a/lib/entry/libimagentrymarkdown/src/lib.rs +++ b/lib/entry/libimagentrymarkdown/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -36,10 +38,10 @@ extern crate hoedown; extern crate url; extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; +#[macro_use] extern crate error_chain; pub mod error; pub mod html; pub mod link; -pub mod result; diff --git a/lib/entry/libimagentrymarkdown/src/link.rs b/lib/entry/libimagentrymarkdown/src/link.rs index 9f13fe65..7de3edc7 100644 --- a/lib/entry/libimagentrymarkdown/src/link.rs +++ b/lib/entry/libimagentrymarkdown/src/link.rs @@ -18,15 +18,14 @@ // use error::MarkdownErrorKind as MEK; -use result::Result; +use error::ResultExt; +use error::Result; use hoedown::renderer::Render; use hoedown::Buffer; use hoedown::Markdown; use url::Url; -use libimagerror::into::IntoError; - #[derive(Debug, Clone, PartialEq, Eq)] pub struct Link { pub title: String, @@ -39,8 +38,7 @@ impl Link { pub fn into_urllink(self) -> Result { Url::parse(&self.link[..]) .map(move |link| UrlLink { title: self.title, link: link, }) - .map_err(Box::new) - .map_err(|e| MEK::LinkParsingError.into_error_with_cause(e)) + .chain_err(|| MEK::LinkParsingError) } } diff --git a/lib/entry/libimagentrymarkdown/src/result.rs b/lib/entry/libimagentrymarkdown/src/result.rs deleted file mode 100644 index f00a3122..00000000 --- a/lib/entry/libimagentrymarkdown/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::MarkdownError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentryref/Cargo.toml b/lib/entry/libimagentryref/Cargo.toml index 2ca29040..c6a89b7c 100644 --- a/lib/entry/libimagentryref/Cargo.toml +++ b/lib/entry/libimagentryref/Cargo.toml @@ -19,6 +19,7 @@ log = "0.3" rust-crypto = "0.2" toml = "^0.4" toml-query = "0.3.0" +error-chain = "0.10" walkdir = "1.0.*" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/entry/libimagentryref/src/error.rs b/lib/entry/libimagentryref/src/error.rs index 56c1e869..b826c7ca 100644 --- a/lib/entry/libimagentryref/src/error.rs +++ b/lib/entry/libimagentryref/src/error.rs @@ -17,39 +17,135 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(RefError, RefErrorKind, - StoreReadError => "Store read error", - StoreWriteError => "Store write error", - IOError => "IO Error", - UTF8Error => "UTF8 Error", - StoreIdError => "Error with storeid", - HeaderTomlError => "Error while working with TOML Header", - HeaderTypeError => "Header type error", - HeaderFieldMissingError => "Header field missing error", - HeaderFieldWriteError => "Header field cannot be written", - HeaderFieldReadError => "Header field cannot be read", - HeaderFieldAlreadyExistsError => "Header field already exists, cannot override", - PathUTF8Error => "Path cannot be converted because of UTF8 Error", - PathHashingError => "Path cannot be hashed", - PathCanonicalizationError => "Path cannot be canonicalized", +error_chain! { + types { + RefError, RefErrorKind, ResultExt, Result; + } - TypeConversionError => "Couldn't convert types", - RefToDisplayError => "Cannot convert Ref to string to show it to user", + links { + ListError(::libimagentrylist::error::ListError, ::libimagentrylist::error::ListErrorKind); + } - RefNotInStore => "Ref/StoreId does not exist in store", + foreign_links { + Io(::std::io::Error); + } - RefTargetDoesNotExist => "Ref Target does not exist", - RefTargetPermissionError => "Ref Target permissions insufficient for referencing", - RefTargetCannotBeHashed => "Ref Target cannot be hashed (is it a directory?)", - RefTargetFileCannotBeOpened => "Ref Target File cannot be open()ed", - RefTargetCannotReadPermissions => "Ref Target: Cannot read permissions", + errors { + StoreReadError { + description("Store read error") + display("Store read error") + } - RefHashingError => "Error while hashing" - ); -); + StoreWriteError { + description("Store write error") + display("Store write error") + } -pub use self::error::RefError; -pub use self::error::RefErrorKind; -pub use self::error::MapErrInto; + IOError { + description("IO Error") + display("IO Error") + } + + UTF8Error { + description("UTF8 Error") + display("UTF8 Error") + } + + StoreIdError { + description("Error with storeid") + display("Error with storeid") + } + + HeaderTomlError { + description("Error while working with TOML Header") + display("Error while working with TOML Header") + } + + HeaderTypeError { + description("Header type error") + display("Header type error") + } + + HeaderFieldMissingError { + description("Header field missing error") + display("Header field missing error") + } + + HeaderFieldWriteError { + description("Header field cannot be written") + display("Header field cannot be written") + } + + HeaderFieldReadError { + description("Header field cannot be read") + display("Header field cannot be read") + } + + HeaderFieldAlreadyExistsError { + description("Header field already exists, cannot override") + display("Header field already exists, cannot override") + } + + PathUTF8Error { + description("Path cannot be converted because of UTF8 Error") + display("Path cannot be converted because of UTF8 Error") + } + + PathHashingError { + description("Path cannot be hashed") + display("Path cannot be hashed") + } + + PathCanonicalizationError { + description("Path cannot be canonicalized") + display("Path cannot be canonicalized") + } + + TypeConversionError { + description("Couldn't convert types") + display("Couldn't convert types") + } + + RefToDisplayError { + description("Cannot convert Ref to string to show it to user") + display("Cannot convert Ref to string to show it to user") + } + + RefNotInStore { + description("Ref/StoreId does not exist in store") + display("Ref/StoreId does not exist in store") + } + + RefTargetDoesNotExist { + description("Ref Target does not exist") + display("Ref Target does not exist") + } + + RefTargetPermissionError { + description("Ref Target permissions insufficient for referencing") + display("Ref Target permissions insufficient for referencing") + } + + RefTargetCannotBeHashed { + description("Ref Target cannot be hashed (is it a directory?)") + display("Ref Target cannot be hashed (is it a directory?)") + } + + RefTargetFileCannotBeOpened { + description("Ref Target File cannot be open()ed") + display("Ref Target File cannot be open()ed") + } + + RefTargetCannotReadPermissions { + description("Ref Target: Cannot read permissions") + display("Ref Target: Cannot read permissions") + } + + RefHashingError { + description("Error while hashing") + display("Error while hashing") + } + + } +} diff --git a/lib/entry/libimagentryref/src/flags.rs b/lib/entry/libimagentryref/src/flags.rs index b3b6851c..53b41540 100644 --- a/lib/entry/libimagentryref/src/flags.rs +++ b/lib/entry/libimagentryref/src/flags.rs @@ -22,7 +22,8 @@ use std::collections::BTreeMap; use toml::Value; use error::RefErrorKind as REK; -use result::Result; +use error::ResultExt; +use error::Result; pub struct RefFlags { content_hashing: bool, @@ -38,10 +39,9 @@ impl RefFlags { pub fn read(v: &Value) -> Result { fn get_field(v: &Value, key: &str) -> Result { use toml_query::read::TomlValueReadExt; - use error::MapErrInto; v.read(key) - .map_err_into(REK::HeaderTomlError) + .chain_err(|| REK::HeaderTomlError) .and_then(|toml| match toml { Some(&Value::Boolean(b)) => Ok(b), Some(_) => Err(REK::HeaderTypeError.into()), diff --git a/lib/entry/libimagentryref/src/hasher.rs b/lib/entry/libimagentryref/src/hasher.rs index d29502d2..ad10f71e 100644 --- a/lib/entry/libimagentryref/src/hasher.rs +++ b/lib/entry/libimagentryref/src/hasher.rs @@ -21,12 +21,12 @@ use std::path::PathBuf; use std::io::Read; use error::RefErrorKind as REK; -use error::MapErrInto; +use error::ResultExt; use crypto::sha1::Sha1; use crypto::digest::Digest; -use result::Result; +use error::Result; /// The Hasher trait is used to implement custom hashing functions for the ref library. /// This means that one can define how the hash of a reference is constructed from the content of @@ -58,7 +58,7 @@ impl Hasher for DefaultHasher { fn create_hash(&mut self, _: &PathBuf, c: &mut R) -> Result { let mut s = String::new(); - try!(c.read_to_string(&mut s).map_err_into(REK::UTF8Error).map_err_into(REK::IOError)); + try!(c.read_to_string(&mut s).chain_err(|| REK::UTF8Error).chain_err(|| REK::IOError)); self.hasher.input_str(&s[..]); Ok(self.hasher.result_str()) } diff --git a/lib/entry/libimagentryref/src/hashers/nbytes.rs b/lib/entry/libimagentryref/src/hashers/nbytes.rs index 5d190840..ec232fd8 100644 --- a/lib/entry/libimagentryref/src/hashers/nbytes.rs +++ b/lib/entry/libimagentryref/src/hashers/nbytes.rs @@ -25,9 +25,9 @@ use crypto::sha1::Sha1; use crypto::digest::Digest; use hasher::Hasher; -use result::Result; +use error::Result; use error::RefErrorKind as REK; -use error::MapErrInto; +use error::ResultExt; pub struct NBytesHasher { hasher: Sha1, @@ -56,8 +56,8 @@ impl Hasher for NBytesHasher { .bytes() .take(self.n) .collect::, _>>() - .map_err_into(REK::IOError) - .and_then(|v| String::from_utf8(v).map_err_into(REK::UTF8Error))); + .chain_err(|| REK::IOError) + .and_then(|v| String::from_utf8(v).chain_err(|| REK::UTF8Error))); self.hasher.input_str(&s[..]); Ok(self.hasher.result_str()) } diff --git a/lib/entry/libimagentryref/src/lib.rs b/lib/entry/libimagentryref/src/lib.rs index 011ba433..2ef25567 100644 --- a/lib/entry/libimagentryref/src/lib.rs +++ b/lib/entry/libimagentryref/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -41,8 +43,9 @@ extern crate toml_query; extern crate walkdir; #[macro_use] extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagentrylist; +#[macro_use] extern crate error_chain; module_entry_path_mod!("ref"); @@ -53,5 +56,4 @@ pub mod hashers; pub mod lister; pub mod reference; pub mod refstore; -pub mod result; mod util; diff --git a/lib/entry/libimagentryref/src/lister.rs b/lib/entry/libimagentryref/src/lister.rs index af843327..0cf4d5bc 100644 --- a/lib/entry/libimagentryref/src/lister.rs +++ b/lib/entry/libimagentryref/src/lister.rs @@ -23,15 +23,13 @@ use std::io::Write; use std::ops::Deref; use libimagentrylist::lister::Lister; -use libimagentrylist::result::Result; +use libimagentrylist::error::Result; use libimagerror::trace::trace_error; use libimagstore::store::FileLockEntry; use libimagentrylist::error::ListErrorKind as LEK; use libimagentrylist::error as lerror; use reference::Ref; -use error::MapErrInto; -use error::RefErrorKind as REK; pub struct RefLister { check_dead: bool, @@ -91,7 +89,7 @@ impl Lister for RefLister { debug!("Listing Entry: {:?}", entry); { let is_dead = if self.check_dead { - if try!(entry.fs_link_exists()) { + if try!(lerror::ResultExt::chain_err(entry.fs_link_exists(), || LEK::FormatError)) { "dead" } else { "alive" @@ -127,15 +125,14 @@ impl Lister for RefLister { entry.get_location())) } .and_then(|s| { - lerror::MapErrInto::map_err_into(write!(stdout(), "{}\n", s), LEK::FormatError) + lerror::ResultExt::chain_err(write!(stdout(), "{}\n", s), || LEK::FormatError) }) - .map_err_into(REK::RefToDisplayError) }) .map(|_| ()); (r, i + 1) }); debug!("Iterated over {} entries", n); - lerror::MapErrInto::map_err_into(r, LEK::FormatError) + r } } diff --git a/lib/entry/libimagentryref/src/reference.rs b/lib/entry/libimagentryref/src/reference.rs index 3dd196ba..049b83d5 100644 --- a/lib/entry/libimagentryref/src/reference.rs +++ b/lib/entry/libimagentryref/src/reference.rs @@ -25,15 +25,15 @@ use std::fs::File; use std::fs::Permissions; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use toml::Value; use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; use error::RefErrorKind as REK; -use error::MapErrInto; -use result::Result; +use error::RefError as RE; +use error::ResultExt; +use error::Result; use hasher::*; pub trait Ref { @@ -121,13 +121,13 @@ impl Ref for Entry { self.get_location() .clone() .into_pathbuf() - .map_err_into(REK::StoreIdError) + .chain_err(|| REK::StoreIdError) .and_then(|pb| { pb.file_name() .and_then(|osstr| osstr.to_str()) .and_then(|s| s.split("~").next()) .map(String::from) - .ok_or(REK::StoreIdError.into_error()) + .ok_or(RE::from_kind(REK::StoreIdError)) }) } @@ -144,13 +144,13 @@ impl Ref for Entry { Ok(Some(&Value::String(ref s))) => Ok(s.clone()), // content hash header field has wrong type - Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()), + Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)), // content hash not stored - Ok(None) => Err(REK::HeaderFieldMissingError.into_error()), + Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)), // Error - Err(e) => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))), + Err(e) => Err(e).chain_err(|| REK::StoreReadError), } } @@ -163,7 +163,11 @@ impl Ref for Entry { /// custom hasher fn get_current_hash_with_hasher(&self, mut h: H) -> Result { self.fs_file() - .and_then(|pb| File::open(pb.clone()).map(|f| (pb, f)).map_err_into(REK::IOError)) + .and_then(|pb| { + File::open(pb.clone()) + .map(|f| (pb, f)) + .chain_err(|| REK::IOError) + }) .and_then(|(path, mut file)| h.create_hash(&path, &mut file)) } @@ -206,16 +210,16 @@ impl Ref for Entry { self .get_header() .read("ref.permissions.ro") - .map_err_into(REK::HeaderFieldReadError) + .chain_err(|| REK::HeaderFieldReadError) .and_then(|ro| { match ro { Some(&Value::Boolean(b)) => Ok(b), - Some(_) => Err(REK::HeaderTypeError.into_error()), - None => Err(REK::HeaderFieldMissingError.into_error()), + Some(_) => Err(RE::from_kind(REK::HeaderTypeError)), + None => Err(RE::from_kind(REK::HeaderFieldMissingError)), } }) .and_then(|ro| self.get_current_permissions().map(|perm| ro == perm.readonly())) - .map_err_into(REK::RefTargetCannotReadPermissions) + .chain_err(|| REK::RefTargetCannotReadPermissions) } /// Check whether the Hashsum of the referenced file is equal to the stored hashsum @@ -240,13 +244,13 @@ impl Ref for Entry { try!(self .get_header_mut() .set("ref.permissions.ro", Value::Boolean(current_perm.readonly())) - .map_err_into(REK::StoreWriteError) + .chain_err(|| REK::StoreWriteError) ); try!(self .get_header_mut() .set(&format!("ref.content_hash.{}", h.hash_name())[..], Value::String(current_hash)) - .map_err_into(REK::StoreWriteError) + .chain_err(|| REK::StoreWriteError) ); Ok(()) @@ -256,9 +260,9 @@ impl Ref for Entry { fn fs_file(&self) -> Result { match self.get_header().read("ref.path") { Ok(Some(&Value::String(ref s))) => Ok(PathBuf::from(s)), - Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()), - Ok(None) => Err(REK::HeaderFieldMissingError.into_error()), - Err(e) => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))), + Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)), + Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)), + Err(e) => Err(e).chain_err(|| REK::StoreReadError), } } @@ -296,11 +300,11 @@ impl Ref for Entry { .into_iter() .map(|entry| { entry - .map_err_into(REK::IOError) + .chain_err(|| REK::IOError) .and_then(|entry| { let pb = PathBuf::from(entry.path()); File::open(entry.path()) - .map_err_into(REK::IOError) + .chain_err(|| REK::IOError) .map(|f| (pb, f)) }) .and_then(|(p, mut f)| h.create_hash(&p, &mut f).map(|h| (p, h))) @@ -311,7 +315,7 @@ impl Ref for Entry { None } }) - .map_err_into(REK::IOError) + .chain_err(|| REK::IOError) }) .filter_map(|e| e.ok()) .filter_map(|e| e) @@ -319,19 +323,22 @@ impl Ref for Entry { }) .flatten() .next() - .ok_or(REK::RefTargetDoesNotExist.into_error()) + .ok_or(RE::from_kind(REK::RefTargetDoesNotExist)) }) } /// Get the permissions of the file which are present fn get_current_permissions(&self) -> Result { self.fs_file() - .and_then(|pb| File::open(pb).map_err_into(REK::HeaderFieldReadError)) + .and_then(|pb| { + File::open(pb) + .chain_err(|| REK::HeaderFieldReadError) + }) .and_then(|file| { file .metadata() .map(|md| md.permissions()) - .map_err_into(REK::RefTargetCannotReadPermissions) + .chain_err(|| REK::RefTargetCannotReadPermissions) }) } diff --git a/lib/entry/libimagentryref/src/refstore.rs b/lib/entry/libimagentryref/src/refstore.rs index e8ec1edd..b005a665 100644 --- a/lib/entry/libimagentryref/src/refstore.rs +++ b/lib/entry/libimagentryref/src/refstore.rs @@ -25,14 +25,14 @@ use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; use libimagstore::store::Store; -use libimagerror::into::IntoError; use toml::Value; use error::RefErrorKind as REK; -use error::MapErrInto; +use error::RefError as RE; +use error::ResultExt; +use error::Result; use flags::RefFlags; -use result::Result; use hasher::*; use module_path::ModuleEntryPath; use util::*; @@ -68,13 +68,13 @@ impl RefStore for Store { /// Check whether there is a reference to the file at `pb` fn exists(&self, pb: PathBuf) -> Result { pb.canonicalize() - .map_err_into(REK::PathCanonicalizationError) + .chain_err(|| REK::PathCanonicalizationError) .and_then(|c| hash_path(&c)) - .map_err_into(REK::PathHashingError) + .chain_err(|| REK::PathHashingError) .and_then(|hash| { self.retrieve_for_module("ref") .map(|iter| (hash, iter)) - .map_err_into(REK::StoreReadError) + .chain_err(|| REK::StoreReadError) }) .and_then(|(hash, possible_refs)| { // This is kind of a manual Iterator::filter() call what we do here, but with the @@ -83,7 +83,7 @@ impl RefStore for Store { // take this note as a todo. for r in possible_refs { let contains_hash = try!(r.to_str() - .map_err_into(REK::TypeConversionError) + .chain_err(|| REK::TypeConversionError) .map(|s| s.contains(&hash[..])) ); @@ -98,8 +98,8 @@ impl RefStore for Store { } }, - Ok(None) => return Err(REK::StoreReadError.into_error()), - Err(e) => return Err(e).map_err_into(REK::StoreReadError) + Ok(None) => return Err(RE::from_kind(REK::StoreReadError)), + Err(e) => return Err(e).chain_err(|| REK::StoreReadError) } } @@ -110,8 +110,8 @@ impl RefStore for Store { /// Try to get `si` as Ref object from the store fn get<'a>(&'a self, si: StoreId) -> Result> { match self.get(si) { - Err(e) => return Err(e).map_err_into(REK::StoreReadError), - Ok(None) => return Err(REK::RefNotInStore.into_error()), + Err(e) => return Err(e).chain_err(|| REK::StoreReadError), + Ok(None) => return Err(RE::from_kind(REK::RefNotInStore)), Ok(Some(fle)) => Ok(fle), } } @@ -123,7 +123,7 @@ impl RefStore for Store { ModuleEntryPath::new(hash) .into_storeid() .and_then(|id| self.get(id)) - .map_err_into(REK::StoreReadError) + .chain_err(|| REK::StoreReadError) } /// Delete a ref by hash @@ -133,7 +133,7 @@ impl RefStore for Store { ModuleEntryPath::new(hash) .into_storeid() .and_then(|id| self.delete(id)) - .map_err_into(REK::StoreWriteError) + .chain_err(|| REK::StoreWriteError) } /// Create a Ref object which refers to `pb` @@ -147,15 +147,15 @@ impl RefStore for Store { use toml_query::insert::TomlValueInsertExt; if !pb.exists() { - return Err(REK::RefTargetDoesNotExist.into_error()); + return Err(RE::from_kind(REK::RefTargetDoesNotExist)); } if flags.get_content_hashing() && pb.is_dir() { - return Err(REK::RefTargetCannotBeHashed.into_error()); + return Err(RE::from_kind(REK::RefTargetCannotBeHashed)); } let (mut fle, content_hash, permissions, canonical_path) = { // scope to be able to fold try!(File::open(pb.clone()) - .map_err_into(REK::RefTargetFileCannotBeOpened) + .chain_err(|| REK::RefTargetFileCannotBeOpened) // If we were able to open this file, // we hash the contents of the file and return (file, hash) @@ -176,7 +176,7 @@ impl RefStore for Store { Some(try!(file .metadata() .map(|md| md.permissions()) - .map_err_into(REK::RefTargetCannotReadPermissions) + .chain_err(|| REK::RefTargetCannotReadPermissions) )) } else { None @@ -192,13 +192,13 @@ impl RefStore for Store { pb.canonicalize() .map(|can| (opt_contenthash, opt_permissions, can)) // if PathBuf::canonicalize() failed, build an error from the return value - .map_err_into(REK::PathCanonicalizationError) + .chain_err(|| REK::PathCanonicalizationError) }) // and then we hash the canonicalized path // and return (file, content hash, permissions, canonicalized path, path hash) .and_then(|(opt_contenthash, opt_permissions, can)| { - let path_hash = try!(hash_path(&can).map_err_into(REK::PathHashingError)); + let path_hash = try!(hash_path(&can).chain_err(|| REK::PathHashingError)); Ok((opt_contenthash, opt_permissions, can, path_hash)) }) @@ -210,7 +210,7 @@ impl RefStore for Store { .and_then(|(opt_conhash, opt_perm, can, path_hash)| { match can.to_str().map(String::from) { // UTF convert error in PathBuf::to_str(), - None => Err(REK::PathUTF8Error.into_error()), + None => Err(RE::from_kind(REK::PathUTF8Error)), Some(can) => Ok((opt_conhash, opt_perm, can, path_hash)) } }) @@ -220,7 +220,7 @@ impl RefStore for Store { .and_then(|(opt_conhash, opt_perm, can, path_hash)| { let fle = try!(self .create(ModuleEntryPath::new(path_hash)) - .map_err_into(REK::StoreWriteError) + .chain_err(|| REK::StoreWriteError) ); Ok((fle, opt_conhash, opt_perm, can)) @@ -246,14 +246,13 @@ impl RefStore for Store { &Some((ref s, ref v)) => { match fle.get_header_mut().insert(s, v.clone()) { Ok(Some(_)) => { - let e = REK::HeaderFieldAlreadyExistsError.into_error(); - return Err(e).map_err_into(REK::HeaderFieldWriteError); + let e = RE::from_kind(REK::HeaderFieldAlreadyExistsError); + return Err(e).chain_err(|| REK::HeaderFieldWriteError); }, Ok(None) => { // Okay, we just inserted a new header value... }, - Err(e) => return Err(e).map_err_into(REK::HeaderFieldWriteError), - _ => (), + Err(e) => return Err(e).chain_err(|| REK::HeaderFieldWriteError), } } &None => { diff --git a/lib/entry/libimagentryref/src/result.rs b/lib/entry/libimagentryref/src/result.rs deleted file mode 100644 index eefcec65..00000000 --- a/lib/entry/libimagentryref/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::RefError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentryref/src/util.rs b/lib/entry/libimagentryref/src/util.rs index 7f9a4730..c69e4d48 100644 --- a/lib/entry/libimagentryref/src/util.rs +++ b/lib/entry/libimagentryref/src/util.rs @@ -20,10 +20,11 @@ use std::path::PathBuf; use error::RefErrorKind as REK; -use result::Result; +use error::RefError as RE; +use error::Result; +use error::ResultExt; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use toml::Value; use toml_query::read::TomlValueReadExt; @@ -40,7 +41,7 @@ pub fn hash_path(pb: &PathBuf) -> Result { hasher.input_str(s); Ok(hasher.result_str()) }, - None => return Err(REK::PathUTF8Error.into_error()), + None => return Err(RE::from_kind(REK::PathUTF8Error)), } } @@ -48,9 +49,9 @@ pub fn hash_path(pb: &PathBuf) -> Result { pub fn read_reference(refentry: &Entry) -> Result { match refentry.get_header().read("ref.path") { Ok(Some(&Value::String(ref s))) => Ok(PathBuf::from(s)), - Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()), - Ok(None) => Err(REK::HeaderFieldMissingError.into_error()), - Err(e) => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))), + Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)), + Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)), + Err(e) => Err(e).chain_err(|| REK::StoreReadError), } } diff --git a/lib/entry/libimagentrytag/Cargo.toml b/lib/entry/libimagentrytag/Cargo.toml index e80aeed6..c9e3d099 100644 --- a/lib/entry/libimagentrytag/Cargo.toml +++ b/lib/entry/libimagentrytag/Cargo.toml @@ -22,6 +22,7 @@ itertools = "0.5" is-match = "0.1" filters = "0.1" toml-query = "0.3.0" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrytag/src/error.rs b/lib/entry/libimagentrytag/src/error.rs index 579e3ce8..453901dd 100644 --- a/lib/entry/libimagentrytag/src/error.rs +++ b/lib/entry/libimagentrytag/src/error.rs @@ -17,16 +17,32 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(TagError, TagErrorKind, - TagTypeError => "Entry Header Tag Type wrong", - HeaderReadError => "Error while reading entry header", - HeaderWriteError => "Error while writing entry header", - NotATag => "String is not a tag" - ); -); +error_chain! { + types { + TagError, TagErrorKind, ResultExt, Result; + } -pub use self::error::TagError; -pub use self::error::TagErrorKind; -pub use self::error::MapErrInto; + errors { + TagTypeError { + description("Entry Header Tag Type wrong") + display("Entry Header Tag Type wrong") + } + + HeaderReadError { + description("Error while reading entry header") + display("Error while reading entry header") + } + + HeaderWriteError { + description("Error while writing entry header") + display("Error while writing entry header") + } + + NotATag { + description("String is not a tag") + display("String is not a tag") + } + + } +} diff --git a/lib/entry/libimagentrytag/src/lib.rs b/lib/entry/libimagentrytag/src/lib.rs index cfa68373..2a191486 100644 --- a/lib/entry/libimagentrytag/src/lib.rs +++ b/lib/entry/libimagentrytag/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -41,12 +43,12 @@ extern crate toml; extern crate toml_query; #[macro_use] extern crate is_match; extern crate filters; +#[macro_use] extern crate error_chain; extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; pub mod error; -pub mod result; pub mod tag; pub mod tagable; diff --git a/lib/entry/libimagentrytag/src/result.rs b/lib/entry/libimagentrytag/src/result.rs deleted file mode 100644 index 02d72766..00000000 --- a/lib/entry/libimagentrytag/src/result.rs +++ /dev/null @@ -1,25 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::TagError; - -pub type Result = RResult; - diff --git a/lib/entry/libimagentrytag/src/tagable.rs b/lib/entry/libimagentrytag/src/tagable.rs index 1a182e57..65c3275d 100644 --- a/lib/entry/libimagentrytag/src/tagable.rs +++ b/lib/entry/libimagentrytag/src/tagable.rs @@ -20,14 +20,14 @@ use itertools::Itertools; use libimagstore::store::Entry; -use libimagerror::into::IntoError; use toml_query::read::TomlValueReadExt; use toml_query::set::TomlValueSetExt; use error::TagErrorKind; -use error::MapErrInto; -use result::Result; +use error::TagError as TE; +use error::ResultExt; +use error::Result; use tag::{Tag, TagSlice}; use tag::is_tag_str; @@ -49,7 +49,7 @@ pub trait Tagable { impl Tagable for Value { fn get_tags(&self) -> Result> { - let tags = try!(self.read("imag.tags").map_err_into(TagErrorKind::HeaderReadError)); + let tags = try!(self.read("imag.tags").chain_err(|| TagErrorKind::HeaderReadError)); match tags { Some(&Value::Array(ref tags)) => { @@ -87,12 +87,11 @@ impl Tagable for Value { let a = ts.iter().unique().map(|t| Value::String(t.clone())).collect(); self.set("imag.tags", Value::Array(a)) .map(|_| ()) - .map_err(Box::new) - .map_err(|e| TagErrorKind::HeaderWriteError.into_error_with_cause(e)) + .chain_err(|| TagErrorKind::HeaderWriteError) } fn add_tag(&mut self, t: Tag) -> Result<()> { - if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TagErrorKind::NotATag.into_error())) { + if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TE::from_kind(TagErrorKind::NotATag))) { debug!("Not a tag: '{}'", t); return Err(TagErrorKind::NotATag.into()); } @@ -106,7 +105,7 @@ impl Tagable for Value { } fn remove_tag(&mut self, t: Tag) -> Result<()> { - if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TagErrorKind::NotATag.into_error())) { + if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TE::from_kind(TagErrorKind::NotATag))) { debug!("Not a tag: '{}'", t); return Err(TagErrorKind::NotATag.into()); } @@ -120,7 +119,7 @@ impl Tagable for Value { } fn has_tag(&self, t: TagSlice) -> Result { - let tags = try!(self.read("imag.tags").map_err_into(TagErrorKind::HeaderReadError)); + let tags = try!(self.read("imag.tags").chain_err(|| TagErrorKind::HeaderReadError)); if !tags.iter().all(|t| is_match!(*t, &Value::String(_))) { return Err(TagErrorKind::TagTypeError.into()); diff --git a/lib/entry/libimagentryview/Cargo.toml b/lib/entry/libimagentryview/Cargo.toml index 42536398..315958a4 100644 --- a/lib/entry/libimagentryview/Cargo.toml +++ b/lib/entry/libimagentryview/Cargo.toml @@ -16,6 +16,7 @@ homepage = "http://imag-pim.org" [dependencies] log = "0.3" toml = "^0.4" +error-chain = "0.10" libimagrt = { version = "0.4.0", path = "../../../lib/core/libimagrt" } libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } diff --git a/lib/entry/libimagentryview/src/builtin/editor.rs b/lib/entry/libimagentryview/src/builtin/editor.rs index 259d4986..abfe0ed2 100644 --- a/lib/entry/libimagentryview/src/builtin/editor.rs +++ b/lib/entry/libimagentryview/src/builtin/editor.rs @@ -22,9 +22,9 @@ use libimagrt::runtime::Runtime; use libimagentryedit::edit::edit_in_tmpfile; use viewer::Viewer; -use result::Result; +use error::Result; +use error::ResultExt; use error::ViewErrorKind as VEK; -use error::ViewError as VE; pub struct EditorView<'a>(&'a Runtime<'a>); @@ -37,8 +37,7 @@ impl<'a> EditorView<'a> { impl<'a> Viewer for EditorView<'a> { fn view_entry(&self, e: &Entry) -> Result<()> { let mut entry = e.to_str().clone().to_string(); - edit_in_tmpfile(self.0, &mut entry) - .map_err(|e| VE::new(VEK::ViewError, Some(Box::new(e)))) + edit_in_tmpfile(self.0, &mut entry).chain_err(|| VEK::ViewError) } } diff --git a/lib/entry/libimagentryview/src/builtin/plain.rs b/lib/entry/libimagentryview/src/builtin/plain.rs index f40b2527..c5c3a2a1 100644 --- a/lib/entry/libimagentryview/src/builtin/plain.rs +++ b/lib/entry/libimagentryview/src/builtin/plain.rs @@ -20,7 +20,7 @@ use libimagstore::store::Entry; use viewer::Viewer; -use result::Result; +use error::Result; pub struct PlainViewer { show_header: bool diff --git a/lib/entry/libimagentryview/src/builtin/stdout.rs b/lib/entry/libimagentryview/src/builtin/stdout.rs index 3d9fea05..20872ae6 100644 --- a/lib/entry/libimagentryview/src/builtin/stdout.rs +++ b/lib/entry/libimagentryview/src/builtin/stdout.rs @@ -22,7 +22,7 @@ use libimagstore::store::Entry; use toml::ser::to_string; use viewer::Viewer; -use result::Result; +use error::Result; pub struct StdoutViewer { view_header: bool, diff --git a/lib/entry/libimagentryview/src/error.rs b/lib/entry/libimagentryview/src/error.rs index c471b3f3..c742d046 100644 --- a/lib/entry/libimagentryview/src/error.rs +++ b/lib/entry/libimagentryview/src/error.rs @@ -17,16 +17,37 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(ViewError, ViewErrorKind, - Unknown => "Unknown view error", - GlobError => "Error while glob()ing", - PatternError => "Error in glob() pattern", - PatternBuildingError => "Could not build glob() pattern", - ViewError => "Failed to start viewer" - ); -); +error_chain! { + types { + ViewError, ViewErrorKind, ResultExt, Result; + } + + errors { + Unknown { + description("Unknown view error") + display("Unknown view error") + } + + GlobError { + description("Error while glob()ing") + display("Error while glob()ing") + } + + PatternError { + description("Error in glob() pattern") + display("Error in glob() pattern") + } + + PatternBuildingError { + description("Could not build glob() pattern") + display("Could not build glob() pattern") + } + + ViewError { + description("Failed to start viewer") + display("Failed to start viewer") + } + + } +} -pub use self::error::ViewError; -pub use self::error::ViewErrorKind; -pub use self::error::MapErrInto; diff --git a/lib/entry/libimagentryview/src/lib.rs b/lib/entry/libimagentryview/src/lib.rs index 1aefc2eb..4ce6d2d0 100644 --- a/lib/entry/libimagentryview/src/lib.rs +++ b/lib/entry/libimagentryview/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -34,14 +36,14 @@ )] extern crate toml; +#[macro_use] extern crate error_chain; extern crate libimagstore; extern crate libimagrt; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; extern crate libimagentryedit; pub mod error; pub mod builtin; -pub mod result; pub mod viewer; diff --git a/lib/entry/libimagentryview/src/result.rs b/lib/entry/libimagentryview/src/result.rs deleted file mode 100644 index 3650b1fe..00000000 --- a/lib/entry/libimagentryview/src/result.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::ViewError; - -pub type Result = RResult; diff --git a/lib/entry/libimagentryview/src/viewer.rs b/lib/entry/libimagentryview/src/viewer.rs index 35763126..aad541c1 100644 --- a/lib/entry/libimagentryview/src/viewer.rs +++ b/lib/entry/libimagentryview/src/viewer.rs @@ -19,7 +19,7 @@ use libimagstore::store::Entry; -use result::Result; +use error::Result; pub trait Viewer { diff --git a/lib/etc/libimaginteraction/Cargo.toml b/lib/etc/libimaginteraction/Cargo.toml index a72de4af..c409e9b8 100644 --- a/lib/etc/libimaginteraction/Cargo.toml +++ b/lib/etc/libimaginteraction/Cargo.toml @@ -21,6 +21,7 @@ lazy_static = "0.2.*" log = "0.3" regex = "0.2" toml = "^0.4" +error-chain = "0.10" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/etc/libimaginteraction/src/ask.rs b/lib/etc/libimaginteraction/src/ask.rs index 2a393d0e..96dbc560 100644 --- a/lib/etc/libimaginteraction/src/ask.rs +++ b/lib/etc/libimaginteraction/src/ask.rs @@ -24,9 +24,9 @@ use std::io::BufRead; use std::io::BufReader; use std::result::Result as RResult; -use error::InteractionError; use error::InteractionErrorKind; -use result::Result; +use error::ResultExt; +use error::Result; use regex::Regex; use ansi_term::Colour::*; @@ -163,7 +163,7 @@ fn ask_string_(s: &str, pub fn ask_select_from_list(list: &[&str]) -> Result { pick_from_list(default_menu_cmd().as_mut(), list, "Selection: ") - .map_err(|e| InteractionError::new(InteractionErrorKind::Unknown, Some(Box::new(e)))) + .chain_err(|| InteractionErrorKind::Unknown) } /// Helper function to print a imag question string. The `question` argument may not contain a diff --git a/lib/etc/libimaginteraction/src/error.rs b/lib/etc/libimaginteraction/src/error.rs index 1a4be7df..28345c94 100644 --- a/lib/etc/libimaginteraction/src/error.rs +++ b/lib/etc/libimaginteraction/src/error.rs @@ -17,23 +17,67 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -generate_error_module!( - generate_error_types!(InteractionError, InteractionErrorKind, - Unknown => "Unknown Error", - CLIError => "Error on commandline", - IdMissingError => "Commandline: ID missing", - StoreIdParsingError => "Error while parsing StoreId", - IdSelectingError => "Error while selecting id", - ConfigError => "Configuration error", - ConfigMissingError => "Configuration missing", - ConfigTypeError => "Config Type Error", - NoConfigError => "No configuration", - ReadlineHistoryFileCreationError => "Could not create history file for readline", - ReadlineError => "Readline error" - ); -); +error_chain! { + types { + InteractionError, InteractionErrorKind, ResultExt, Result; + } -pub use self::error::InteractionError; -pub use self::error::InteractionErrorKind; -pub use self::error::MapErrInto; + errors { + Unknown { + description("Unknown Error") + display("Unknown Error") + } + + CLIError { + description("Error on commandline") + display("Error on commandline") + } + + IdMissingError { + description("Commandline: ID missing") + display("Commandline: ID missing") + } + + StoreIdParsingError { + description("Error while parsing StoreId") + display("Error while parsing StoreId") + } + + IdSelectingError { + description("Error while selecting id") + display("Error while selecting id") + } + + ConfigError { + description("Configuration error") + display("Configuration error") + } + + ConfigMissingError { + description("Configuration missing") + display("Configuration missing") + } + + ConfigTypeError { + description("Config Type Error") + display("Config Type Error") + } + + NoConfigError { + description("No configuration") + display("No configuration") + } + + ReadlineHistoryFileCreationError { + description("Could not create history file for readline") + display("Could not create history file for readline") + } + + ReadlineError { + description("Readline error") + display("Readline error") + } + + } +} diff --git a/lib/etc/libimaginteraction/src/lib.rs b/lib/etc/libimaginteraction/src/lib.rs index cd38071a..0a2aa118 100644 --- a/lib/etc/libimaginteraction/src/lib.rs +++ b/lib/etc/libimaginteraction/src/lib.rs @@ -17,6 +17,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +#![recursion_limit="256"] + #![deny( dead_code, non_camel_case_types, @@ -39,13 +41,13 @@ extern crate ansi_term; extern crate regex; extern crate clap; extern crate toml; +#[macro_use] extern crate error_chain; extern crate libimagstore; -#[macro_use] extern crate libimagerror; +extern crate libimagerror; pub mod ask; pub mod error; pub mod filter; -pub mod result; pub mod ui; diff --git a/lib/etc/libimaginteraction/src/readline.rs b/lib/etc/libimaginteraction/src/readline.rs index 7b998dd0..7d498ce5 100644 --- a/lib/etc/libimaginteraction/src/readline.rs +++ b/lib/etc/libimaginteraction/src/readline.rs @@ -17,8 +17,9 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use error::InteractionError as IE; use error::InteractionErrorKind as IEK; -use error::MapErrInto; +use error::ResultExt; use toml::Value; @@ -44,37 +45,37 @@ impl Readline { let histfile = try!(match histfile { Value::String(s) => PathBuf::from(s), - _ => Err(IEK::ConfigTypeError.into_error()) - .map_err_into(IEK::ConfigError) - .map_err_into(IEK::ReadlineError) + _ => Err(IE::from_kind(IEK::ConfigTypeError)) + .chain_err(|| IEK::ConfigError) + .chain_err(|| IEK::ReadlineError) }); let histsize = try!(match histsize { Value::Integer(i) => i, - _ => Err(IEK::ConfigTypeError.into_error()) - .map_err_into(IEK::ConfigError) - .map_err_into(IEK::ReadlineError) + _ => Err(IE::from_kind(IEK::ConfigTypeError)) + .chain_err(|| IEK::ConfigError) + .chain_err(|| IEK::ReadlineError) }); let histigndups = try!(match histigndups { Value::Boolean(b) => b, - _ => Err(IEK::ConfigTypeError.into_error()) - .map_err_into(IEK::ConfigError) - .map_err_into(IEK::ReadlineError) + _ => Err(IE::from_kind(IEK::ConfigTypeError)) + .chain_err(|| IEK::ConfigError) + .chain_err(|| IEK::ReadlineError) }); let histignspace = try!(match histignspace { Value::Boolean(b) => b, - _ => Err(IEK::ConfigTypeError.into_error()) - .map_err_into(IEK::ConfigError) - .map_err_into(IEK::ReadlineError) + _ => Err(IE::from_kind(IEK::ConfigTypeError)) + .chain_err(|| IEK::ConfigError) + .chain_err(|| IEK::ReadlineError) }); let prompt = try!(match prompt { Value::String(s) => s, - _ => Err(IEK::ConfigTypeError.into_error()) - .map_err_into(IEK::ConfigError) - .map_err_into(IEK::ReadlineError) + _ => Err(IE::from_kind(IEK::ConfigTypeError)) + .chain_err(|| IEK::ConfigError) + .chain_err(|| IEK::ReadlineError) }); let config = Config::builder(). @@ -87,10 +88,10 @@ impl Readline { if !histfile.exists() { let _ = try!(File::create(histfile.clone()) - .map_err_into(IEK::ReadlineHistoryFileCreationError)); + .chain_err(|| IEK::ReadlineHistoryFileCreationError)); } - let _ = try!(editor.load_history(&histfile).map_err_into(ReadlineError)); + let _ = try!(editor.load_history(&histfile).chain_err(|| ReadlineError)); Ok(Readline { editor: editor, diff --git a/lib/etc/libimaginteraction/src/result.rs b/lib/etc/libimaginteraction/src/result.rs deleted file mode 100644 index 8eeaf47b..00000000 --- a/lib/etc/libimaginteraction/src/result.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer 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 std::result::Result as RResult; - -use error::InteractionError; - -pub type Result = RResult; diff --git a/lib/etc/libimaginteraction/src/ui.rs b/lib/etc/libimaginteraction/src/ui.rs index 49c4619d..d1712f94 100644 --- a/lib/etc/libimaginteraction/src/ui.rs +++ b/lib/etc/libimaginteraction/src/ui.rs @@ -22,11 +22,11 @@ use std::path::PathBuf; use clap::{Arg, ArgMatches}; use libimagstore::storeid::StoreId; -use libimagerror::into::IntoError; -use result::Result; -use error::MapErrInto; +use error::InteractionError as IE; +use error::Result; use error::InteractionErrorKind as IEK; +use error::ResultExt; pub fn id_argument<'a, 'b>() -> Arg<'a, 'b> { Arg::with_name(id_argument_name()) @@ -52,14 +52,14 @@ pub fn id_argument_long() -> &'static str { pub fn get_id(matches: &ArgMatches) -> Result> { matches .values_of(id_argument_name()) - .ok_or(IEK::IdMissingError.into_error()) - .map_err_into(IEK::CLIError) + .ok_or(IE::from_kind(IEK::IdMissingError)) + .chain_err(|| IEK::CLIError) .and_then(|vals| { vals.into_iter() .fold(Ok(vec![]), |acc, elem| { acc.and_then(|mut v| { let elem = StoreId::new_baseless(PathBuf::from(String::from(elem))); - let elem = try!(elem.map_err_into(IEK::StoreIdParsingError)); + let elem = try!(elem.chain_err(|| IEK::StoreIdParsingError)); v.push(elem); Ok(v) }) @@ -70,12 +70,12 @@ pub fn get_id(matches: &ArgMatches) -> Result> { pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Result> { use interactor::{pick_file, default_menu_cmd}; - match get_id(matches).map_err_into(IEK::IdSelectingError) { + match get_id(matches).chain_err(|| IEK::IdSelectingError) { Ok(v) => Ok(v), Err(_) => { let path = store_path.clone(); - let p = try!(pick_file(default_menu_cmd, path).map_err_into(IEK::IdSelectingError)); - let id = try!(StoreId::new_baseless(p).map_err_into(IEK::StoreIdParsingError)); + let p = try!(pick_file(default_menu_cmd, path).chain_err(|| IEK::IdSelectingError)); + let id = try!(StoreId::new_baseless(p).chain_err(|| IEK::StoreIdParsingError)); Ok(vec![id]) }, }