Refactor errors to use error-chain linking functionality
This commit is contained in:
parent
a64fbbbdb9
commit
cac7697054
7 changed files with 50 additions and 85 deletions
|
@ -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")
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
)
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue