~matthiasbeyer/imag

9b48dc27cd00fcc75917c2702dc8dc4c6493e8d3 — Matthias Beyer 4 years ago 5a7def4
libimagentryref: Move from error-chain to failure

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
M lib/entry/libimagentryref/Cargo.toml => lib/entry/libimagentryref/Cargo.toml +2 -2
@@ 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 }

D lib/entry/libimagentryref/src/error.rs => lib/entry/libimagentryref/src/error.rs +0 -71
@@ 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")
        }

    }
}


M lib/entry/libimagentryref/src/generators/base.rs => lib/entry/libimagentryref/src/generators/base.rs +4 -5
@@ 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
    }
}

M lib/entry/libimagentryref/src/generators/mod.rs => lib/entry/libimagentryref/src/generators/mod.rs +9 -20
@@ 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());

M lib/entry/libimagentryref/src/lib.rs => lib/entry/libimagentryref/src/lib.rs +1 -2
@@ 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;


M lib/entry/libimagentryref/src/reference.rs => lib/entry/libimagentryref/src/reference.rs +20 -16
@@ 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()?))
    }

M lib/entry/libimagentryref/src/refstore.rs => lib/entry/libimagentryref/src/refstore.rs +15 -17
@@ 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),