libimagentryref: Move from error-chain to failure

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2018-10-30 18:40:52 +01:00
parent 5a7def4c8e
commit 9b48dc27cd
7 changed files with 51 additions and 133 deletions

View file

@ -23,8 +23,8 @@ maintenance = { status = "actively-developed" }
itertools = "0.7" itertools = "0.7"
log = "0.4.0" log = "0.4.0"
toml = "0.4" toml = "0.4"
toml-query = "0.7" toml-query = { git = "https://github.com/matthiasbeyer/toml-query", branch = "failure" }
error-chain = "0.12" failure = "0.1"
sha-1 = { version = "0.7", optional = true } sha-1 = { version = "0.7", optional = true }
sha2 = { version = "0.7", optional = true } sha2 = { version = "0.7", optional = true }
sha3 = { version = "0.7", optional = true } sha3 = { version = "0.7", optional = true }

View file

@ -1,71 +0,0 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
error_chain! {
types {
RefError, RefErrorKind, ResultExt, Result;
}
links {
StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind);
TomlQueryError(::toml_query::error::Error, ::toml_query::error::ErrorKind);
EntryUtilError(::libimagentryutil::error::EntryUtilError, ::libimagentryutil::error::EntryUtilErrorKind);
}
foreign_links {
Io(::std::io::Error);
Utf8Error(::std::string::FromUtf8Error);
TomlDeError(::toml::de::Error);
TomlSerError(::toml::ser::Error);
}
errors {
HeaderTypeError(field: &'static str, expectedtype: &'static str) {
description("Header type error")
display("Header type error: '{}' should be {}", field, expectedtype)
}
HeaderFieldMissingError(field: &'static str) {
description("Header field missing error")
display("Header field missing: {}", field)
}
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")
}
}
}

View file

@ -21,27 +21,26 @@ use std::path::Path;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use error::RefError;
use refstore::UniqueRefPathGenerator; use refstore::UniqueRefPathGenerator;
use failure::Fallible as Result;
/// A base UniqueRefPathGenerator which must be overridden by the actual UniqueRefPathGenerator /// A base UniqueRefPathGenerator which must be overridden by the actual UniqueRefPathGenerator
/// which is provided by this crate /// which is provided by this crate
#[allow(dead_code)] #[allow(dead_code)]
pub struct Base; pub struct Base;
impl UniqueRefPathGenerator for Base { impl UniqueRefPathGenerator for Base {
type Error = RefError;
fn collection() -> &'static str { fn collection() -> &'static str {
"ref" "ref"
} }
fn unique_hash<A: AsRef<Path>>(_path: A) -> Result<String, Self::Error> { fn unique_hash<A: AsRef<Path>>(_path: A) -> Result<String> {
// This has to be overridden // This has to be overridden
panic!("Not overridden base functionality. This is a BUG!") panic!("Not overridden base functionality. This is a BUG!")
} }
fn postprocess_storeid(sid: StoreId) -> Result<StoreId, Self::Error> { fn postprocess_storeid(sid: StoreId) -> Result<StoreId> {
Ok(sid) // default implementation Ok(sid) // default implementation
} }
} }

View file

