summaryrefslogtreecommitdiffstats
path: root/lib/entry/libimagentryref
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-09-04 21:59:54 +0200
committerGitHub <noreply@github.com>2017-09-04 21:59:54 +0200
commit6d1dab31179eb4414b45d9a94f453833ddc558ce (patch)
tree8bca1ca131e17a647a98d083087e0a42124067eb /lib/entry/libimagentryref
parentf025416cf7d96b5f2a41d545c75255cab9fe2d06 (diff)
parent6583ba04a2151d940d99d4277713df4f50bf9eac (diff)
Merge pull request #1029 from matthiasbeyer/all-extensions-as-traits
All extensions as traits
Diffstat (limited to 'lib/entry/libimagentryref')
-rw-r--r--lib/entry/libimagentryref/Cargo.toml2
-rw-r--r--lib/entry/libimagentryref/src/hashers/nbytes.rs11
-rw-r--r--lib/entry/libimagentryref/src/lib.rs2
-rw-r--r--lib/entry/libimagentryref/src/lister.rs116
-rw-r--r--lib/entry/libimagentryref/src/reference.rs461
-rw-r--r--lib/entry/libimagentryref/src/refstore.rs269
-rw-r--r--lib/entry/libimagentryref/src/util.rs56
7 files changed, 487 insertions, 430 deletions
diff --git a/lib/entry/libimagentryref/Cargo.toml b/lib/entry/libimagentryref/Cargo.toml
index 842c5535..2ca29040 100644
--- a/lib/entry/libimagentryref/Cargo.toml
+++ b/lib/entry/libimagentryref/Cargo.toml
@@ -18,8 +18,8 @@ itertools = "0.5"
log = "0.3"
rust-crypto = "0.2"
toml = "^0.4"
-walkdir = "1.0.*"
toml-query = "0.3.0"
+walkdir = "1.0.*"
libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" }
diff --git a/lib/entry/libimagentryref/src/hashers/nbytes.rs b/lib/entry/libimagentryref/src/hashers/nbytes.rs
index 995e3dd8..5d190840 100644
--- a/lib/entry/libimagentryref/src/hashers/nbytes.rs
+++ b/lib/entry/libimagentryref/src/hashers/nbytes.rs
@@ -24,8 +24,6 @@ use std::result::Result as RResult;
use crypto::sha1::Sha1;
use crypto::digest::Digest;
-use libimagerror::into::IntoError;
-
use hasher::Hasher;
use result::Result;
use error::RefErrorKind as REK;
@@ -54,16 +52,13 @@ impl Hasher for NBytesHasher {
}
fn create_hash<R: Read>(&mut self, _: &PathBuf, contents: &mut R) -> Result<String> {
- let s = contents
+ let s = try!(contents
.bytes()
.take(self.n)
.collect::<RResult<Vec<u8>, _>>()
.map_err_into(REK::IOError)
- .and_then(|v| String::from_utf8(v).map_err_into(REK::IOError))
- .map_err(Box::new)
- .map_err(|e| REK::UTF8Error.into_error_with_cause(e))
- .map_err_into(REK::IOError);
- self.hasher.input_str(&try!(s)[..]);
+ .and_then(|v| String::from_utf8(v).map_err_into(REK::UTF8Error)));
+ self.hasher.input_str(&s[..]);
Ok(self.hasher.result_str())
}
diff --git a/lib/entry/libimagentryref/src/lib.rs b/lib/entry/libimagentryref/src/lib.rs
index 17cbe112..011ba433 100644
--- a/lib/entry/libimagentryref/src/lib.rs
+++ b/lib/entry/libimagentryref/src/lib.rs
@@ -52,4 +52,6 @@ pub mod hasher;
pub mod hashers;
pub mod lister;
pub mod reference;
+pub mod refstore;
pub mod result;
+mod util;
diff --git a/lib/entry/libimagentryref/src/lister.rs b/lib/entry/libimagentryref/src/lister.rs
index 662ea9f6..af843327 100644
--- a/lib/entry/libimagentryref/src/lister.rs
+++ b/lib/entry/libimagentryref/src/lister.rs
@@ -20,13 +20,14 @@
use std::default::Default;
use std::io::stdout;
use std::io::Write;
+use std::ops::Deref;
use libimagentrylist::lister::Lister;
use libimagentrylist::result::Result;
use libimagerror::trace::trace_error;
use libimagstore::store::FileLockEntry;
-use libimagerror::into::IntoError;
use libimagentrylist::error::ListErrorKind as LEK;
+use libimagentrylist::error as lerror;
use reference::Ref;
use error::MapErrInto;
@@ -88,15 +89,45 @@ impl Lister for RefLister {
debug!("fold({:?}, {:?})", accu, entry);
let r = accu.and_then(|_| {
debug!("Listing Entry: {:?}", entry);
- lister_fn(entry,
- self.check_dead,
- self.check_changed,
- self.check_changed_content,
- self.check_changed_permiss)
+ {
+ let is_dead = if self.check_dead {
+ if try!(entry.fs_link_exists()) {
+ "dead"
+ } else {
+ "alive"
+ }
+ } else {
+ "not checked"
+ };
+
+ let is_changed = if self.check_changed {
+ if check_changed(entry.deref()) { "changed" } else { "unchanged" }
+ } else {
+ "not checked"
+ };
+
+ let is_changed_content = if self.check_changed_content {
+ if check_changed_content(entry.deref()) { "changed" } else { "unchanged" }
+ } else {
+ "not checked"
+ };
+
+ let is_changed_permiss = if self.check_changed_permiss {
+ if check_changed_permiss(entry.deref()) { "changed" } else { "unchanged" }
+ } else {
+ "not checked"
+ };
+
+ Ok(format!("{} | {} | {} | {} | {} | {}",
+ is_dead,
+ is_changed,
+ is_changed_content,
+ is_changed_permiss,
+ entry.get_path_hash().unwrap_or_else(|_| String::from("Cannot get hash")),
+ entry.get_location()))
+ }
.and_then(|s| {
- write!(stdout(), "{}\n", s)
- .map_err(Box::new)
- .map_err(|e| LEK::FormatError.into_error_with_cause(e))
+ lerror::MapErrInto::map_err_into(write!(stdout(), "{}\n", s), LEK::FormatError)
})
.map_err_into(REK::RefToDisplayError)
})
@@ -104,73 +135,16 @@ impl Lister for RefLister {
(r, i + 1)
});
debug!("Iterated over {} entries", n);
- r.map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
+ lerror::MapErrInto::map_err_into(r, LEK::FormatError)
}
}
-fn lister_fn(fle: FileLockEntry,
- do_check_dead: bool,
- do_check_changed: bool,
- do_check_changed_content: bool,
- do_check_changed_permiss: bool) -> Result<String>
-{
- Ref::from_filelockentry(fle)
- .map(|r| {
- let is_dead = if do_check_dead {
- if check_dead(&r) { "dead" } else { "alive" }
- } else {
- "not checked"
- };
-
- let is_changed = if do_check_changed {
- if check_changed(&r) { "changed" } else { "unchanged" }
- } else {
- "not checked"
- };
-
- let is_changed_content = if do_check_changed_content {
- if check_changed_content(&r) { "changed" } else { "unchanged" }
- } else {
- "not checked"
- };
-
- let is_changed_permiss = if do_check_changed_permiss {
- if check_changed_permiss(&r) { "changed" } else { "unchanged" }
- } else {
- "not checked"
- };
-
- format!("{} | {} | {} | {} | {} | {}",
- is_dead,
- is_changed,
- is_changed_content,
- is_changed_permiss,
- r.get_path_hash().unwrap_or_else(|_| String::from("Cannot get hash")),
- r.get_location())
- })
- .map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
-}
-
-fn check_dead(r: &Ref) -> bool {
- match r.fs_link_exists() {
- Ok(b) => b,
- Err(e) => {
- warn!("Could not check whether the ref {} exists on the FS:", r);
- trace_error(&e);
-
- // We continue here and tell the callee that this reference is dead, what is kind of
- // true actually, as we might not have access to it right now
- true
- },
- }
-}
-
-fn check_changed(r: &Ref) -> bool {
+fn check_changed<R: Ref>(r: &R) -> bool {
check_changed_content(r) && check_changed_permiss(r)
}
-fn check_changed_content(r: &Ref) -> bool {
+fn check_changed_content<R: Ref>(r: &R) -> bool {
let eq = r.get_current_hash()
.and_then(|hash| r.get_stored_hash().map(|stored| (hash, stored)))
.map(|(hash, stored)| hash == stored);
@@ -178,7 +152,7 @@ fn check_changed_content(r: &Ref) -> bool {
match eq {
Ok(eq) => eq,
Err(e) => {
- warn!("Could not check whether the ref {} changed on the FS:", r);
+ warn!("Could not check whether the ref changed on the FS");
trace_error(&e);
// We continue here and tell the callee that this reference is unchanged
@@ -187,7 +161,7 @@ fn check_changed_content(r: &Ref) -> bool {
}
}
-fn check_changed_permiss(_: &Ref) -> bool {
+fn check_changed_permiss<R: Ref>(_: &R) -> bool {
warn!("Permission changes tracking not supported yet.");
false
}
diff --git a/lib/entry/libimagentryref/src/reference.rs b/lib/entry/libimagentryref/src/reference.rs
index 81e991ca..3dd196ba 100644
--- a/lib/entry/libimagentryref/src/reference.rs
+++ b/lib/entry/libimagentryref/src/reference.rs
@@ -21,238 +21,104 @@
//! files outside of the imag store.
use std::path::PathBuf;
-use std::ops::Deref;
-use std::ops::DerefMut;
-use std::collections::BTreeMap;
use std::fs::File;
-use std::fmt::{Display, Error as FmtError, Formatter};
use std::fs::Permissions;
-use std::result::Result as RResult;
-use libimagstore::store::FileLockEntry;
-use libimagstore::storeid::StoreId;
-use libimagstore::storeid::IntoStoreId;
-use libimagstore::store::Store;
+use libimagstore::store::Entry;
use libimagerror::into::IntoError;
use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::set::TomlValueSetExt;
-use toml_query::insert::TomlValueInsertExt;
use error::RefErrorKind as REK;
use error::MapErrInto;
-use flags::RefFlags;
use result::Result;
use hasher::*;
-use module_path::ModuleEntryPath;
-#[derive(Debug)]
-pub struct Ref<'a>(FileLockEntry<'a>);
+pub trait Ref {
-impl<'a> Ref<'a> {
+ /// Get the hash from the path of the ref
+ fn get_path_hash(&self) -> Result<String>;
- /// Try to build a Ref object based on an existing FileLockEntry object
- pub fn from_filelockentry(fle: FileLockEntry<'a>) -> Result<Ref<'a>> {
- Ref::read_reference(&fle).map(|_| Ref(fle))
- }
+ /// Get the hash of the link target which is stored in the ref object
+ fn get_stored_hash(&self) -> Result<String>;
- /// Try to get `si` as Ref object from the store
- pub fn get(store: &'a Store, si: StoreId) -> Result<Ref<'a>> {
- match store.get(si) {
- Err(e) => return Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
- Ok(None) => return Err(REK::RefNotInStore.into_error()),
- Ok(Some(fle)) => Ref::from_filelockentry(fle),
- }
- }
+ /// 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>;
- /// Get a Ref object from the store by hash.
- ///
- /// Returns None if the hash cannot be found.
- pub fn get_by_hash(store: &'a Store, hash: String) -> Result<Option<Ref<'a>>> {
- ModuleEntryPath::new(hash)
- .into_storeid()
- .and_then(|id| store.get(id))
- .map(|opt_fle| opt_fle.map(|fle| Ref(fle)))
- .map_err(Box::new)
- .map_err(|e| REK::StoreReadError.into_error_with_cause(e))
- }
+ /// Get the hash of the link target by reading the link target and hashing the contents
+ fn get_current_hash(&self) -> Result<String>;
- /// Delete a ref by hash
- ///
- /// If the returned Result contains an error, the ref might not be deleted.
- pub fn delete_by_hash(store: &'a Store, hash: String) -> Result<()> {
- ModuleEntryPath::new(hash)
- .into_storeid()
- .and_then(|id| store.delete(id))
- .map_err(Box::new)
- .map_err(|e| REK::StoreWriteError.into_error_with_cause(e))
- }
+ /// Get the hash of the link target by reading the link target and hashing the contents with the
+ /// custom hasher
+ fn get_current_hash_with_hasher<H: Hasher>(&self, h: H) -> Result<String>;
- fn read_reference(fle: &FileLockEntry<'a>) -> Result<PathBuf> {
- match fle.get_header().read("ref.path") {
- Ok(Some(&Value::String(ref s))) => Ok(PathBuf::from(s)),
- Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()),
- Ok(None) => Err(REK::HeaderFieldMissingError.into_error()),
- Err(e) => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
- }
- }
+ /// check whether the pointer the Ref represents still points to a file which exists
+ fn fs_link_exists(&self) -> Result<bool>;
- pub fn create_with_hasher<H: Hasher>(store: &'a Store, pb: PathBuf, flags: RefFlags, mut h: H)
- -> Result<Ref<'a>>
- {
- if !pb.exists() {
- return Err(REK::RefTargetDoesNotExist.into_error());
- }
- if flags.get_content_hashing() && pb.is_dir() {
- return Err(REK::RefTargetCannotBeHashed.into_error());
- }
+ /// Alias for `r.fs_link_exists() && r.deref().is_file()`
+ fn is_ref_to_file(&self) -> Result<bool>;
- let (mut fle, content_hash, permissions, canonical_path) = { // scope to be able to fold
- try!(File::open(pb.clone())
- .map_err(Box::new)
- .map_err(|e| REK::RefTargetFileCannotBeOpened.into_error_with_cause(e))
-
- // If we were able to open this file,
- // we hash the contents of the file and return (file, hash)
- .and_then(|mut file| {
- let opt_contenthash = if flags.get_content_hashing() {
- Some(try!(h.create_hash(&pb, &mut file)))
- } else {
- None
- };
-
- Ok((file, opt_contenthash))
- })
-
- // and then we get the permissions if we have to
- // and return (file, content hash, permissions)
- .and_then(|(file, opt_contenthash)| {
- let opt_permissions = if flags.get_permission_tracking() {
- Some(try!(file
- .metadata()
- .map(|md| md.permissions())
- .map_err(Box::new)
- .map_err(|e| REK::RefTargetCannotReadPermissions.into_error_with_cause(e))
- ))
- } else {
- None
- };
-
- Ok((opt_contenthash, opt_permissions))
- })
-
- // and then we try to canonicalize the PathBuf, because we want to store a
- // canonicalized path
- // and return (file, content hash, permissions, canonicalized path)
- .and_then(|(opt_contenthash, opt_permissions)| {
- pb.canonicalize()
- .map(|can| (opt_contenthash, opt_permissions, can))
- // if PathBuf::canonicalize() failed, build an error from the return value
- .map_err(|e| REK::PathCanonicalizationError.into_error_with_cause(Box::new(e)))
- })
-
- // and then we hash the canonicalized path
- // and return (file, content hash, permissions, canonicalized path, path hash)
- .and_then(|(opt_contenthash, opt_permissions, can)| {
- let path_hash = try!(Ref::hash_path(&can)
- .map_err(Box::new)
- .map_err(|e| REK::PathHashingError.into_error_with_cause(e))
- );
-
- Ok((opt_contenthash, opt_permissions, can, path_hash))
- })
-
- // and then we convert the PathBuf of the canonicalized path to a String to be able
- // to save it in the Ref FileLockEntry obj
- // and return
- // (file, content hash, permissions, canonicalized path as String, path hash)
- .and_then(|(opt_conhash, opt_perm, can, path_hash)| {
- match can.to_str().map(String::from) {
- // UTF convert error in PathBuf::to_str(),
- None => Err(REK::PathUTF8Error.into_error()),
- Some(can) => Ok((opt_conhash, opt_perm, can, path_hash))
- }
- })
-
- // 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!(store
- .create(ModuleEntryPath::new(path_hash))
- .map_err(Box::new)
- .map_err(|e| REK::StoreWriteError.into_error_with_cause(e))
- );
-
- Ok((fle, opt_conhash, opt_perm, can))
- })
- )
- };
-
- for tpl in [
- Some((String::from("ref"), Value::Table(BTreeMap::new()))),
- Some((String::from("ref.permissions"), Value::Table(BTreeMap::new()))),
- Some((String::from("ref.path"), Value::String(canonical_path))),
- Some((String::from("ref.content_hash"), Value::Table(BTreeMap::new()))),
-
- content_hash.map(|hash| {
- (format!("ref.content_hash.{}", h.hash_name()), Value::String(hash))
- }),
- permissions.map(|p| {
- (String::from("ref.permissions.ro"), Value::Boolean(p.readonly()))
- }),
- ].into_iter()
- {
- match tpl {
- &Some((ref s, ref v)) => {
- match fle.get_header_mut().insert(s, v.clone()) {
- Ok(None) => {
- debug!("Header insert worked");
- }
- Ok(Some(val)) => {
- debug!("Overwrote: {}, which was: {:?}", s, val);
- },
- Err(e) => {
- let e = Box::new(e);
- let e = REK::HeaderFieldWriteError.into_error_with_cause(e);
- return Err(e);
- },
- }
- }
- &None => {
- debug!("Not going to insert.");
- }
- }
- }
+ /// Alias for `r.fs_link_exists() && r.deref().is_dir()`
+ fn is_ref_to_dir(&self) -> Result<bool>;
- Ok(Ref(fle))
- }
+ /// Alias for `!Ref::fs_link_exists()`
+ fn is_dangling(&self) -> Result<bool>;
- /// Create a Ref object which refers to `pb`
- pub fn create(store: &'a Store, pb: PathBuf, flags: RefFlags) -> Result<Ref<'a>> {
- Ref::create_with_hasher(store, pb, flags, DefaultHasher::new())
- }
+ /// check whether the pointer the Ref represents is valid
+ /// This includes:
+ /// - Hashsum of the file is still the same as stored in the Ref
+ /// - file permissions are still valid
+ fn fs_link_valid(&self) -> Result<bool>;
- /// Creates a Hash from a PathBuf by making the PathBuf absolute and then running a hash
- /// algorithm on it
- fn hash_path(pb: &PathBuf) -> Result<String> {
- use crypto::sha1::Sha1;
- use crypto::digest::Digest;
-
- match pb.to_str() {
- Some(s) => {
- let mut hasher = Sha1::new();
- hasher.input_str(s);
- Ok(hasher.result_str())
- },
- None => return Err(REK::PathUTF8Error.into_error()),
- }
- }
+ /// Check whether the file permissions of the referenced file are equal to the stored
+ /// permissions
+ fn fs_link_valid_permissions(&self) -> Result<bool>;
+
+ /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
+ fn fs_link_valid_hash(&self) -> Result<bool>;
+
+ /// Update the Ref by re-checking the file from FS
+ /// This errors if the file is not present or cannot be read()
+ fn update_ref(&mut self) -> Result<()>;
+
+ /// Update the Ref by re-checking the file from FS using the passed Hasher instance
+ /// This errors if the file is not present or cannot be read()
+ fn update_ref_with_hasher<H: Hasher>(&mut self, h: &H) -> Result<()>;
+
+ /// Get the path of the file which is reffered to by this Ref
+ fn fs_file(&self) -> Result<PathBuf>;
+
+ /// Re-find a referenced file
+ ///
+ /// This function tries to re-find a ref by searching all directories in `search_roots` recursively
+ /// for a file which matches the hash of the Ref.
+ ///
+ /// If `search_roots` is `None`, it starts at the filesystem root `/`.
+ ///
+ /// If the target cannot be found, this yields a RefTargetDoesNotExist error kind.
+ ///
+ /// # Warning
+ ///
+ /// This option causes heavy I/O as it recursively searches the Filesystem.
+ fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Result<PathBuf>;
+
+ /// See documentation of `Ref::refind()`
+ fn refind_with_hasher<H: Hasher>(&self, search_roots: Option<Vec<PathBuf>>, h: H)
+ -> Result<PathBuf>;
+
+ /// Get the permissions of the file which are present
+ fn get_current_permissions(&self) -> Result<Permissions>;
+}
+
+
+impl Ref for Entry {
/// Get the hash from the path of the ref
- pub fn get_path_hash(&self) -> Result<String> {
- self.0
- .get_location()
+ fn get_path_hash(&self) -> Result<String> {
+ self.get_location()
.clone()
.into_pathbuf()
.map_err_into(REK::StoreIdError)
@@ -266,14 +132,14 @@ impl<'a> Ref<'a> {
}
/// Get the hash of the link target which is stored in the ref object
- pub fn get_stored_hash(&self) -> Result<String> {
+ fn get_stored_hash(&self) -> Result<String> {
self.get_stored_hash_with_hasher(&DefaultHasher::new())
}
/// Get the hahs of the link target which is stored in the ref object, which is hashed with a
/// custom Hasher instance.
- pub fn get_stored_hash_with_hasher<H: Hasher>(&self, h: &H) -> Result<String> {
- match self.0.get_header().read(&format!("ref.content_hash.{}", h.hash_name())[..]) {
+ 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())[..]) {
// content hash stored...
Ok(Some(&Value::String(ref s))) => Ok(s.clone()),
@@ -289,57 +155,35 @@ impl<'a> Ref<'a> {
}
/// Get the hash of the link target by reading the link target and hashing the contents
- pub fn get_current_hash(&self) -> Result<String> {
+ fn get_current_hash(&self) -> Result<String> {
self.get_current_hash_with_hasher(DefaultHasher::new())
}
/// Get the hash of the link target by reading the link target and hashing the contents with the
/// custom hasher
- pub 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()
- .and_then(|pb| {
- File::open(pb.clone())
- .map(|f| (pb, f))
- .map_err(Box::new)
- .map_err(|e| REK::IOError.into_error_with_cause(e))
- })
+ .and_then(|pb| File::open(pb.clone()).map(|f| (pb, f)).map_err_into(REK::IOError))
.and_then(|(path, mut file)| h.create_hash(&path, &mut file))
}
- /// Get the permissions of the file which are present
- fn get_current_permissions(&self) -> Result<Permissions> {
- self.fs_file()
- .and_then(|pb| {
- File::open(pb)
- .map_err(Box::new)
- .map_err(|e| REK::HeaderFieldReadError.into_error_with_cause(e))
- })
- .and_then(|file| {
- file
- .metadata()
- .map(|md| md.permissions())
- .map_err(Box::new)
- .map_err(|e| REK::RefTargetCannotReadPermissions.into_error_with_cause(e))
- })
- }
-
/// check whether the pointer the Ref represents still points to a file which exists
- pub fn fs_link_exists(&self) -> Result<bool> {
+ fn fs_link_exists(&self) -> Result<bool> {
self.fs_file().map(|pathbuf| pathbuf.exists())
}
/// Alias for `r.fs_link_exists() && r.deref().is_file()`
- pub fn is_ref_to_file(&self) -> Result<bool> {
+ fn is_ref_to_file(&self) -> Result<bool> {
self.fs_file().map(|pathbuf| pathbuf.is_file())
}
/// Alias for `r.fs_link_exists() && r.deref().is_dir()`
- pub fn is_ref_to_dir(&self) -> Result<bool> {
+ fn is_ref_to_dir(&self) -> Result<bool> {
self.fs_file().map(|pathbuf| pathbuf.is_dir())
}
/// Alias for `!Ref::fs_link_exists()`
- pub fn is_dangling(&self) -> Result<bool> {
+ fn is_dangling(&self) -> Result<bool> {
self.fs_link_exists().map(|b| !b)
}
@@ -347,7 +191,7 @@ impl<'a> Ref<'a> {
/// This includes:
/// - Hashsum of the file is still the same as stored in the Ref
/// - file permissions are still valid
- pub fn fs_link_valid(&self) -> Result<bool> {
+ fn fs_link_valid(&self) -> Result<bool> {
match (self.fs_link_valid_permissions(), self.fs_link_valid_hash()) {
(Ok(true) , Ok(true)) => Ok(true),
(Ok(_) , Ok(_)) => Ok(false),
@@ -358,12 +202,11 @@ impl<'a> Ref<'a> {
/// Check whether the file permissions of the referenced file are equal to the stored
/// permissions
- pub fn fs_link_valid_permissions(&self) -> Result<bool> {
- self.0
+ fn fs_link_valid_permissions(&self) -> Result<bool> {
+ self
.get_header()
.read("ref.permissions.ro")
- .map_err(Box::new)
- .map_err(|e| REK::HeaderFieldReadError.into_error_with_cause(e))
+ .map_err_into(REK::HeaderFieldReadError)
.and_then(|ro| {
match ro {
Some(&Value::Boolean(b)) => Ok(b),
@@ -372,12 +215,11 @@ impl<'a> Ref<'a> {
}
})
.and_then(|ro| self.get_current_permissions().map(|perm| ro == perm.readonly()))
- .map_err(Box::new)
- .map_err(|e| REK::RefTargetCannotReadPermissions.into_error_with_cause(e))
+ .map_err_into(REK::RefTargetCannotReadPermissions)
}
/// Check whether the Hashsum of the referenced file is equal to the stored hashsum
- pub fn fs_link_valid_hash(&self) -> Result<bool> {
+ fn fs_link_valid_hash(&self) -> Result<bool> {
let stored_hash = try!(self.get_stored_hash());
let current_hash = try!(self.get_current_hash());
Ok(stored_hash == current_hash)
@@ -385,36 +227,34 @@ impl<'a> Ref<'a> {
/// Update the Ref by re-checking the file from FS
/// This errors if the file is not present or cannot be read()
- pub fn update_ref(&mut self) -> Result<()> {
+ fn update_ref(&mut self) -> Result<()> {
self.update_ref_with_hasher(&DefaultHasher::new())
}
/// Update the Ref by re-checking the file from FS using the passed Hasher instance
/// This errors if the file is not present or cannot be read()
- pub fn update_ref_with_hasher<H: Hasher>(&mut self, h: &H) -> Result<()> {
+ fn update_ref_with_hasher<H: Hasher>(&mut self, h: &H) -> Result<()> {
let current_hash = try!(self.get_current_hash()); // uses the default hasher
let current_perm = try!(self.get_current_permissions());
- try!(self.0
+ try!(self
.get_header_mut()
.set("ref.permissions.ro", Value::Boolean(current_perm.readonly()))
- .map_err(Box::new)
- .map_err(|e| REK::StoreWriteError.into_error_with_cause(e))
+ .map_err_into(REK::StoreWriteError)
);
- try!(self.0
+ try!(self
.get_header_mut()
.set(&format!("ref.content_hash.{}", h.hash_name())[..], Value::String(current_hash))
- .map_err(Box::new)
- .map_err(|e| REK::StoreWriteError.into_error_with_cause(e))
+ .map_err_into(REK::StoreWriteError)
);
Ok(())
}
/// Get the path of the file which is reffered to by this Ref
- pub fn fs_file(&self) -> Result<PathBuf> {
- match self.0.get_header().read("ref.path") {
+ 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(REK::HeaderTypeError.into_error()),
Ok(None) => Err(REK::HeaderFieldMissingError.into_error()),
@@ -422,56 +262,6 @@ impl<'a> Ref<'a> {
}
}
- /// Check whether there is a reference to the file at `pb`
- pub fn exists(store: &Store, pb: PathBuf) -> Result<bool> {
- pb.canonicalize()
- .map_err(Box::new)
- .map_err(|e| REK::PathCanonicalizationError.into_error_with_cause(e))
- .and_then(|can| {
- Ref::hash_path(&can)
- .map_err(Box::new)
- .map_err(|e| REK::PathHashingError.into_error_with_cause(e))
- })
- .and_then(|hash| {
- store.retrieve_for_module("ref").map(|iter| (hash, iter))
- .map_err(Box::new)
- .map_err(|e| REK::StoreReadError.into_error_with_cause(e))
- })
- .and_then(|(hash, possible_refs)| {
- // This is kind of a manual Iterator::filter() call what we do here, but with the
- // actual ::filter method we cannot return the error in a nice way, so we do it
- // manually here. If you can come up with a better version of this, feel free to
- // take this note as a todo.
- for r in possible_refs {
- let contains_hash = try!(r.to_str()
- .map_err_into(REK::TypeConversionError)
- .map(|s| s.contains(&hash[..])));
-
- if !contains_hash {
- continue;
- }
-
- match store.get(r) {
- Ok(Some(fle)) => {
- if Ref::read_reference(&fle).map(|path| path == pb).unwrap_or(false) {
- return Ok(true)
- }
- },
-
- Ok(None) => { // Something weird just happened
- return Err(REK::StoreReadError.into_error());
- },
-
- Err(e) => {
- return Err(REK::StoreReadError.into_error_with_cause(Box::new(e)));
- },
- }
- }
-
- Ok(false)
- })
- }
-
/// Re-find a referenced file
///
/// This function tries to re-find a ref by searching all directories in `search_roots` recursively
@@ -484,11 +274,12 @@ impl<'a> Ref<'a> {
/// # Warning
///
/// This option causes heavy I/O as it recursively searches the Filesystem.
- pub fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Result<PathBuf> {
+ fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Result<PathBuf> {
self.refind_with_hasher(search_roots, DefaultHasher::new())
}
- pub fn refind_with_hasher<H: Hasher>(&self, search_roots: Option<Vec<PathBuf>>, mut h: H)
+ /// See documentation of `Ref::refind()`
+ fn refind_with_hasher<H: Hasher>(&self, search_roots: Option<Vec<PathBuf>>, mut h: H)
-> Result<PathBuf>
{
use itertools::Itertools;
@@ -505,13 +296,11 @@ impl<'a> Ref<'a> {
.into_iter()
.map(|entry| {
entry
- .map_err(Box::new)
- .map_err(|e| REK::IOError.into_error_with_cause(e))
+ .map_err_into(REK::IOError)
.and_then(|entry| {
let pb = PathBuf::from(entry.path());
File::open(entry.path())
- .map_err(Box::new)
- .map_err(|e| REK::IOError.into_error_with_cause(e))
+ .map_err_into(REK::IOError)
.map(|f| (pb, f))
})
.and_then(|(p, mut f)| h.create_hash(&p, &mut f).map(|h| (p, h)))
@@ -522,8 +311,7 @@ impl<'a> Ref<'a> {
None
}
})
- .map_err(Box::new)
- .map_err(|e| REK::IOError.into_error_with_cause(e))
+ .map_err_into(REK::IOError)
})
.filter_map(|e| e.ok())
.filter_map(|e| e)
@@ -535,43 +323,16 @@ impl<'a> Ref<'a> {
})
}
-}