summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2018-02-13 21:11:45 +0100
committerMatthias Beyer <mail@beyermatthias.de>2018-02-19 12:14:32 +0100
commit1014f58cfcc2090ee72b1fc43088e0b78fb5e474 (patch)
treeeee3df916277936ba804f738f31412078ee7309e
parent73af12188289cbf6140f2db58c0a12f529bba832 (diff)
Rewrite interface
-rw-r--r--lib/entry/libimagentryref/Cargo.toml2
-rw-r--r--lib/entry/libimagentryref/src/error.rs68
-rw-r--r--lib/entry/libimagentryref/src/lib.rs4
-rw-r--r--lib/entry/libimagentryref/src/reference.rs306
-rw-r--r--lib/entry/libimagentryref/src/refstore.rs313
-rw-r--r--lib/entry/libimagentryref/src/util.rs52
6 files changed, 110 insertions, 635 deletions
diff --git a/lib/entry/libimagentryref/Cargo.toml b/lib/entry/libimagentryref/Cargo.toml
index e46d2103..5e1f7f9a 100644
--- a/lib/entry/libimagentryref/Cargo.toml
+++ b/lib/entry/libimagentryref/Cargo.toml
@@ -22,11 +22,9 @@ maintenance = { status = "actively-developed" }
[dependencies]
itertools = "0.7"
log = "0.4.0"
-rust-crypto = "0.2"
toml = "0.4"
toml-query = "0.6"
error-chain = "0.11"
-walkdir = "1"
libimagstore = { version = "0.7.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.7.0", path = "../../../lib/core/libimagerror" }
diff --git a/lib/entry/libimagentryref/src/error.rs b/lib/entry/libimagentryref/src/error.rs
index 3c75c202..1a76aea0 100644
--- a/lib/entry/libimagentryref/src/error.rs
+++ b/lib/entry/libimagentryref/src/error.rs
@@ -23,7 +23,6 @@ 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);
EntryUtilError(::libimagentryutil::error::EntryUtilError, ::libimagentryutil::error::EntryUtilErrorKind);
@@ -34,16 +33,10 @@ error_chain! {
Utf8Error(::std::string::FromUtf8Error);
TomlDeError(::toml::de::Error);
TomlSerError(::toml::ser::Error);
- WalkDirError(::walkdir::Error);
}
errors {
- UTF8Error {
- description("UTF8 Error")
- display("UTF8 Error")
- }
-
- HeaderTypeError {
+ HeaderTypeError {
description("Header type error")
display("Header type error")
}
@@ -53,12 +46,12 @@ error_chain! {
display("Header field missing error")
}
- HeaderFieldWriteError {
+ HeaderFieldWriteError {
description("Header field cannot be written")
display("Header field cannot be written")
}
- HeaderFieldReadError {
+ HeaderFieldReadError {
description("Header field cannot be read")
display("Header field cannot be read")
}
@@ -73,61 +66,6 @@ error_chain! {
display("Path cannot be converted because of UTF8 Error")
}
- PathHashingError {
- description("Path cannot be hashed")
- display("Path cannot be hashed")
- }
-
- PathCanonicalizationError {
- description("Path cannot be canonicalized")
- display("Path cannot be canonicalized")
- }
-
- TypeConversionError {
- description("Couldn't convert types")
- display("Couldn't convert types")
- }
-
- RefToDisplayError {
- description("Cannot convert Ref to string to show it to user")
- display("Cannot convert Ref to string to show it to user")
- }
-
- RefNotInStore {
- description("Ref/StoreId does not exist in store")
- display("Ref/StoreId does not exist in store")
- }
-
- RefTargetDoesNotExist {
- description("Ref Target does not exist")
- display("Ref Target does not exist")
- }
-
- RefTargetPermissionError {
- description("Ref Target permissions insufficient for referencing")
- display("Ref Target permissions insufficient for referencing")
- }
-
- RefTargetCannotBeHashed {
- description("Ref Target cannot be hashed (is it a directory?)")
- display("Ref Target cannot be hashed (is it a directory?)")
- }
-
- RefTargetFileCannotBeOpened {
- description("Ref Target File cannot be open()ed")
- display("Ref Target File cannot be open()ed")
- }
-
- RefTargetCannotReadPermissions {
- description("Ref Target: Cannot read permissions")
- display("Ref Target: Cannot read permissions")
- }
-
- RefHashingError {
- description("Error while hashing")
- display("Error while hashing")
- }
-
}
}
diff --git a/lib/entry/libimagentryref/src/lib.rs b/lib/entry/libimagentryref/src/lib.rs
index ea0824d3..7311d13b 100644
--- a/lib/entry/libimagentryref/src/lib.rs
+++ b/lib/entry/libimagentryref/src/lib.rs
@@ -36,11 +36,9 @@
)]
#[macro_use] extern crate log;
-extern crate crypto;
extern crate itertools;
extern crate toml;
extern crate toml_query;
-extern crate walkdir;
#[macro_use] extern crate libimagstore;
extern crate libimagerror;
@@ -53,4 +51,4 @@ module_entry_path_mod!("ref");
pub mod error;
pub mod reference;
pub mod refstore;
-mod util;
+
diff --git a/lib/entry/libimagentryref/src/reference.rs b/lib/entry/libimagentryref/src/reference.rs
index dcfc9a1a..43222a86 100644
--- a/lib/entry/libimagentryref/src/reference.rs
+++ b/lib/entry/libimagentryref/src/reference.rs
@@ -21,316 +21,82 @@
//! files outside of the imag store.
use std::path::PathBuf;
-use std::fs::File;
-use std::fs::Permissions;
+use std::result::Result as RResult;
-use libimagstore::store::Entry;
use libimagentryutil::isa::Is;
use libimagentryutil::isa::IsKindHeaderPathProvider;
+use libimagstore::store::Entry;
-use toml::Value;
-use toml_query::read::TomlValueReadTypeExt;
-use toml_query::set::TomlValueSetExt;
+use toml_query::read::TomlValueReadExt;
+use refstore::UniqueRefPathGenerator;
-use error::RefErrorKind as REK;
-use error::RefError as RE;
-use error::ResultExt;
use error::Result;
-use hasher::*;
+use error::RefError as RE;
+use error::RefErrorKind as REK;
pub trait Ref {
/// Check whether the underlying object is actually a ref
fn is_ref(&self) -> Result<bool>;
- /// Get the hash from the path of the ref
- fn get_path_hash(&self) -> Result<String>;
-
- /// Get the hash of the link target which is stored in the ref object
- fn get_stored_hash(&self) -> Result<String>;
-
- /// 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 the hash of the link target by reading the link target and hashing the contents
- fn get_current_hash(&self) -> Result<String>;
-
- /// 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>;
-
- /// check whether the pointer the Ref represents still points to a file which exists
- fn fs_link_exists(&self) -> Result<bool>;
-
- /// Alias for `r.fs_link_exists() && r.deref().is_file()`
- fn is_ref_to_file(&self) -> Result<bool>;
-
- /// Alias for `r.fs_link_exists() && r.deref().is_dir()`
- fn is_ref_to_dir(&self) -> Result<bool>;
-
- /// Alias for `!Ref::fs_link_exists()`
- fn is_dangling(&self) -> Result<bool>;
-
- /// 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>;
-
- /// 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.
+ /// Get the stored hash.
///
- /// # 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>;
+ /// Does not need a `UniqueRefPathGenerator` as it reads the hash stored in the header
+ fn get_hash(&self) -> Result<String>;
- /// Get the permissions of the file which are present
- fn get_current_permissions(&self) -> Result<Permissions>;
-}
-
-provide_kindflag_path!(pub IsRef, "ref.is_ref");
-
-impl Ref for Entry {
-
- /// Check whether the underlying object is actually a ref
- fn is_ref(&self) -> Result<bool> {
- self.is::<IsRef>().map_err(From::from)
- }
-
- /// Get the hash from the path of the ref
- fn get_path_hash(&self) -> Result<String> {
- self.get_location()
- .clone()
- .into_pathbuf()
- .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(String::from("String splitting error"))
- .map_err(From::from)
- })
- }
-
- /// Get the hash of the link target which is stored in the ref object
- 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.
- fn get_stored_hash_with_hasher<H: Hasher>(&self, h: &H) -> Result<String> {
- self.get_header()
- .read_string(&format!("ref.content_hash.{}", h.hash_name())[..])?
- .ok_or(RE::from_kind(REK::HeaderFieldMissingError))
- }
+ /// Get the referenced path.
+ ///
+ /// Does not need a `UniqueRefPathGenerator` as it reads the path stored in the header.
+ fn get_path(&self) -> Result<PathBuf>;
- /// Get the hash of the link target by reading the link target and hashing the contents
- fn get_current_hash(&self) -> Result<String> {
- self.get_current_hash_with_hasher(DefaultHasher::new())
- }
+ /// Check whether the referenced file still matches its hash
+ fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> Result<bool>;
- /// 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, mut h: H) -> Result<String> {
- self.fs_file()
- .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))
- }
-
- /// check whether the pointer the Ref represents still points to a file which exists
- fn fs_link_exists(&self) -> Result<bool> {
- self.fs_file().map(|pathbuf| pathbuf.exists())
- }
+ /// Update the stored hash
+ ///
+ /// This updates the hash in the header and moves the entry to the appropriate location
+ fn update_hash<RPG: UniqueRefPathGenerator>(&mut self, store: &Store) -> Result<bool>;
/// Alias for `r.fs_link_exists() && r.deref().is_file()`
fn is_ref_to_file(&self) -> Result<bool> {
- self.fs_file().map(|pathbuf| pathbuf.is_file())
+ self.get_path().map(|p| p.is_file())
}
/// Alias for `r.fs_link_exists() && r.deref().is_dir()`
fn is_ref_to_dir(&self) -> Result<bool> {
- self.fs_file().map(|pathbuf| pathbuf.is_dir())
+ self.get_path().map(|p| p.is_dir())
}
/// Alias for `!Ref::fs_link_exists()`
fn is_dangling(&self) -> Result<bool> {
- self.fs_link_exists().map(|b| !b)
- }
-
- /// 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> {
- match (self.fs_link_valid_permissions(), self.fs_link_valid_hash()) {
- (Ok(true) , Ok(true)) => Ok(true),
- (Ok(_) , Ok(_)) => Ok(false),
- (Err(e) , _) => Err(e),
- (_ , Err(e)) => Err(e),
- }
+ self.get_path().map(|p| !p.exists())
}
- /// Check whether the file permissions of the referenced file are equal to the stored
- /// permissions
- fn fs_link_valid_permissions(&self) -> Result<bool> {
- self
- .get_header()
- .read_bool("ref.permissions.ro")
- .chain_err(|| REK::HeaderFieldReadError)?
- .ok_or(RE::from_kind(REK::HeaderFieldMissingError))
- .and_then(|ro| self.get_current_permissions().map(|perm| ro == perm.readonly()))
- .chain_err(|| REK::RefTargetCannotReadPermissions)
- }
-
- /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
- fn fs_link_valid_hash(&self) -> Result<bool> {
- let stored_hash = self.get_stored_hash()?;
- let current_hash = self.get_current_hash()?;
- Ok(stored_hash == current_hash)
- }
-
- /// 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<()> {
- 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()
- fn update_ref_with_hasher<H: Hasher>(&mut self, h: &H) -> Result<()> {
- let current_hash = self.get_current_hash()?; // uses the default hasher
- let current_perm = self.get_current_permissions()?;
+}
- self
- .get_header_mut()
- .set("ref.permissions.ro", Value::Boolean(current_perm.readonly()))
- ?;
+provide_kindflag_path!(pub IsRef, "ref.is_ref");
- self
- .get_header_mut()
- .set(&format!("ref.content_hash.{}", h.hash_name())[..], Value::String(current_hash))
- ?;
+impl Ref for Entry {
- Ok(())
+ /// Check whether the underlying object is actually a ref
+ fn is_ref(&self) -> Result<bool> {
+ self.is::<IsRef>().map_err(From::from)
}
- /// Get the path of the file which is reffered to by this Ref
- fn fs_file(&self) -> Result<PathBuf> {
- self.get_header()
- .read_string("ref.path")?
- .ok_or(RE::from_kind(REK::HeaderFieldMissingError))
- .map(PathBuf::from)
+ fn get_hash(&self) -> Result<String> {
+ unimplemented!()
}
- /// 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> {
- self.refind_with_hasher(search_roots, DefaultHasher::new())
+ fn get_path(&self) -> Result<PathBuf> {
+ unimplemented!()
}
- /// 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;
- use walkdir::WalkDir;
-
- self.get_stored_hash()
- .and_then(|stored_hash| {
- search_roots
- .unwrap_or(vec![PathBuf::from("/")])
- .into_iter()
- .map(|root| {
- WalkDir::new(root)
- .follow_links(false)
- .into_iter()
- .map(|entry| {
- entry
- .map_err(From::from)
- .and_then(|entry| {
- let pb = PathBuf::from(entry.path());
- File::open(entry.path())
- .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)
- })
- .map(|(path, hash)| {
- if hash == stored_hash {
- Some(path)
- } else {
- None
- }
- })
- })
- .filter_map(Result::ok)
- .filter_map(|e| e)
- .next()
- })
- .flatten()
- .next()
- .ok_or(RE::from_kind(REK::RefTargetDoesNotExist))
- })
+ fn hash_valid<RPG: UniqueRefPathGenerator>(&self) -> Result<bool> {
+ unimplemented!()
}
- /// 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)
- .chain_err(|| REK::HeaderFieldReadError)
- })
- .and_then(|file| {
- file
- .metadata()
- .map(|md| md.permissions())
- .chain_err(|| REK::RefTargetCannotReadPermissions)
- })
+ fn update_hash<RPG: UniqueRefPathGenerator>(&mut self, store: &Store) -> Result<bool> {
+ unimplemented!()
}
}
diff --git a/lib/entry/libimagentryref/src/refstore.rs b/lib/entry/libimagentryref/src/refstore.rs
index 7248bbe8..5f1c780d 100644
--- a/lib/entry/libimagentryref/src/refstore.rs
+++ b/lib/entry/libimagentryref/src/refstore.rs
@@ -17,280 +17,107 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
+use std::path::Path;
use std::path::PathBuf;
-use std::collections::BTreeMap;
-use std::fs::File;
use libimagstore::store::FileLockEntry;
-use libimagstore::storeid::IntoStoreId;
-use libimagstore::storeid::StoreId;
-use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::Store;
+use libimagstore::storeid::StoreId;
use libimagentryutil::isa::Is;
+use toml_query::insert::TomlValueInsertExt;
use toml::Value;
-use error::RefErrorKind as REK;
use error::RefError as RE;
-use error::ResultExt;
-use error::Result;
-use flags::RefFlags;
+use error::RefErrorKind as REK;
use reference::IsRef;
-use hasher::*;
-use module_path::ModuleEntryPath;
-use util::*;
-
-pub trait RefStore {
-
- /// Check whether there is a reference to the file at `pb`
- fn exists(&self, pb: PathBuf) -> Result<bool>;
-
- /// Get a Ref object from the store by hash.
- ///
- /// Returns None if the hash cannot be found.
- fn get_by_hash<'a>(&'a self, hash: String) -> Result<Option<FileLockEntry<'a>>>;
-
- /// Find a store id by partial ref (also see documentation for
- /// `RefStore::get_by_partitial_hash()`.
- fn find_storeid_by_partial_hash(&self, hash: &String) -> Result<Option<StoreId>>;
-
- /// Get a Ref object from the store by (eventually partial) hash.
- ///
- /// If the hash is complete, `RefStore::get_by_hash()` should be used as it is cheaper.
- /// If the hash comes from user input and thus might be abbreviated, this function can be used.
- fn get_by_partitial_hash<'a>(&'a self, hash: &String) -> Result<Option<FileLockEntry<'a>>>;
- /// Delete a ref by hash
- ///
- /// If the returned Result contains an error, the ref might not be deleted.
- fn delete_by_hash(&self, hash: String) -> Result<()>;
+/// A UniqueRefPathGenerator generates unique Pathes
+///
+/// It is basically a functor which generates a StoreId from a &Path.
+/// For more information have a look at the documentation of RefStore.
+pub trait UniqueRefPathGenerator {
+ type Error: From<RE>;
- /// Create a Ref object which refers to `pb`
- fn create<'a>(&'a self, pb: PathBuf, flags: RefFlags) -> Result<FileLockEntry<'a>>;
-
- fn create_with_hasher<'a, H: Hasher>(&'a self, pb: PathBuf, flags: RefFlags, h: H)
- -> Result<FileLockEntry<'a>>;
+ /// The collection the `StoreId` should be created for
+ fn collection() -> &'static str {
+ "ref"
+ }
- /// Get all reference objects
- fn all_references(&self) -> Result<StoreIdIterator>;
+ /// A function which should generate a unique string for a Path
+ fn unique_hash<A: AsRef<Path>>(path: A) -> Result<String, Self::Error>;
+ /// Postprocess the generated `StoreId` object
+ fn postprocess_storeid(sid: StoreId) -> Result<StoreId, Self::Error> {
+ Ok(sid)
+ }
}
-impl RefStore for Store {
-
- /// Check whether there is a reference to the file at `pb`
- fn exists(&self, pb: PathBuf) -> Result<bool> {
- pb.canonicalize()
- .chain_err(|| REK::PathCanonicalizationError)
- .and_then(|c| hash_path(&c))
- .chain_err(|| REK::PathHashingError)
- .and_then(|hash| {
- 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
- // 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 = r.to_str()
- .chain_err(|| REK::TypeConversionError)
- .map(|s| s.contains(&hash[..]))
- ?;
+/// A extensions for the `Store` to handle `Ref` objects
+///
+/// The RefStore handles refs using a `UniqueRefPathGenerator`. The `UniqueRefPathGenerator`, as it
+/// name suggests, generates unique `StoreId`s for a `&Path`. It is a functor `&Path -> StoreId`.
+///
+/// It provides three functions which are called in the following sequence:
+///
+/// * The `UniqueRefPathGenerator::collection()` function is used for get the collection a `StoreId`
+/// should be in (The first element of the `StoreId` path)
+/// * The `UniqueRefPathGenerator::unique_hash()` gets the `&Path` which it then should generate a
+/// unique String for. How this is done does not matter. It can hash the Path itself, read the
+/// file and hash that or something else. It should be reproduceable, though.
+/// * These two parts are joined and put into a `StoreId` which the
+/// `UniqueRefPathGenerator::postprocess_storeid()` function is then allowed to postprocess (for
+/// example add more parts to the StoreId). The default implementation does nothing.
+///
+/// The StoreId which is generated is then used to carry out the actual action (reading, creating
+/// ...).
+/// If a entry is created, header information is set (that it is a ref, the hash which was just
+/// generated and the path of the referenced file)
+///
+/// # Details
+///
+/// The `UniqueRefPathGenerator` is passed as type parameter to enforce some semantics:
+///
+/// * The used `UniqueRefPathGenerator` is defined by the implementation rather than by the runtime
+/// of the program or some environment. Of course this is only a small hurdle to enforce this, but
+/// a hint.
+/// * The `UniqueRefPathGenerator` is a functor which does not carry state.
+///
+pub trait RefStore<'a> {
+
+ fn get_ref<RPG: UniqueRefPathGenerator>(&'a self, hash: &String) -> Result<Option<FileLockEntry<'a>>, RPG::Error>;
+ fn create_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>, RPG::Error>;
+ fn retrieve_ref<RPG: UniqueRefPathGenerator, A: AsRef<Path>>(&'a self, path: A) -> Result<FileLockEntry<'a>, RPG::Error>;
- if !contains_hash {
- continue;
- }
-
- match self.get(r.clone())? {
- Some(fle) => {
- if read_reference(&fle).map(|path| path == pb).unwrap_or(false) {
- return Ok(true)
- }
- },
-
- None => {
- let e = format!("Failed to get from store: {}", r);
- return Err(e).map_err(From::from)
- },
- }
- }
+}
- Ok(false)
- })
- }
+impl<'a> RefStore<'a> for Store {
- /// Get a Ref object from the store by hash.
- ///
- /// Returns None if the hash cannot be found.
- fn get_by_hash<'a>(&'a self, hash: String) -> Result<Option<FileLockEntry<'a>>> {
- ModuleEntryPath::new(hash)
- .into_storeid()
- .and_then(|id| self.get(id))
- .map_err(From::from)
+ fn get_ref<RPG: UniqueRefPathGenerator>(&self) -> Result<Option<FileLockEntry<'a>>, RPG::Error> {
+ unimplemented!()
}
- fn find_storeid_by_partial_hash(&self, hash: &String) -> Result<Option<StoreId>> {
- debug!("Trying to find '{}' in store...", hash);
- for id in self.retrieve_for_module("ref")? {
- let components_have_hash = id
- .components()
- .any(|c| c.as_os_str().to_str().map(|s| s.contains(hash)).unwrap_or(false));
-
- if components_have_hash {
- debug!("Found hash '{}' in {:?}", hash, id);
- return Ok(Some(id))
- }
- }
- Ok(None)
+ fn create_ref<RPG: UniqueRefPathGenerator>(&self) -> Result<FileLockEntry<'a>, RPG::Error> {
+ unimplemented!()
}
- /// Get a Ref object from the store by (eventually partial) hash.
- ///
- /// If the hash is complete, `RefStore::get_by_hash()` should be used as it is cheaper.
- /// If the hash comes from user input and thus might be abbreviated, this function can be used.
- fn get_by_partitial_hash<'a>(&'a self, hash: &String) -> Result<Option<FileLockEntry<'a>>> {
- match self.find_storeid_by_partial_hash(hash)? {
- Some(id) => self.get(id).map_err(From::from),
- None => Ok(None),
- }
+ fn retrieve_ref<RPG: UniqueRefPathGenerator>(&self) Result<FileLockEntry<'a>, RPG::Error> {
+ unimplemented!()
}
- /// Delete a ref by hash
- ///
- /// If the returned Result contains an error, the ref might not be deleted.
- fn delete_by_hash(&self, hash: String) -> Result<()> {
- ModuleEntryPath::new(hash)
- .into_storeid()
- .and_then(|id| self.delete(id))
- .map_err(From::from)
+ fn delete_ref<RPG: UniqueRefPathGenerator>(&self) -> Result<(), RPG::Error> {
+ unimplemented!()
}
- /// Create a Ref object which refers to `pb`
- fn create<'a>(&'a self, pb: PathBuf, flags: RefFlags) -> Result<FileLockEntry<'a>> {
- self.create_with_hasher(pb, flags, DefaultHasher::new())
+ fn ref_exists<RPG: UniqueRefPathGenerator>(&self) -> Result<bool, RPG::Error> {
+ unimplemented!()
}
- fn create_with_hasher<'a, H: Hasher>(&'a self, pb: PathBuf, flags: RefFlags, mut h: H)
- -> Result<FileLockEntry<'a>>
+ fn move_ref_by_id<OLDRPG: UniqueRefPathGenerator, NEWRPG: UniqueRefPathGenerator>(&self)
+ -> Result<(), Either<OLDRPG::Error, NEWRPG::Error>>
{
- use toml_query::insert::TomlValueInsertExt;
-
- if !pb.exists() {
- return Err(RE::from_kind(REK::RefTargetDoesNotExist));
- }
- if flags.get_content_hashing() && pb.is_dir() {
- return Err(RE::from_kind(REK::RefTargetCannotBeHashed));
- }
-
- let (mut fle, content_hash, permissions, canonical_path) = { // scope to be able to fold
- File::open(pb.clone())
- .chain_err(|| REK::RefTargetFileCannotBeOpened)
-
- // 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(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(file.metadata()
- .map(|md| md.permissions())
- .chain_err(|| REK::RefTargetCannotReadPermissions)?)
- } 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
- .chain_err(|| REK::PathCanonicalizationError)
- })
-
- // 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 = hash_path(&can).chain_err(|| REK::PathHashingError)?;
-
- 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(RE::from_kind(REK::PathUTF8Error)),
- 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 = self.create(ModuleEntryPath::new(path_hash))?;
- 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(Some(_)) => {
- let e = RE::from_kind(REK::HeaderFieldAlreadyExistsError);
- return Err(e).chain_err(|| REK::HeaderFieldWriteError);
- },
- Ok(None) => {
- // Okay, we just inserted a new header value...
- },
- Err(e) => return Err(e).chain_err(|| REK::HeaderFieldWriteError),
- }
- }
- &None => {
- debug!("Not going to insert.");
- }
- }
- }
-
- let _ = fle.set_isflag::<IsRef>()?;
-
- Ok(fle)
+ unimplemented!()
}
- fn all_references(&self) -> Result<StoreIdIterator> {
- self.retrieve_for_module("ref").map_err(From::from)
- }
}
diff --git a/lib/entry/libimagentryref/src/util.rs b/lib/entry/libimagentryref/src/util.rs
deleted file mode 100644
index 878b98cd..00000000
--- a/lib/entry/libimagentryref/src/util.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015-2018 Matthias Beyer <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public L