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"
log = "0.4.0"
toml = "0.4"
toml-query = "0.7"
error-chain = "0.12"
toml-query = { git = "https://github.com/matthiasbeyer/toml-query", branch = "failure" }
failure = "0.1"
sha-1 = { version = "0.7", optional = true }
sha2 = { 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 error::RefError;
use refstore::UniqueRefPathGenerator;
use failure::Fallible as Result;
/// A base UniqueRefPathGenerator which must be overridden by the actual UniqueRefPathGenerator
/// which is provided by this crate
#[allow(dead_code)]
pub struct Base;
impl UniqueRefPathGenerator for Base {
type Error = RefError;
fn collection() -> &'static str {
"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
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
}
}

View file

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

View file

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

View file

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

View file

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