Merge pull request #1108 from matthiasbeyer/libimagentryref/refactor-errors

Refactor errors to use error-chain linking functionality
This commit is contained in:
Matthias Beyer 2017-09-24 15:23:04 +02:00 committed by GitHub
commit 046eb5eca3
8 changed files with 51 additions and 86 deletions

View file

@ -51,7 +51,7 @@ impl Hasher for MailHasher {
use email::Header;
let mut s = String::new();
try!(c.read_to_string(&mut s).chain_err(|| REK::UTF8Error).chain_err(|| REK::IOError));
try!(c.read_to_string(&mut s));
MimeMessage::parse(&s)
.chain_err(|| REK::RefHashingError)

View file

@ -24,43 +24,24 @@ error_chain! {
links {
ListError(::libimagentrylist::error::ListError, ::libimagentrylist::error::ListErrorKind);
StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind);
TomlQueryError(::toml_query::error::Error, ::toml_query::error::ErrorKind);
}
foreign_links {
Io(::std::io::Error);
Utf8Error(::std::string::FromUtf8Error);
TomlDeError(::toml::de::Error);
TomlSerError(::toml::ser::Error);
WalkDirError(::walkdir::Error);
}
errors {
StoreReadError {
description("Store read error")
display("Store read error")
}
StoreWriteError {
description("Store write error")
display("Store write error")
}
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")

View file

@ -22,7 +22,6 @@ use std::collections::BTreeMap;
use toml::Value;
use error::RefErrorKind as REK;
use error::ResultExt;
use error::Result;
pub struct RefFlags {
@ -41,7 +40,7 @@ impl RefFlags {
use toml_query::read::TomlValueReadExt;
v.read(key)
.chain_err(|| REK::HeaderTomlError)
.map_err(From::from)
.and_then(|toml| match toml {
Some(&Value::Boolean(b)) => Ok(b),
Some(_) => Err(REK::HeaderTypeError.into()),

View file

@ -20,9 +20,6 @@
use std::path::PathBuf;
use std::io::Read;
use error::RefErrorKind as REK;
use error::ResultExt;
use crypto::sha1::Sha1;
use crypto::digest::Digest;
@ -58,7 +55,7 @@ impl Hasher for DefaultHasher {
fn create_hash<R: Read>(&mut self, _: &PathBuf, c: &mut R) -> Result<String> {
let mut s = String::new();
try!(c.read_to_string(&mut s).chain_err(|| REK::UTF8Error).chain_err(|| REK::IOError));
try!(c.read_to_string(&mut s));
self.hasher.input_str(&s[..]);
Ok(self.hasher.result_str())
}

View file

@ -26,8 +26,7 @@ use crypto::digest::Digest;
use hasher::Hasher;
use error::Result;
use error::RefErrorKind as REK;
use error::ResultExt;
use error::RefError as RE;
pub struct NBytesHasher {
hasher: Sha1,
@ -52,12 +51,13 @@ impl Hasher for NBytesHasher {
}
fn create_hash<R: Read>(&mut self, _: &PathBuf, contents: &mut R) -> Result<String> {
let s = try!(contents
let s : String = try!(contents
.bytes()
.take(self.n)
.collect::<RResult<Vec<u8>, _>>()
.chain_err(|| REK::IOError)
.and_then(|v| String::from_utf8(v).chain_err(|| REK::UTF8Error)));
.map_err(From::from)
.and_then(|v| String::from_utf8(v).map_err(RE::from)));
self.hasher.input_str(&s[..]);
Ok(self.hasher.result_str())
}

View file

@ -121,13 +121,14 @@ impl Ref for Entry {
self.get_location()
.clone()
.into_pathbuf()
.chain_err(|| REK::StoreIdError)
.map_err(From::from)
.and_then(|pb| {
pb.file_name()
.and_then(|osstr| osstr.to_str())
.and_then(|s| s.split("~").next())
.map(String::from)
.ok_or(RE::from_kind(REK::StoreIdError))
.ok_or(String::from("String splitting error"))
.map_err(From::from)
})
}
@ -139,18 +140,16 @@ impl Ref for Entry {
/// Get the hahs of the link target which is stored in the ref object, which is hashed with a
/// custom Hasher instance.
fn get_stored_hash_with_hasher<H: Hasher>(&self, h: &H) -> Result<String> {
match self.get_header().read(&format!("ref.content_hash.{}", h.hash_name())[..]) {
match self.get_header().read(&format!("ref.content_hash.{}", h.hash_name())[..])? {
// content hash stored...
Ok(Some(&Value::String(ref s))) => Ok(s.clone()),
Some(&Value::String(ref s)) => Ok(s.clone()),
// content hash header field has wrong type
Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)),
Some(_) => Err(RE::from_kind(REK::HeaderTypeError)),
// content hash not stored
Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)),
None => Err(RE::from_kind(REK::HeaderFieldMissingError)),
// Error
Err(e) => Err(e).chain_err(|| REK::StoreReadError),
}
}
@ -163,11 +162,7 @@ impl Ref for Entry {
/// custom hasher
fn get_current_hash_with_hasher<H: Hasher>(&self, mut h: H) -> Result<String> {
self.fs_file()
.and_then(|pb| {
File::open(pb.clone())
.map(|f| (pb, f))
.chain_err(|| REK::IOError)
})
.and_then(|pb| File::open(pb.clone()).map(|f| (pb, f)).map_err(From::from))
.and_then(|(path, mut file)| h.create_hash(&path, &mut file))
}
@ -244,13 +239,11 @@ impl Ref for Entry {
try!(self
.get_header_mut()
.set("ref.permissions.ro", Value::Boolean(current_perm.readonly()))
.chain_err(|| REK::StoreWriteError)
);
try!(self
.get_header_mut()
.set(&format!("ref.content_hash.{}", h.hash_name())[..], Value::String(current_hash))
.chain_err(|| REK::StoreWriteError)
);
Ok(())
@ -258,11 +251,10 @@ impl Ref for Entry {
/// Get the path of the file which is reffered to by this Ref
fn fs_file(&self) -> Result<PathBuf> {
match self.get_header().read("ref.path") {
Ok(Some(&Value::String(ref s))) => Ok(PathBuf::from(s)),
Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)),
Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)),
Err(e) => Err(e).chain_err(|| REK::StoreReadError),
match self.get_header().read("ref.path")? {
Some(&Value::String(ref s)) => Ok(PathBuf::from(s)),
Some(_) => Err(RE::from_kind(REK::HeaderTypeError)),
None => Err(RE::from_kind(REK::HeaderFieldMissingError)),
}
}
@ -300,14 +292,18 @@ impl Ref for Entry {
.into_iter()
.map(|entry| {
entry
.chain_err(|| REK::IOError)
.map_err(From::from)
.and_then(|entry| {
let pb = PathBuf::from(entry.path());
File::open(entry.path())
.chain_err(|| REK::IOError)
.map(|f| (pb, f))
.map_err(From::from)
})
.and_then(|(p, mut f)| {
h.create_hash(&p, &mut f)
.map(|h| (p, h))
.map_err(From::from)
})
.and_then(|(p, mut f)| h.create_hash(&p, &mut f).map(|h| (p, h)))
.map(|(path, hash)| {
if hash == stored_hash {
Some(path)
@ -315,9 +311,8 @@ impl Ref for Entry {
None
}
})
.chain_err(|| REK::IOError)
})
.filter_map(|e| e.ok())
.filter_map(Result::ok)
.filter_map(|e| e)
.next()
})

View file

@ -72,9 +72,7 @@ impl RefStore for Store {
.and_then(|c| hash_path(&c))
.chain_err(|| REK::PathHashingError)
.and_then(|hash| {
self.retrieve_for_module("ref")
.map(|iter| (hash, iter))
.chain_err(|| REK::StoreReadError)
self.retrieve_for_module("ref").map(|iter| (hash, iter)).map_err(From::from)
})
.and_then(|(hash, possible_refs)| {
// This is kind of a manual Iterator::filter() call what we do here, but with the
@ -91,15 +89,17 @@ impl RefStore for Store {
continue;
}
match self.get(r) {
Ok(Some(fle)) => {
match self.get(r.clone())? {
Some(fle) => {
if read_reference(&fle).map(|path| path == pb).unwrap_or(false) {
return Ok(true)
}
},
Ok(None) => return Err(RE::from_kind(REK::StoreReadError)),
Err(e) => return Err(e).chain_err(|| REK::StoreReadError)
None => {
let e = format!("Failed to get from store: {}", r);
return Err(e).map_err(From::from)
},
}
}
@ -109,10 +109,9 @@ impl RefStore for Store {
/// Try to get `si` as Ref object from the store
fn get<'a>(&'a self, si: StoreId) -> Result<FileLockEntry<'a>> {
match self.get(si) {
Err(e) => return Err(e).chain_err(|| REK::StoreReadError),
Ok(None) => return Err(RE::from_kind(REK::RefNotInStore)),
Ok(Some(fle)) => Ok(fle),
match self.get(si)? {
None => return Err(RE::from_kind(REK::RefNotInStore)),
Some(fle) => Ok(fle),
}
}
@ -123,7 +122,7 @@ impl RefStore for Store {
ModuleEntryPath::new(hash)
.into_storeid()
.and_then(|id| self.get(id))
.chain_err(|| REK::StoreReadError)
.map_err(From::from)
}
/// Delete a ref by hash
@ -133,7 +132,7 @@ impl RefStore for Store {
ModuleEntryPath::new(hash)
.into_storeid()
.and_then(|id| self.delete(id))
.chain_err(|| REK::StoreWriteError)
.map_err(From::from)
}
/// Create a Ref object which refers to `pb`
@ -218,11 +217,7 @@ impl RefStore for Store {
// and then we create the FileLockEntry in the Store
// and return (filelockentry, content hash, permissions, canonicalized path)
.and_then(|(opt_conhash, opt_perm, can, path_hash)| {
let fle = try!(self
.create(ModuleEntryPath::new(path_hash))
.chain_err(|| REK::StoreWriteError)
);
let fle = try!(self.create(ModuleEntryPath::new(path_hash)));
Ok((fle, opt_conhash, opt_perm, can))
})
)

View file

@ -22,7 +22,6 @@ use std::path::PathBuf;
use error::RefErrorKind as REK;
use error::RefError as RE;
use error::Result;
use error::ResultExt;
use libimagstore::store::Entry;
@ -47,11 +46,10 @@ pub fn hash_path(pb: &PathBuf) -> Result<String> {
/// Read the reference from a file
pub fn read_reference(refentry: &Entry) -> Result<PathBuf> {
match refentry.get_header().read("ref.path") {
Ok(Some(&Value::String(ref s))) => Ok(PathBuf::from(s)),
Ok(Some(_)) => Err(RE::from_kind(REK::HeaderTypeError)),
Ok(None) => Err(RE::from_kind(REK::HeaderFieldMissingError)),
Err(e) => Err(e).chain_err(|| REK::StoreReadError),
match refentry.get_header().read("ref.path")? {
Some(&Value::String(ref s)) => Ok(PathBuf::from(s)),
Some(_) => Err(RE::from_kind(REK::HeaderTypeError)),
None => Err(RE::from_kind(REK::HeaderFieldMissingError)),
}
}