diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2016-07-16 01:25:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-16 01:25:28 +0200 |
commit | cb4840cce4f87b0782b59e7955114ae79b3b18b6 (patch) | |
tree | d76e45989fee3d1329e96cbc4007c02a1684e19a /libimagref | |
parent | 5a4e6b4af67448486e940817084fafc5965a6480 (diff) | |
parent | 900513594c6b56c5ea4c9df79616681b11f86f2d (diff) |
Merge pull request #497 from matthiasbeyer/libimagref/list
libimagref/list
Diffstat (limited to 'libimagref')
-rw-r--r-- | libimagref/Cargo.toml | 3 | ||||
-rw-r--r-- | libimagref/src/error.rs | 2 | ||||
-rw-r--r-- | libimagref/src/lib.rs | 3 | ||||
-rw-r--r-- | libimagref/src/lister.rs | 193 | ||||
-rw-r--r-- | libimagref/src/reference.rs | 8 |
5 files changed, 208 insertions, 1 deletions
diff --git a/libimagref/Cargo.toml b/libimagref/Cargo.toml index f0c31392..dd14cdbc 100644 --- a/libimagref/Cargo.toml +++ b/libimagref/Cargo.toml @@ -21,3 +21,6 @@ path = "../libimagerror" [dependencies.libimagutil] path = "../libimagutil" +[dependencies.libimagentrylist] +path = "../libimagentrylist" + diff --git a/libimagref/src/error.rs b/libimagref/src/error.rs index 4fee1429..fdd6314a 100644 --- a/libimagref/src/error.rs +++ b/libimagref/src/error.rs @@ -13,6 +13,7 @@ generate_error_module!( PathCanonicalizationError => "Path cannot be canonicalized", TypeConversionError => "Couldn't convert types", + RefToDisplayError => "Cannot convert Ref to string to show it to user", RefNotInStore => "Ref/StoreId does not exist in store", @@ -26,4 +27,5 @@ generate_error_module!( pub use self::error::RefError; pub use self::error::RefErrorKind; +pub use self::error::MapErrInto; diff --git a/libimagref/src/lib.rs b/libimagref/src/lib.rs index c34651ab..c6f595c2 100644 --- a/libimagref/src/lib.rs +++ b/libimagref/src/lib.rs @@ -9,11 +9,12 @@ extern crate walkdir; #[macro_use] extern crate libimagstore; #[macro_use] extern crate libimagerror; #[macro_use] extern crate libimagutil; +extern crate libimagentrylist; module_entry_path_mod!("ref", "0.2.0"); pub mod error; pub mod flags; +pub mod lister; pub mod reference; pub mod result; - diff --git a/libimagref/src/lister.rs b/libimagref/src/lister.rs new file mode 100644 index 00000000..2889ee52 --- /dev/null +++ b/libimagref/src/lister.rs @@ -0,0 +1,193 @@ +use std::default::Default; +use std::io::stdout; +use std::io::Write; + +use toml::Value; + +use libimagentrylist::lister::Lister; +use libimagentrylist::result::Result; +use libimagerror::trace::trace_error; +use libimagstore::store::Entry; +use libimagstore::store::FileLockEntry; +use libimagerror::into::IntoError; +use libimagentrylist::error::ListError as LE; +use libimagentrylist::error::ListErrorKind as LEK; + +use reference::Ref; +use error::MapErrInto; +use error::RefErrorKind as REK; + +pub struct RefLister { + check_dead: bool, + check_changed: bool, + check_changed_content: bool, + check_changed_permiss: bool, +} + +impl RefLister { + + pub fn new() -> RefLister { + RefLister::default() + } + + pub fn check_dead(mut self, b: bool) -> RefLister { + self.check_dead = b; + self + } + + pub fn check_changed(mut self, b: bool) -> RefLister { + self.check_changed = b; + self + } + + pub fn check_changed_content(mut self, b: bool) -> RefLister { + self.check_changed_content = b; + self + } + + pub fn check_changed_permiss(mut self, b: bool) -> RefLister { + self.check_changed_permiss = b; + self + } + +} + +impl Default for RefLister { + + fn default() -> RefLister { + RefLister { + check_dead: false, + check_changed: false, + check_changed_content: false, + check_changed_permiss: false, + } + } +} + +fn list_fn(e: &Entry) -> String { + let stored_hash = match e.get_header().read("ref.content_hash") { + Ok(Some(Value::String(s))) => s.clone(), + _ => String::from("<Error: Could not read stored hash>"), + }; + + let filepath = match e.get_header().read("ref.path") { + Ok(Some(Value::String(ref s))) => s.clone(), + _ => String::from("<Error: Could not read file path>"), + }; + + format!("Ref({} -> {})", stored_hash, filepath) +} + +impl Lister for RefLister { + + fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> { + + debug!("Called list()"); + let (r, n) = entries.fold((Ok(()), 0), |(accu, i), entry| { + 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) + .and_then(|s| { + write!(stdout(), "{}\n", s) + .map_err(Box::new) + .map_err(|e| LEK::FormatError.into_error_with_cause(e)) + }) + .map_err_into(REK::RefToDisplayError) + }) + .map(|_| ()); + (r, i + 1) + }); + debug!("Iterated over {} entries", n); + r.map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e))) + } + +} + +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 { + check_changed_content(r) && check_changed_permiss(r) +} + +fn check_changed_content(r: &Ref) -> bool { + let eq = r.get_current_hash() + .and_then(|hash| r.get_stored_hash().map(|stored| (hash, stored))) + .map(|(hash, stored)| hash == stored); + + match eq { + Ok(eq) => eq, + Err(e) => { + warn!("Could not check whether the ref {} changed on the FS:", r); + trace_error(&e); + + // We continue here and tell the callee that this reference is unchanged + false + }, + } +} + +fn check_changed_permiss(r: &Ref) -> bool { + warn!("Permission changes tracking not supported yet."); + false +} + diff --git a/libimagref/src/reference.rs b/libimagref/src/reference.rs index a6b6a9ef..e756aeb9 100644 --- a/libimagref/src/reference.rs +++ b/libimagref/src/reference.rs @@ -511,6 +511,14 @@ impl<'a> Display for Ref<'a> { } +impl<'a> Into<FileLockEntry<'a>> for Ref<'a> { + + fn into(self) -> FileLockEntry<'a> { + self.0 + } + +} + fn hash_file_contents(f: &mut File) -> String { let mut hasher = Sha1::new(); let mut s = String::new(); |