@ -50,24 +50,22 @@ macro_rules! make_unique_ref_path_generator {
( (
$name:ident $name:ident
over $underlying:ty over $underlying:ty
=> with error $errtype:ty
=> with collection name $collectionname:expr => with collection name $collectionname:expr
) => { ) => {
struct $name; struct $name;
impl $crate::refstore::UniqueRefPathGenerator for $name { impl $crate::refstore::UniqueRefPathGenerator for $name {
type Error = $errtype;
fn collection() -> &'static str { fn collection() -> &'static str {
$collectionname $collectionname
} }
fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String, Self::Error> { fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String> {
$underlying::unique_hash(path) $underlying::unique_hash(path)
} }
fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId) fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId)
-> Result<::libimagstore::storeid::StoreId, Self::Error> -> Result<::libimagstore::storeid::StoreId>
{ {
Ok(sid) Ok(sid)
} }
@ -77,7 +75,6 @@ macro_rules! make_unique_ref_path_generator {
( (
$name:ident $name:ident
over $underlying:ty over $underlying:ty
=> with error $errtype:ty
=> with collection name $collectionname:expr => with collection name $collectionname:expr
=> $impl:expr => $impl:expr
) => { ) => {
@ -90,13 +87,13 @@ macro_rules! make_unique_ref_path_generator {
$collectionname $collectionname
} }
fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String, Self::Error> { fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String> {
debug!("Making unique hash for path: {:?}", path.as_ref()); debug!("Making unique hash for path: {:?}", path.as_ref());
$impl(path) $impl(path)
} }
fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId) fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId)
-> Result<::libimagstore::storeid::StoreId, Self::Error> -> Result<::libimagstore::storeid::StoreId>
{ {
Ok(sid) Ok(sid)
} }
@ -106,14 +103,12 @@ macro_rules! make_unique_ref_path_generator {
( (
pub $name:ident pub $name:ident
over $underlying:ty over $underlying:ty
=> with error $errtype:ty
=> with collection name $collectionname:expr => with collection name $collectionname:expr
=> $impl:expr => $impl:expr
) => { ) => {
make_unique_ref_path_generator!( make_unique_ref_path_generator!(
pub $name pub $name
over $underlying over $underlying
=> with error $errtype
=> with collection name $collectionname => with collection name $collectionname
=> $impl => |sid| { Ok(sid) } => $impl => |sid| { Ok(sid) }
); );
@ -122,7 +117,6 @@ macro_rules! make_unique_ref_path_generator {
( (
pub $name:ident pub $name:ident
over $underlying:ty over $underlying:ty
=> with error $errtype:ty
=> with collection name $collectionname:expr => with collection name $collectionname:expr
=> $impl:expr => $impl:expr
=> $postproc:expr => $postproc:expr
@ -130,19 +124,17 @@ macro_rules! make_unique_ref_path_generator {
pub struct $name; pub struct $name;
impl $crate::refstore::UniqueRefPathGenerator for $name { impl $crate::refstore::UniqueRefPathGenerator for $name {
type Error = $errtype;
fn collection() -> &'static str { fn collection() -> &'static str {
$collectionname $collectionname
} }
fn unique_hash<A: AsRef<Path>>(path: A) -> ::std::result::Result<String, Self::Error> { fn unique_hash<A: AsRef<Path>>(path: A) -> ::failure::Fallible<String> {
debug!("Making unique hash for path: {:?}", path.as_ref()); debug!("Making unique hash for path: {:?}", path.as_ref());
$impl(path) $impl(path)
} }
fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId) fn postprocess_storeid(sid: ::libimagstore::storeid::StoreId)
-> Result<::libimagstore::storeid::StoreId, Self::Error> -> ::failure::Fallible<::libimagstore::storeid::StoreId>
{ {
$postproc(sid) $postproc(sid)
} }
@ -173,13 +165,10 @@ macro_rules! make_sha_mod {
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::Read; use std::io::Read;
use error::RefError as RE;
use hex; use hex;
make_unique_ref_path_generator! ( make_unique_ref_path_generator! (
pub $hashname pub $hashname
over generators::base::Base over generators::base::Base
=> with error RE
=> with collection name "ref" => with collection name "ref"
=> |path| { => |path| {
OpenOptions::new() OpenOptions::new()
@ -187,7 +176,7 @@ macro_rules! make_sha_mod {
.write(false) .write(false)
.create(false) .create(false)
.open(path) .open(path)
.map_err(RE::from) .map_err(::failure::Error::from)
.and_then(|mut file| { .and_then(|mut file| {
let mut buffer = String::new(); let mut buffer = String::new();
let _ = file.read_to_string(&mut buffer)?; let _ = file.read_to_string(&mut buffer)?;
@ -199,14 +188,14 @@ macro_rules! make_sha_mod {
impl $hashname { impl $hashname {
/// Function which can be used by a wrapping UniqueRefPathGenerator to hash only N bytes. /// Function which can be used by a wrapping UniqueRefPathGenerator to hash only N bytes.
pub fn hash_n_bytes<A: AsRef<Path>>(path: A, n: usize) -> Result<String, RE> { pub fn hash_n_bytes<A: AsRef<Path>>(path: A, n: usize) -> ::failure::Fallible<String> {
debug!("Opening '{}' for hashing", path.as_ref().display()); debug!("Opening '{}' for hashing", path.as_ref().display());
OpenOptions::new() OpenOptions::new()
.read(true) .read(true)
.write(false) .write(false)
.create(false) .create(false)
.open(path) .open(path)
.map_err(RE::from) .map_err(::failure::Error::from)
.and_then(|mut file| { .and_then(|mut file| {
let mut buffer = vec![0; n]; let mut buffer = vec![0; n];
debug!("Allocated {} bytes", buffer.capacity()); debug!("Allocated {} bytes", buffer.capacity());

View file

@ -43,11 +43,10 @@ extern crate toml_query;
#[macro_use] extern crate libimagstore; #[macro_use] extern crate libimagstore;
extern crate libimagerror; extern crate libimagerror;
#[macro_use] extern crate libimagentryutil; #[macro_use] extern crate libimagentryutil;
#[macro_use] extern crate error_chain; extern crate failure;
module_entry_path_mod!("ref"); module_entry_path_mod!("ref");
pub mod error;
pub mod reference; pub mod reference;
pub mod refstore; pub mod refstore;

View file

@ -22,21 +22,20 @@
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::result::Result as RResult;
use libimagentryutil::isa::Is; use libimagentryutil::isa::Is;
use libimagentryutil::isa::IsKindHeaderPathProvider; use libimagentryutil::isa::IsKindHeaderPathProvider;
use libimagstore::store::Entry; use libimagstore::store::Entry;
use libimagerror::errors::ErrorMsg as EM;
use toml::Value; use toml::Value;
use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadExt;
use toml_query::delete::TomlValueDeleteExt; use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt; use toml_query::insert::TomlValueInsertExt;
use failure::Fallible as Result;
use failure::Error;
use refstore::UniqueRefPathGenerator; use refstore::UniqueRefPathGenerator;
use error::Result;
use error::RefError as RE;
use error::RefErrorKind as REK;
pub trait Ref { pub trait Ref {
@ -57,7 +56,7 @@ pub trait Ref {
fn get_path(&self) -> Result<PathBuf>; fn get_path(&self) -> Result<PathBuf>;
/// Check whether the referenced file still matches its hash /// Check whether the referenced file still matches its hash
fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> RResult<bool, RPG::Error>; fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> Result<bool>;
fn remove_ref(&mut self) -> Result<()>; fn remove_ref(&mut self) -> Result<()>;
@ -84,15 +83,17 @@ impl Ref for Entry {
/// Check whether the underlying object is actually a ref /// Check whether the underlying object is actually a ref
fn is_ref(&self) -> Result<bool> { fn is_ref(&self) -> Result<bool> {
self.is::<IsRef>().map_err(From::from) self.is::<IsRef>().map_err(Error::from)
} }
fn get_hash(&self) -> Result<&str> { fn get_hash(&self) -> Result<&str> {
self.get_header() self.get_header()
.read("ref.hash") .read("ref.hash")
.map_err(RE::from)? .map_err(Error::from)?
.ok_or_else(|| REK::HeaderFieldMissingError("ref.hash").into()) .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.hash")))
.and_then(|v| v.as_str().ok_or_else(|| REK::HeaderTypeError("ref.hash", "string").into())) .and_then(|v| {
v.as_str().ok_or_else(|| Error::from(EM::EntryHeaderTypeError2("ref.hash", "string")))
})
} }
fn make_ref<P: AsRef<Path>>(&mut self, hash: String, path: P) -> Result<()> { fn make_ref<P: AsRef<Path>>(&mut self, hash: String, path: P) -> Result<()> {
@ -100,7 +101,7 @@ impl Ref for Entry {
.as_ref() .as_ref()
.to_str() .to_str()
.map(String::from) .map(String::from)
.ok_or_else(|| RE::from(REK::PathUTF8Error))?; .ok_or_else(|| EM::UTF8Error)?;
let _ = self.set_isflag::<IsRef>()?; let _ = self.set_isflag::<IsRef>()?;
let hdr = self.get_header_mut(); let hdr = self.get_header_mut();
@ -113,17 +114,20 @@ impl Ref for Entry {
fn get_path(&self) -> Result<PathBuf> { fn get_path(&self) -> Result<PathBuf> {
self.get_header() self.get_header()
.read("ref.path") .read("ref.path")
.map_err(RE::from)? .map_err(Error::from)?
.ok_or_else(|| REK::HeaderFieldMissingError("ref.path").into()) .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.path")))
.and_then(|v| v.as_str().ok_or_else(|| REK::HeaderTypeError("ref.path", "string").into())) .and_then(|v| {
v.as_str()
.ok_or_else(|| EM::EntryHeaderTypeError2("ref.path", "string"))
.map_err(Error::from)
})
.map(PathBuf::from) .map(PathBuf::from)
} }
fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> RResult<bool, RPG::Error> { fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> Result<bool> {
self.get_path() self.get_path()
.map(PathBuf::from) .map(PathBuf::from)
.map_err(RE::from) .map_err(Error::from)
.map_err(RPG::Error::from)
.and_then(|pb| RPG::unique_hash(pb)) .and_then(|pb| RPG::unique_hash(pb))
.and_then(|h| Ok(h == self.get_hash()?)) .and_then(|h| Ok(h == self.get_hash()?))
} }

View file

@ -24,26 +24,26 @@ use libimagstore::store::FileLockEntry;
use libimagstore::store::Store; use libimagstore::store::Store;
use libimagstore::storeid::StoreId; use libimagstore::storeid::StoreId;
use error::RefError as RE;
use reference::Ref; use reference::Ref;
use failure::Fallible as Result;
use failure::Error;
/// A UniqueRefPathGenerator generates unique Pathes /// A UniqueRefPathGenerator generates unique Pathes
/// ///
/// It is basically a functor which generates a StoreId from a &Path. /// It is basically a functor which generates a StoreId from a &Path.
/// For more information have a look at the documentation of RefStore. /// For more information have a look at the documentation of RefStore.
pub trait UniqueRefPathGenerator { pub trait UniqueRefPathGenerator {
type Error: From<RE>;
/// The collection the `StoreId` should be created for /// The collection the `StoreId` should be created for
fn collection() -> &'static str { fn collection() -> &'static str {
"ref" "ref"
} }
/// A function which should generate a unique string for a Path /// A function which should generate a unique string for a Path
fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String, Self::Error>; fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String>;
/// Postprocess the generated `StoreId` object /// Postprocess the generated `StoreId` object
fn postprocess_storeid(sid: StoreId) -> Result<StoreId, Self::Error> { fn postprocess_storeid(sid: StoreId) -> Result<StoreId> {
Ok(sid) Ok(sid)
} }
} }
@ -80,45 +80,43 @@ pub trait UniqueRefPathGenerator {
/// ///
pub trait RefStore<'a> { pub trait RefStore<'a> {
fn get_ref<RPG: UniqueRefPathGenerator, H: AsRef<str>>(&'a self, hash: H) -> Result<Option<FileLockEntry<'a>>, RPG::Error>; fn get_ref<RPG: UniqueRefPathGenerator, H: AsRef<str>>(&'a self, hash: H) -> Result<Option<FileLockEntry<'a>>>;
fn create_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>, RPG::Error>; fn create_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>>;
fn retrieve_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>, RPG::Error>; fn retrieve_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>>;
} }
impl<'a> RefStore<'a> for Store { impl<'a> RefStore<'a> for Store {
fn get_ref<RPG: UniqueRefPathGenerator, H: AsRef<str>>(&'a self, hash: H) fn get_ref<RPG: UniqueRefPathGenerator, H: AsRef<str>>(&'a self, hash: H)
-> Result<Option<FileLockEntry<'a>>, RPG::Error> -> Result<Option<FileLockEntry<'a>>>
{ {
let sid = StoreId::new_baseless(PathBuf::from(format!("{}/{}", RPG::collection(), hash.as_ref()))) let sid = StoreId::new_baseless(PathBuf::from(format!("{}/{}", RPG::collection(), hash.as_ref())))
.map_err(RE::from)?; .map_err(Error::from)?;
debug!("Getting: {:?}", sid); debug!("Getting: {:?}", sid);
self.get(sid) self.get(sid)
.map_err(RE::from) .map_err(Error::from)
.map_err(RPG::Error::from)
} }
fn create_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) fn create_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A)
-> Result<FileLockEntry<'a>, RPG::Error> -> Result<FileLockEntry<'a>>
{ {
let hash = RPG::unique_hash(&path)?; let hash = RPG::unique_hash(&path)?;
let pathbuf = PathBuf::from(format!("{}/{}", RPG::collection(), hash)); let pathbuf = PathBuf::from(format!("{}/{}", RPG::collection(), hash));
let sid = StoreId::new_baseless(pathbuf.clone()).map_err(RE::from)?; let sid = StoreId::new_baseless(pathbuf.clone())?;
debug!("Creating: {:?}", sid); debug!("Creating: {:?}", sid);
self.create(sid) self.create(sid)
.map_err(RE::from) .map_err(Error::from)
.and_then(|mut fle| { .and_then(|mut fle| {
fle.make_ref(hash, path)?; fle.make_ref(hash, path)?;
Ok(fle) Ok(fle)
}) })
.map_err(RPG::Error::from)
} }
fn retrieve_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) fn retrieve_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A)
-> Result<FileLockEntry<'a>, RPG::Error> -> Result<FileLockEntry<'a>>
{ {
match self.get_ref::<RPG, String>(RPG::unique_hash(path.as_ref())?)? { match self.get_ref::<RPG, String>(RPG::unique_hash(path.as_ref())?)? {
Some(r) => Ok(r), Some(r) => Ok(r),