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; use email::Header;
let mut s = String::new(); 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) MimeMessage::parse(&s)
.chain_err(|| REK::RefHashingError) .chain_err(|| REK::RefHashingError)

View file

@ -24,43 +24,24 @@ error_chain! {
links { links {
ListError(::libimagentrylist::error::ListError, ::libimagentrylist::error::ListErrorKind); 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 { foreign_links {
Io(::std::io::Error); Io(::std::io::Error);
Utf8Error(::std::string::FromUtf8Error);
TomlDeError(::toml::de::Error);
TomlSerError(::toml::ser::Error);
WalkDirError(::walkdir::Error);
} }
errors { 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 { UTF8Error {
description("UTF8 Error") description("UTF8 Error")
display("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 { HeaderTypeError {
description("Header type error") description("Header type error")
display("Header type error") display("Header type error")

View file

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

View file

@ -20,9 +20,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::io::Read; use std::io::Read;
use error::RefErrorKind as REK;
use error::ResultExt;
use crypto::sha1::Sha1; use crypto::sha1::Sha1;
use crypto::digest::Digest; 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> { fn create_hash<R: Read>(&mut self, _: &PathBuf, c: &mut R) -> Result<String> {
let mut s = String::new(); 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[..]); self.hasher.input_str(&s[..]);
Ok(self.hasher.result_str()) Ok(self.hasher.result_str())
} }

View file

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

View file

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

View file

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

View file

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