summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-06-04 16:30:43 +0200
committerMatthias Beyer <mail@beyermatthias.de>2017-06-06 11:12:37 +0200
commit204ef2470381967c2cd9044c623f83f2eaff7588 (patch)
treeb4c1f5799cb4ee39f4c7439bf7352dfde5e1250e
parent1b8ccb42a715e83ef95ade3fa2615a6cfdaf67a0 (diff)
downloadimag-204ef2470381967c2cd9044c623f83f2eaff7588.zip
imag-204ef2470381967c2cd9044c623f83f2eaff7588.tar.gz
Remove hook support from store
-rw-r--r--libimagstore/src/configuration.rs596
-rw-r--r--libimagstore/src/error.rs15
-rw-r--r--libimagstore/src/hook/accessor.rs49
-rw-r--r--libimagstore/src/hook/aspect.rs151
-rw-r--r--libimagstore/src/hook/error.rs65
-rw-r--r--libimagstore/src/hook/mod.rs36
-rw-r--r--libimagstore/src/hook/position.rs32
-rw-r--r--libimagstore/src/hook/result.rs22
-rw-r--r--libimagstore/src/lib.rs1
-rw-r--r--libimagstore/src/store.rs860
10 files changed, 7 insertions, 1820 deletions
diff --git a/libimagstore/src/configuration.rs b/libimagstore/src/configuration.rs
index 06e0d3c..0dfc049 100644
--- a/libimagstore/src/configuration.rs
+++ b/libimagstore/src/configuration.rs
@@ -20,160 +20,19 @@
use toml::Value;
use libimagerror::into::IntoError;
-use libimagutil::iter::FoldResult;
use store::Result;
/// Check whether the configuration is valid for the store
-///
-/// The passed `Value` _must be_ the `[store]` sub-tree of the configuration. Otherwise this will
-/// fail.
-///
-/// It checks whether the configuration looks like the store wants it to be:
-///
-/// ```toml
-/// [store]
-/// pre-create-hook-aspects = [ "misc", "encryption", "version-control"]
-///
-/// [store.aspects.misc]
-/// parallel = true
-///
-/// [store.aspects.encryption]
-/// parallel = false
-///
-/// [store.aspects.version-control]
-/// parallel = false
-///
-/// [store.hooks.gnupg]
-/// aspect = "encryption"
-/// key = "0x123456789"
-///
-/// [store.hooks.git]
-/// aspect = "version-control"
-/// ```
-///
-/// It checks:
-/// * Whether all the maps are there (whether store, store.aspects, store.aspects.example are all
-/// maps)
-/// * Whether each aspect configuration has a "parallel = <Boolean>" setting
-/// * Whether each hook congfiguration has a "aspect = <String>" setting
-///
-/// It does NOT check:
-/// * Whether all aspects which are used in the hook configuration are also configured
-///
-/// No configuration is a valid configuration, as the store will use the most conservative settings
-/// automatically. This has also performance impact, as all hooks run in no-parallel mode then.
-/// You have been warned!
-///
-///
pub fn config_is_valid(config: &Option<Value>) -> Result<()> {
- use std::collections::BTreeMap;
use error::StoreErrorKind as SEK;
if config.is_none() {
return Ok(());
}
- /// Check whether the config has a key with a string array.
- /// The `key` is the key which is checked
- /// The `kind` is the error kind which is used as `cause` if there is an error, so we can
- /// indicate via error type which key is missing
- fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str,
- kind: SEK) -> Result<()> {
- v.get(key)
- .ok_or_else(|| {
- warn!("Required key '{}' is not in store config", key);
- SEK::ConfigKeyMissingError.into_error_with_cause(Box::new(kind.into_error()))
- })
- .and_then(|t| match *t {
- Value::Array(ref a) => {
- a.iter().fold_result(|elem| if is_match!(*elem, Value::String(_)) {
- Ok(())
- } else {
- let cause = Box::new(kind.into_error());
- Err(SEK::ConfigTypeError.into_error_with_cause(cause))
- })
- },
- _ => {
- warn!("Key '{}' in store config should contain an array", key);
- Err(SEK::ConfigTypeError.into_error_with_cause(Box::new(kind.into_error())))
- }
- })
- }
-
- /// Check that
- /// * the top-level configuration
- /// * is a table
- /// * where all entries of a key `section` (eg. "hooks" or "aspects")
- /// * Are maps
- /// * where each has a key `key` (eg. "aspect" or "parallel")
- /// * which fullfills constraint `f` (typecheck)
- fn check_all_inner_maps_have_key_with<F>(store_config: &BTreeMap<String, Value>,
- section: &str,
- key: &str,
- f: F)
- -> Result<()>
- where F: Fn(&Value) -> bool
- {
- store_config.get(section) // The store config has the section `section`
- .ok_or_else(|| {
- warn!("Store config expects section '{}' to be present, but isn't.", section);
- SEK::ConfigKeyMissingError.into_error()
- })
- .and_then(|section_table| match *section_table { // which is
- Value::Table(ref section_table) => // a table
- section_table.iter().fold_result(|(inner_key, cfg)| {
- match *cfg {
- Value::Table(ref hook_config) => { // are tables
- // with a key
- let hook_aspect_is_valid = try!(hook_config.get(key)
- .map(|hook_aspect| f(&hook_aspect))
- .ok_or(SEK::ConfigKeyMissingError.into_error())
- );
-
- if !hook_aspect_is_valid {
- Err(SEK::ConfigTypeError.into_error())
- } else {
- Ok(())
- }
- },
- _ => {
- warn!("Store config expects '{}' to be in '{}.{}', but isn't.",
- key, section, inner_key);
- Err(SEK::ConfigKeyMissingError.into_error())
- }
- }
- }),
- _ => {
- warn!("Store config expects '{}' to be a Table, but isn't.", section);
- Err(SEK::ConfigTypeError.into_error())
- }
- })
- }
-
match *config {
- Some(Value::Table(ref t)) => {
- try!(has_key_with_string_ary(t, "store-unload-hook-aspects", SEK::ConfigKeyUnloadAspectsError));
-
- try!(has_key_with_string_ary(t, "pre-create-hook-aspects", SEK::ConfigKeyPreCreateAspectsError));
- try!(has_key_with_string_ary(t, "post-create-hook-aspects", SEK::ConfigKeyPostCreateAspectsError));
- try!(has_key_with_string_ary(t, "pre-retrieve-hook-aspects", SEK::ConfigKeyPreRetrieveAspectsError));
- try!(has_key_with_string_ary(t, "post-retrieve-hook-aspects", SEK::ConfigKeyPostRetrieveAspectsError));
- try!(has_key_with_string_ary(t, "pre-update-hook-aspects", SEK::ConfigKeyPreUpdateAspectsError));
- try!(has_key_with_string_ary(t, "post-update-hook-aspects", SEK::ConfigKeyPostUpdateAspectsError));
- try!(has_key_with_string_ary(t, "pre-delete-hook-aspects", SEK::ConfigKeyPreDeleteAspectsError));
- try!(has_key_with_string_ary(t, "post-delete-hook-aspects", SEK::ConfigKeyPostDeleteAspectsError));
-
- // The section "hooks" has maps which have a key "aspect" which has a value of type
- // String
- try!(check_all_inner_maps_have_key_with(t, "hooks", "aspect",
- |asp| is_match!(asp, &Value::String(_))));
-
- // The section "aspects" has maps which have a key "parllel" which has a value of type
- // Boolean
- check_all_inner_maps_have_key_with(t, "aspects", "parallel",
- |asp| is_match!(asp, &Value::Boolean(_)))
- }
+ Some(Value::Table(_)) => Ok(()),
_ => {
warn!("Store config is no table");
Err(SEK::ConfigTypeError.into_error())
@@ -207,152 +66,6 @@ pub fn config_implicit_store_create_allowed(config: Option<&Value>) -> bool {
}).unwrap_or(false)
}
-pub fn get_store_unload_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("store-unload-hook-aspects", value)
-}
-
-pub fn get_pre_create_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("pre-create-hook-aspects", value)
-}
-
-pub fn get_post_create_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("post-create-hook-aspects", value)
-}
-
-pub fn get_pre_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("pre-retrieve-hook-aspects", value)
-}
-
-pub fn get_post_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("post-retrieve-hook-aspects", value)
-}
-
-pub fn get_pre_update_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("pre-update-hook-aspects", value)
-}
-
-pub fn get_post_update_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("post-update-hook-aspects", value)
-}
-
-pub fn get_pre_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("pre-delete-hook-aspects", value)
-}
-
-pub fn get_post_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("post-delete-hook-aspects", value)
-}
-
-pub fn get_pre_move_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("pre-move-hook-aspects", value)
-}
-
-pub fn get_post_move_aspect_names(value: &Option<Value>) -> Vec<String> {
- get_aspect_names_for_aspect_position("post-move-hook-aspects", value)
-}
-
-#[derive(Debug)]
-pub struct AspectConfig {
- parallel: bool,
- mutable_hooks: bool,
- config: Value,
-}
-
-impl AspectConfig {
-
- pub fn new(init: Value) -> AspectConfig {
- debug!("Trying to parse AspectConfig from: {:?}", init);
- let parallel = AspectConfig::is_parallel(&init);
- let muthooks = AspectConfig::allows_mutable_hooks(&init);
- AspectConfig {
- config: init,
- mutable_hooks: muthooks,
- parallel: parallel,
- }
- }
-
- fn is_parallel(init: &Value) -> bool {
- match *init {
- Value::Table(ref t) =>
- t.get("parallel")
- .map_or(false, |value| {
- match *value {
- Value::Boolean(b) => b,
- _ => false,
- }
- }),
- _ => false,
- }
- }
-
- fn allows_mutable_hooks(init: &Value) -> bool {
- match *init {
- Value::Table(ref t) =>
- t.get("mutable_hooks")
- .map_or(false, |value| {
- match *value {
- Value::Boolean(b) => b,
- _ => false,
- }
- }),
- _ => false,
- }
- }
-
- pub fn allow_mutable_hooks(&self) -> bool {
- self.mutable_hooks
- }
-
- /// Get the aspect configuration for an aspect.
- ///
- /// Pass the store configuration object, this searches in `[aspects][<aspect_name>]`.
- ///
- /// Returns `None` if one of the keys in the chain is not available
- pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
- debug!("Get aspect configuration for {:?} from {:?}", a_name, v);
- let res = match *v {
- Some(Value::Table(ref tabl)) => {
- match tabl.get("aspects") {
- Some(&Value::Table(ref tabl)) => {
- tabl.get(&a_name[..]).map(|asp| AspectConfig::new(asp.clone()))
- },
-
- _ => None,
- }
- },
- _ => None,
- };
- debug!("Found aspect configuration for {:?}: {:?}", a_name, res);
- res
- }
-
-}
-
-fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
- use itertools::Itertools;
- let mut v = vec![];
-
- match *value {
- Some(Value::Table(ref t)) => {
- match t.get(config_name) {
- Some(&Value::Array(ref a)) => {
- for elem in a {
- match *elem {
- Value::String(ref s) => v.push(s.clone()),
- _ => warn!("Non-String in configuration, inside '{}'", config_name),
- }
- }
- },
- _ => warn!("'{}' configuration key should contain Array, does not", config_name),
- };
- },
- None => warn!("No store configuration, cannot get '{}'", config_name),
- _ => warn!("Configuration is not a table"),
- }
-
- v.into_iter().unique().collect()
-}
-
#[cfg(test)]
mod tests {
use toml::de::from_str as toml_from_str;
@@ -387,312 +100,5 @@ mod tests {
assert!(config_implicit_store_create_allowed(Some(config).as_ref()));
}
- #[test]
- fn test_get_store_unload_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- let names = get_store_unload_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_store_unload_aspect_names_empty() {
- let config = toml_from_str(r#"
- store-unload-hook-aspects = [ ]
- "#).unwrap();
- let names = get_store_unload_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_store_unload_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- store-unload-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_store_unload_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_pre_create_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_pre_create_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_pre_create_aspect_names_empty() {
- let config = toml_from_str(r#"
- pre-create-hook-aspects = [ ]
- "#).unwrap();
- let names = get_pre_create_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_pre_create_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- pre-create-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_pre_create_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_post_create_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_post_create_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_post_create_aspect_names_empty() {
- let config = toml_from_str(r#"
- post-create-hook-aspects = [ ]
- "#).unwrap();
- let names = get_post_create_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_post_create_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- post-create-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_post_create_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_pre_retrieve_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_pre_retrieve_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_pre_retrieve_aspect_names_empty() {
- let config = toml_from_str(r#"
- pre-retrieve-hook-aspects = [ ]
- "#).unwrap();
- let names = get_pre_retrieve_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_pre_retrieve_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- pre-retrieve-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_pre_retrieve_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_post_retrieve_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_post_retrieve_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_post_retrieve_aspect_names_empty() {
- let config = toml_from_str(r#"
- post-retrieve-hook-aspects = [ ]
- "#).unwrap();
- let names = get_post_retrieve_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_post_retrieve_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- post-retrieve-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_post_retrieve_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_pre_update_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_pre_update_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_pre_update_aspect_names_empty() {
- let config = toml_from_str(r#"
- pre-update-hook-aspects = [ ]
- "#).unwrap();
- let names = get_pre_update_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_pre_update_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- pre-update-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_pre_update_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_post_update_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_post_update_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_post_update_aspect_names_empty() {
- let config = toml_from_str(r#"
- post-update-hook-aspects = [ ]
- "#).unwrap();
- let names = get_post_update_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_post_update_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- post-update-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_post_update_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_pre_delete_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_pre_delete_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_pre_delete_aspect_names_empty() {
- let config = toml_from_str(r#"
- pre-delete-hook-aspects = [ ]
- "#).unwrap();
- let names = get_pre_delete_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_pre_delete_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- pre-delete-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_pre_delete_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_post_delete_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_post_delete_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_post_delete_aspect_names_empty() {
- let config = toml_from_str(r#"
- post-delete-hook-aspects = [ ]
- "#).unwrap();
- let names = get_post_delete_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_post_delete_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- post-delete-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_post_delete_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_pre_move_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_pre_move_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_pre_move_aspect_names_empty() {
- let config = toml_from_str(r#"
- pre-move-hook-aspects = [ ]
- "#).unwrap();
- let names = get_pre_move_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_pre_move_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- pre-move-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_pre_move_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_post_move_aspect_names_not_existent() {
- let config = toml_from_str("").unwrap();
- assert!(get_post_move_aspect_names(&Some(config)).is_empty());
- }
-
- #[test]
- fn test_get_post_move_aspect_names_empty() {
- let config = toml_from_str(r#"
- post-move-hook-aspects = [ ]
- "#).unwrap();
- let names = get_post_move_aspect_names(&Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_post_move_aspect_names_one_elem() {
- let config = toml_from_str(r#"
- post-move-hook-aspects = [ "example" ]
- "#).unwrap();
- let names = get_post_move_aspect_names(&Some(config));
- assert_eq!(1, names.len());
- assert_eq!("example", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_aspect_names_for_aspect_position_arbitrary_empty() {
- let config = toml_from_str(r#"
- test-key = [ ]
- "#).unwrap();
- let names = get_aspect_names_for_aspect_position("test-key", &Some(config));
- assert!(names.is_empty());
- }
-
- #[test]
- fn test_get_aspect_names_for_aspect_position_arbitrary_one() {
- let config = toml_from_str(r#"
- test-key = [ "test-value" ]
- "#).unwrap();
- let names = get_aspect_names_for_aspect_position("test-key", &Some(config));
- assert_eq!(1, names.len());
- assert_eq!("test-value", names.iter().next().unwrap());
- }
-
- #[test]
- fn test_get_aspect_names_for_aspect_position_arbitrary_duplicated() {
- let config = toml_from_str(r#"
- test-key = [ "test-value", "test-value" ]
- "#).unwrap();
- let names = get_aspect_names_for_aspect_position("test-key", &Some(config));
- assert_eq!(1, names.len());
- let mut iter = names.iter();
- assert_eq!("test-value", iter.next().unwrap());
- assert!(iter.next().is_none());
- }
-
}
diff --git a/libimagstore/src/error.rs b/libimagstore/src/error.rs
index 09ed092..3fe5a36 100644
--- a/libimagstore/src/error.rs
+++ b/libimagstore/src/error.rs
@@ -28,16 +28,6 @@ generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData,
ConfigTypeError => "Store configuration type error",
ConfigKeyMissingError => "Configuration Key missing",
- ConfigKeyUnloadAspectsError => "Config Key 'store-unload-hook-aspects' caused an error",
- ConfigKeyPreCreateAspectsError => "Config Key 'pre-create-hook-aspects' caused an error",
- ConfigKeyPostCreateAspectsError => "Config Key 'post-create-hook-aspects' caused an error",
- ConfigKeyPreRetrieveAspectsError => "Config Key 'pre-retrieve-hook-aspect' caused an error",
- ConfigKeyPostRetrieveAspectsError => "Config Key 'post-retrieve-hook-aspec' caused an error",
- ConfigKeyPreUpdateAspectsError => "Config Key 'pre-update-hook-aspects' caused an error",
- ConfigKeyPostUpdateAspectsError => "Config Key 'post-update-hook-aspects' caused an error",
- ConfigKeyPreDeleteAspectsError => "Config Key 'pre-delete-hook-aspects' caused an error",
- ConfigKeyPostDeleteAspectsError => "Config Key 'post-delete-hook-aspects' caused an error",
-
CreateStoreDirDenied => "Creating store directory implicitely denied",
FileError => "File Error",
IoError => "IO Error",
@@ -63,11 +53,6 @@ generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData,
HeaderPathTypeFailure => "Header has wrong type for path",
HeaderKeyNotFound => "Header Key not found",
HeaderTypeFailure => "Header type is wrong",
- HookRegisterError => "Hook register error",
- AspectNameNotFoundError => "Aspect name not found",
- HookExecutionError => "Hook execution error",
- PreHookExecuteError => "Pre-Hook execution error",
- PostHookExecuteError => "Post-Hook execution error",
StorePathLacksVersion => "The supplied store path has no version part",
GlobError => "glob() error",
EncodingError => "Encoding error",
diff --git a/libimagstore/src/hook/accessor.rs b/libimagstore/src/hook/accessor.rs
deleted file mode 100644
index 8bcca25..0000000
--- a/libimagstore/src/hook/accessor.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use std::fmt::Debug;
-
-use hook::result::HookResult;
-use store::FileLockEntry;
-use storeid::StoreId;
-
-pub trait StoreIdAccessor : Debug + Send {
- fn access(&self, &StoreId) -> HookResult<()>;
-}
-
-pub trait MutableHookDataAccessor : Debug + Send {
- fn access_mut(&self, &mut FileLockEntry) -> HookResult<()>;
-}
-
-pub trait NonMutableHookDataAccessor : Debug + Send {
- fn access(&self, &FileLockEntry) -> HookResult<()>;
-}
-
-#[derive(Debug)]
-pub enum HookDataAccessor<'a> {
- StoreIdAccess(&'a StoreIdAccessor),
- MutableAccess(&'a MutableHookDataAccessor),
- NonMutableAccess(&'a NonMutableHookDataAccessor),
-}
-
-pub trait HookDataAccessorProvider {
- fn accessor(&self) -> HookDataAccessor;
-}
-
-
diff --git a/libimagstore/src/hook/aspect.rs b/libimagstore/src/hook/aspect.rs
deleted file mode 100644
index 75cd595..0000000
--- a/libimagstore/src/hook/aspect.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use libimagerror::trace::trace_error;
-use libimagutil::iter::FoldResult;
-
-use store::FileLockEntry;
-use storeid::StoreId;
-use hook::Hook;
-use hook::result::HookResult;
-use hook::accessor::{StoreIdAccessor, MutableHookDataAccessor, NonMutableHookDataAccessor};
-use hook::accessor::HookDataAccessor as HDA;
-
-use hook::error::HookError as HE;
-use hook::error::HookErrorKind as HEK;
-use configuration::AspectConfig;
-
-#[derive(Debug)]
-pub struct Aspect {
- cfg: Option<AspectConfig>,
- name: String,
- hooks: Vec<Box<Hook>>,
-}
-
-impl Aspect {
-
- pub fn new(name: String, cfg: Option<AspectConfig>) -> Aspect {
- Aspect {
- cfg: cfg,
- name: name,
- hooks: vec![],
- }
- }
-
- pub fn name(&self) -> &String {
- &self.name
- }
-
- pub fn register_hook(&mut self, h: Box<Hook>) {
- self.hooks.push(h);
- }
-
-}
-
-impl StoreIdAccessor for Aspect {
- fn access(&self, id: &StoreId) -> HookResult<()> {
- let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
- if !accessors.iter().all(|a| {
- let x = is_match!(*a, HDA::StoreIdAccess(_));
- if !x {
- warn!("Denied execution of None-StoreId-Accessing Hook");
- debug!("Accessor: {:?}", a);
- debug!("in StoreIdAccess-Aspect execution: {:?}", self);
- }
- x
- }) {
- return Err(HE::new(HEK::AccessTypeViolation, None));
- }
-
- accessors.iter().fold_result(|accessor| {
- let res = match accessor {
- &HDA::StoreIdAccess(accessor) => accessor.access(id),
- _ => unreachable!(),
- };
- trace_hook_errors(res)
- })
- }
-}
-
-impl MutableHookDataAccessor for Aspect {
- fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
- debug!("Checking whether mutable hooks are allowed");
- debug!("-> config = {:?}", self.cfg);
-
- let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
-
- // TODO: Naiive implementation.
- // More sophisticated version would check whether there are _chunks_ of
- // NonMutableAccess accessors and execute these chunks in parallel. We do not have
- // performance concerns yet, so this is okay.
- accessors.iter().fold_result(|accessor| {
- let res = match accessor {
- &HDA::StoreIdAccess(ref accessor) => accessor.access(fle.get_location()),
- &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
- &HDA::MutableAccess(ref accessor) => {
- if !self.cfg.as_ref().map(|c| c.allow_mutable_hooks()).unwrap_or(false) {
- debug!("Apparently mutable hooks are not allowed... failing now.");
- return Err(HE::new(HEK::MutableHooksNotAllowed, None));
- }
-
- accessor.access_mut(fle)
- },
- };
- trace_hook_errors(res)
- })
- }
-}
-
-impl NonMutableHookDataAccessor for Aspect {
- fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
- let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
- if !accessors.iter().all(|a| {
- let x = is_match!(*a, HDA::NonMutableAccess(_));
- if !x {
- warn!("Denied execution of Non-Mutable-Accessing Hook");
- debug!("Accessor: {:?}", a);
- debug!("in StoreIdAccess-Aspect execution: {:?}", self);
- }
- x
- }) {
- return Err(HE::new(HEK::AccessTypeViolation, None));
- }
-
- accessors.iter().fold_result(|accessor| {
- let res = match accessor {
- &HDA::NonMutableAccess(accessor) => accessor.access(fle),
- _ => unreachable!(),
- };
- trace_hook_errors(res)
- })
- }
-}
-
-fn trace_hook_errors(res: HookResult<()>) -> HookResult<()> {
- res.or_else(|e| {
- if !e.is_aborting() {
- trace_error(&e);
- // ignore error if it is not aborting, as we printed it already
- Ok(())
- } else {
- Err(e)
- }
- })
-}
-
diff --git a/libimagstore/src/hook/error.rs b/libimagstore/src/hook/error.rs
deleted file mode 100644
index 0d890bf..0000000
--- a/libimagstore/src/hook/error.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use std::default::Default;
-
-generate_error_imports!();
-
-generate_custom_error_types!(HookError, HookErrorKind, CustomData,
- HookExecutionError => "Hook exec error",
- AccessTypeViolation => "Hook access type violation",
- MutableHooksNotAllowed => "Mutable Hooks are denied"
-);
-
-generate_result_helper!(HookError, HookErrorKind);
-
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
-pub struct CustomData {
- aborting: bool,
-}
-
-impl CustomData {
-
- pub fn aborting(mut self, b: bool) -> CustomData {
- self.aborting = b;
- self
- }
-
-}
-
-impl Default for CustomData {
-
- fn default() -> CustomData {
- CustomData {
- aborting: true
- }
- }
-
-}
-
-impl HookError {
-
- pub fn is_aborting(&self) -> bool {
- match self.custom_data {
- Some(b) => b.aborting,
- None => true
- }
- }
-
-}
diff --git a/libimagstore/src/hook/mod.rs b/libimagstore/src/hook/mod.rs
deleted file mode 100644
index 5c8e50f..0000000
--- a/libimagstore/src/hook/mod.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use std::fmt::Debug;
-
-use toml::Value;
-
-pub mod accessor;
-pub mod aspect;
-pub mod error;
-pub mod position;
-pub mod result;
-
-use hook::accessor::HookDataAccessorProvider;
-
-pub trait Hook : HookDataAccessorProvider + Debug + Send {
- fn name(&self) -> &'static str;
- fn set_config(&mut self, cfg: &Value);
-}
-
diff --git a/libimagstore/src/hook/position.rs b/libimagstore/src/hook/position.rs
deleted file mode 100644
index 8b9f926..0000000
--- a/libimagstore/src/hook/position.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#[derive(Debug, Clone)]
-pub enum HookPosition {
- StoreUnload,
-
- PreCreate,
- PostCreate,
- PreRetrieve,
- PostRetrieve,
- PreUpdate,
- PostUpdate,
- PreDelete,
- PostDelete,
-}
diff --git a/libimagstore/src/hook/result.rs b/libimagstore/src/hook/result.rs
deleted file mode 100644
index e25c722..0000000
--- a/libimagstore/src/hook/result.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 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 License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-use hook::error::HookError;
-
-pub type HookResult<T> = Result<T, HookError>;
diff --git a/libimagstore/src/lib.rs b/libimagstore/src/lib.rs
index 44fecc3..948865f 100644
--- a/libimagstore/src/lib.rs
+++ b/libimagstore/src/lib.rs
@@ -52,7 +52,6 @@ extern crate libimagutil;
pub mod storeid;
pub mod error;
-pub mod hook;
pub mod store;
mod configuration;
mod file_abstraction;
diff --git a/libimagstore/src/store.rs b/libimagstore/src/store.rs
index ef5725f..4d7e811 100644
--- a/libimagstore/src/store.rs
+++ b/libimagstore/src/store.rs
@@ -26,7 +26,6 @@ use std::sync::RwLock;
use std::io::Read;
use std::convert::From;
use std::convert::Into;
-use std::sync::Mutex;
use std::ops::Deref;
use std::ops::DerefMut;
use std::fmt::Formatter;
@@ -45,17 +44,8 @@ use storeid::{IntoStoreId, StoreId, StoreIdIterator};
use file_abstraction::FileAbstraction;
use toml_ext::*;
-use hook::aspect::Aspect;
-use hook::error::HookErrorKind;
-use hook::result::HookResult;
-use hook::accessor::{ MutableHookDataAccessor,
- StoreIdAccessor};
-use hook::position::HookPosition;
-use hook::Hook;
-
use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;
-use libimagutil::iter::FoldResult;
use libimagutil::debug_result::*;
use self::glob_store_iter::*;
@@ -195,23 +185,6 @@ pub struct Store {
///
configuration: Option<Value>,
- //
- // Registered hooks
- //
-
- store_unload_aspects : Arc<Mutex<Vec<Aspect>>>,
-
- pre_create_aspects : Arc<Mutex<Vec<Aspect>>>,
- post_create_aspects : Arc<Mutex<Vec<Aspect>>>,
- pre_retrieve_aspects : Arc<Mutex<Vec<Aspect>>>,
- post_retrieve_aspects : Arc<Mutex<Vec<Aspect>>>,
- pre_update_aspects : Arc<Mutex<Vec<Aspect>>>,
- post_update_aspects : Arc<Mutex<Vec<Aspect>>>,
- pre_delete_aspects : Arc<Mutex<Vec<Aspect>>>,
- post_delete_aspects : Arc<Mutex<Vec<Aspect>>>,
- pre_move_aspects : Arc<Mutex<Vec<Aspect>>>,
- post_move_aspects : Arc<Mutex<Vec<Aspect>>>,
-
///
/// Internal Path->File cache map
///
@@ -237,8 +210,6 @@ impl Store {
///
/// If the path exists and is a file, the operation is aborted as well, an error is returned.
///
- /// After that, the store hook aspects are created and registered in the store.
- ///
/// # Return values
///
/// - On success: Store object
@@ -273,88 +244,9 @@ impl Store {
return Err(SEK::StorePathExists.into_error());
}
- let store_unload_aspects = get_store_unload_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let pre_create_aspects = get_pre_create_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let post_create_aspects = get_post_create_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let pre_retrieve_aspects = get_pre_retrieve_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let post_retrieve_aspects = get_post_retrieve_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let pre_update_aspects = get_pre_update_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let post_update_aspects = get_post_update_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let pre_delete_aspects = get_pre_delete_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let post_delete_aspects = get_post_delete_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let pre_move_aspects = get_pre_move_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
- let post_move_aspects = get_post_move_aspect_names(&store_config)
- .into_iter().map(|n| {
- let cfg = AspectConfig::get_for(&store_config, n.clone());
- Aspect::new(n, cfg)
- }).collect();
-
let store = Store {
location: location.clone(),
configuration: store_config,
-
- store_unload_aspects : Arc::new(Mutex::new(store_unload_aspects)),
-
- pre_create_aspects : Arc::new(Mutex::new(pre_create_aspects)),
- post_create_aspects : Arc::new(Mutex::new(post_create_aspects)),
- pre_retrieve_aspects : Arc::new(Mutex::new(pre_retrieve_aspects)),
- post_retrieve_aspects : Arc::new(Mutex::new(post_retrieve_aspects)),
- pre_update_aspects : Arc::new(Mutex::new(pre_update_aspects)),
- post_update_aspects : Arc::new(Mutex::new(post_update_aspects)),
- pre_delete_aspects : Arc::new(Mutex::new(pre_delete_aspects)),
- post_delete_aspects : Arc::new(Mutex::new(post_delete_aspects)),
- pre_move_aspects : Arc::new(Mutex::new(pre_move_aspects)),
- post_move_aspects : Arc::new(Mutex::new(post_move_aspects)),
entries: Arc::new(RwLock::new(HashMap::new())),
};
@@ -429,32 +321,17 @@ impl Store {
/// Creates the Entry at the given location (inside the entry)
///
- /// # Executed Hooks
- ///
- /// - Pre create aspects
- /// - post create aspects
- ///
/// # Return value
///
/// On success: FileLockEntry
///
/// On error:
/// - Errors StoreId::into_storeid() might return
- /// - CreateCallError(HookExecutionError(PreHookExecuteError(_)))
- /// of the first failing pre hook.
- /// - CreateCallError(HookExecutionError(PostHookExecuteError(_)))
- /// of the first failing post hook.
/// - CreateCallError(LockPoisoned()) if the internal lock is poisened.
/// - CreateCallError(EntryAlreadyExists()) if the entry exists already.
///
pub fn create<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
let id = try!(id.into_storeid()).with_base(self.path().clone());
- if let Err(e) = self.execute_hooks_for_id(self.pre_create_aspects.clone(), &id) {
- return Err(e)
- .map_err_into(SEK::PreHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::CreateCallError)
- }
{
let mut hsmap = match self.entries.write() {
@@ -472,12 +349,7 @@ impl Store {
});
}
- let mut fle = FileLockEntry::new(self, Entry::new(id));
- self.execute_hooks_for_mut_file(self.post_create_aspects.clone(), &mut fle)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::CreateCallError)
- .map(|_| fle)
+ Ok(FileLockEntry::new(self, Entry::new(id)))
}
/// Borrow a given Entry. When the `FileLockEntry` is either `update`d or
@@ -486,32 +358,16 @@ impl Store {
/// Implicitely creates a entry in the store if there is no entry with the id `id`. For a
/// non-implicitely-create look at `Store::get`.
///
- /// # Executed Hooks
- ///
- /// - Pre retrieve aspects
- /// - post retrieve aspects
- ///
/// # Return value
///
/// On success: FileLockEntry
///
/// On error:
/// - Errors StoreId::into_storeid() might return
- /// - RetrieveCallError(HookExecutionError(PreHookExecuteError(_)))
- /// of the first failing pre hook.
- /// - RetrieveCallError(HookExecutionError(PostHookExecuteError(_)))
- /// of the first failing post hook.
/// - RetrieveCallError(LockPoisoned()) if the internal lock is poisened.
///
pub fn retrieve<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
let id = try!(id.into_storeid()).with_base(self.path().clone());
- if let Err(e) = self.execute_hooks_for_id(self.pre_retrieve_aspects.clone(), &id) {
- return Err(e)
- .map_err_into(SEK::PreHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::RetrieveCallError)
- }
-
let entry = try!({
self.entries
.write()
@@ -526,21 +382,11 @@ impl Store {
.map_err_into(SEK::RetrieveCallError)
});
- let mut fle = FileLockEntry::new(self, entry);
- self.execute_hooks_for_mut_file(self.post_retrieve_aspects.clone(), &mut fle)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::RetrieveCallError)
- .and(Ok(fle))
+ Ok(FileLockEntry::new(self, entry))
}
/// Get an entry from the store if it exists.
///
- /// # Executed Hooks
- ///
- /// - Pre get aspects
- /// - post get aspects
- ///
/// # Return value
///
/// On success: Some(FileLockEntry) or None
@@ -617,32 +463,17 @@ impl Store {
/// This method assumes that entry is dropped _right after_ the call, hence
/// it is not public.
///
- /// # Executed Hooks
- ///
- /// - Pre update aspects
- /// - post update aspects
- ///
/// # Return value
///
/// On success: Entry
///
/// On error:
- /// - UpdateCallError(HookExecutionError(PreHookExecuteError(_)))
- /// of the first failing pre hook.
- /// - UpdateCallError(HookExecutionError(PostHookExecuteError(_)))
- /// of the first failing post hook.
/// - UpdateCallError(LockPoisoned()) if the internal write lock cannot be aquierd.
/// - IdNotFound() if the entry was not found in the stor
/// - Errors Entry::verify() might return
/// - Errors StoreEntry::write_entry() might return
///
- fn _update<'a>(&'a self, mut entry: &mut FileLockEntry<'a>, modify_presence: bool) -> Result<()> {
- let _ = try!(self.execute_hooks_for_mut_file(self.pre_update_aspects.clone(), &mut entry)
- .map_err_into(SEK::PreHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::UpdateCallError)
- );
-
+ fn _update<'a>(&'a self, entry: &mut FileLockEntry<'a>, modify_presence: bool) -> Result<()> {
let mut hsmap = match self.entries.write() {
Err(_) => return Err(SE::new(SEK::LockPoisoned, None)),
Ok(e) => e,
@@ -661,21 +492,12 @@ impl Store {
se.status = StoreEntryStatus::Present;
}
- self.execute_hooks_for_mut_file(self.post_update_aspects.clone(), &mut entry)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::UpdateCallError)
+ Ok(())
}
/// Retrieve a copy of a given entry, this cannot be used to mutate
/// the one on disk
///
- /// TODO: Create Hooks for retrieving a copy
- ///
- /// # Executed Hooks
- ///
- /// - (none yet)
- ///
/// # Return value
///
/// On success: Entry
@@ -705,32 +527,17 @@ impl Store {
/// Delete an entry
///
- /// # Executed Hooks
- ///
- /// - Pre delete aspects, if the id can be used
- /// - Post delete aspects, if the operation succeeded
- ///
/// # Return value
///
/// On success: ()
///
/// On error:
- /// - DeleteCallError(HookExecutionError(PreHookExecuteError(_)))
- /// of the first failing pre hook.
- /// - DeleteCallError(HookExecutionError(PostHookExecuteError(_)))
- /// of the first failing post hook.
/// - DeleteCallError(LockPoisoned()) if the internal write lock cannot be aquierd.
/// - DeleteCallError(FileNotFound()) if the StoreId refers to a non-existing entry.
/// - DeleteCallError(FileError()) if the internals failed to remove the file.
///
pub fn delete<S: IntoStoreId>(&self, id: S) -> Result<()> {
let id = try!(id.into_storeid()).with_base(self.path().clone());
- if let Err(e) = self.execute_hooks_for_id(self.pre_delete_aspects.clone(), &id) {
- return Err(e)
- .map_err_into(SEK::PreHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::DeleteCallError)
- }
{
let mut entries = match self.entries.write() {
@@ -758,25 +565,16 @@ impl Store {
}
}
- self.execute_hooks_for_id(self.post_delete_aspects.clone(), &id)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::DeleteCallError)
+ Ok(())
}
/// Save a copy of the Entry in another place
- /// Executes the post_move_aspects for the new id
- ///
- /// TODO: Introduce new aspect for `save_to()`.
pub fn save_to(&self, entry: &FileLockEntry, new_id: StoreId) -> Result<()> {
self.save_to_other_location(entry, new_id, false)
}
/// Save an Entry in another place
/// Removes the original entry
- /// Executes the post_move_aspects for the new id
- ///
- /// TODO: Introduce new aspect for `save_as()`.
pub fn save_as(&self, entry: FileLockEntry, new_id: StoreId) -> Result<()> {
self.save_to_other_location(&entry, new_id, true)
}
@@ -809,9 +607,6 @@ impl Store {
}
})
.map_err_into(SEK::FileError)
- .and_then(|_| self.execute_hooks_for_id(self.post_move_aspects.clone(), &new_id)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError))
.map_err_into(SEK::MoveCallError)
}
@@ -826,14 +621,11 @@ impl Store {
///
/// This function returns an error in certain cases:
///
- /// * If pre-move-hooks error (if they return an error which indicates that the action should be
- /// aborted)
/// * If the about-to-be-moved entry is borrowed
/// * If the lock on the internal data structure cannot be aquired
/// * If the new path already exists
/// * If the about-to-be-moved entry does not exist
/// * If the FS-operation failed
- /// * If the post-move-hooks error (though the operation has succeeded then).
///
/// # Warnings
///
@@ -855,13 +647,6 @@ impl Store {
let new_id = new_id.with_base(self.path().clone());
let old_id = old_id.with_base(self.path().clone());
- if let Err(e) = self.execute_hooks_for_id(self.pre_move_aspects.clone(), &old_id) {
- return Err(e)
- .map_err_into(SEK::PreHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::MoveByIdCallError)
- }
-
{
let mut hsmap = match self.entries.write() {
Err(_) => return Err(SE::new(SEK::LockPoisoned, None)),
@@ -900,10 +685,7 @@ impl Store {
}
- self.execute_hooks_for_id(self.pre_move_aspects.clone(), &new_id)
- .map_err_into(SEK::PostHookExecuteError)
- .map_err_into(SEK::HookExecutionError)
- .map_err_into(SEK::MoveByIdCallError)
+ Ok(())
}
/// Gets the path where this store is on the disk
@@ -911,127 +693,6 @@ impl Store {
&self.location
}
- /// Register a hook in the store.
- ///
- /// A hook is registered by a position (when should the hook be executed) and an aspect name.
- /// The aspect name must be in the configuration file, so the configuration for the hook can be
- /// passed to the `Hook` object.
- ///
- /// # Available Hook positions
- ///
- /// The hook positions are described in the type description of `HookPosition`.
- ///
- /// # Aspect names
- ///
- /// Aspect names are arbitrary, though sane things like "debug" or "vcs" are encouraged.
- /// Refer to the documentation for more information.
- ///
- pub fn register_hook(&mut self,
- position: HookPosition,
- aspect_name: &str,
- mut h: Box<Hook>)
- -> Result<()>
- {
- debug!("Registering hook: {:?}", h);
- debug!(" in position: {:?}", position);
- debug!(" with aspect: {:?}", aspect_name);
-
- let guard = match position {
- HookPosition::StoreUnload => self.store_unload_aspects.clone(),
-
- HookPosition::PreCreate => self.pre_create_aspects.clone(),
- HookPosition::PostCreate => self.post_create_aspects.clone(),
- HookPosition::PreRetrieve => self.pre_retrieve_aspects.clone(),
- HookPosition::PostRetrieve => self.post_retrieve_aspects.clone(),
- HookPosition::PreUpdate => self.pre_update_aspects.clone(),
- HookPosition::PostUpdate => self.post_update_aspects.clone(),
- HookPosition::PreDelete => self.pre_delete_aspects.clone(),
- HookPosition::PostDelete => self.post_delete_aspects.clone(),
- };
-
- let mut guard = match guard.deref().lock().map_err(|_| SE::new(SEK::LockError, None)) {
- Err(e) => return Err(SEK::HookRegisterError.into_error_with_cause(Box::new(e))),
- Ok(g) => g,
- };
-
- for mut aspect in guard.deref_mut() {
- if aspect.name().clone() == aspect_name.clone() {
- debug!("Trying to find configuration for hook: {:?}", h);
- self.get_config_for_hook(h.name()).map(|config| h.set_config(config));
- debug!("Trying to register hook in aspect: {:?} <- {:?}", aspect, h);
- aspect.register_hook(h);
- return Ok(());
- }
- }
-
- let annfe = SEK::AspectNameNotFoundError.into_error();
- Err(SEK::HookRegisterError.into_error_with_cause(Box::new(annfe)))
- }
-
- /// Get the configuration for a hook by the name of the hook, from the configuration file.
- fn get_config_for_hook(&self, name: &str) -> Option<&Value> {
- match self.configuration {
- Some(Value::Table(ref tabl)) => {
- debug!("Trying to head 'hooks' section from {:?}", tabl);
- tabl.get("hooks")
- .map(|hook_section| {
- debug!("Found hook section: {:?}", hook_section);
- debug!("Reading section key: {:?}", name);
- match *hook_section {
- Value::Table(ref tabl) => tabl.get(name),
- _ => None
- }
- })
- .unwrap_or(None)
- },
- _ => None,
- }
- }
-
- /// Execute all hooks from all aspects for a Store Id object.
- ///
- /// # Return value
- ///
- /// - () on success
- /// - Error on the first failing hook.
- ///
- fn execute_hooks_for_id(&self,
- aspects: Arc<Mutex<Vec<Aspect>>>,
- id: &StoreId)
- -> HookResult<()>
- {
- match aspects.lock() {
- Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
- Ok(g) => g
- }.iter().fold_result(|aspect| {
- debug!("[Aspect][exec]: {:?}", aspect);
- (aspect as &StoreIdAccessor).access(id)
- }).map_err(Box::new)
- .map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
- }
-
- /// Execute all hooks from all aspects for a mutable `FileLockEntry` object.
- ///
- /// # Return value
- ///
- /// - () on success
- /// - Error on the first failing hook.
- ///
- fn execute_hooks_for_mut_file(&self,
- aspects: Arc<Mutex<Vec<Aspect>>>,
- fle: &mut FileLockEntry)
- -> HookResult<()>
- {
- match aspects.lock() {
- Err(_) => return Err(HookErrorKind::HookExecutionError.into()),
- Ok(g) => g
- }.iter().fold_result(|aspect| {
- debug!("[Aspect][exec]: {:?}", aspect);
- aspect.access_mut(fle)
- }).map_err(Box::new)
- .map_err(|e| HookErrorKind::HookExecutionError.into_error_with_cause(e))
- }
-
}
impl Debug for Store {
@@ -1042,14 +703,6 @@ impl Debug for Store {
try!(write!(fmt, "\n"));
try!(write!(fmt, " - location : {:?}\n", self.location));
try!(write!(fmt, " - configuration : {:?}\n", self.configuration));
- try!(write!(fmt, " - pre_create_aspects : {:?}\n", self.pre_create_aspects ));
- try!(write!(fmt, " - post_create_aspects : {:?}\n", self.post_create_aspects ));
- try!(write!(fmt, " - pre_retrieve_aspects : {:?}\n", self.pre_retrieve_aspects ));
- try!(write!(fmt, " - post_retrieve_aspects : {:?}\n", self.post_retrieve_aspects ));
- try!(write!(fmt, " - pre_update_aspects : {:?}\n", self.pre_update_aspects ));
- try!(write!(fmt, " - post_update_aspects : {:?}\n", self.post_update_aspects ));
- try!(write!(fmt, " - pre_delete_aspects : {:?}\n", self.pre_delete_aspects ));
- try!(write!(fmt, " - post_delete_aspects : {:?}\n", self.post_delete_aspects ));
try!(write!(fmt, "\n"));
try!(write!(fmt, "Entries:\n"));
try!(write!(fmt, "{:?}", self.entries));
@@ -1065,23 +718,8 @@ impl Drop for Store {
/// Unlock all files on drop
//
/// TODO: Unlock them
- /// TODO: Resolve this dirty hack with the StoreId for the Store drop hooks.
///
fn drop(&mut self) {
- match StoreId::new(Some(self.location.clone()), PathBuf::from(".")) {
- Err(e) => {
- trace_error(&e);
- warn!("Cannot construct StoreId for Store to execute hooks!");
- warn!("Will close Store without executing hooks!");
- },
- Ok(store_id) => {
- if let Err(e) = self.execute_hooks_for_id(self.store_unload_aspects.clone(), &store_id) {
- debug!("Store-load hooks execution failed. Cannot create store object.");
- warn!("Store Unload Hook error: {:?}", e);
- }
- },
- };
-
debug!("Dropping store");
}
@@ -1541,19 +1179,6 @@ mod store_tests {
assert_eq!(store.location, PathBuf::from("/"));
assert!(store.entries.read().unwrap().is_empty());
-
- assert!(store.store_unload_aspects.lock().unwrap().is_empty());
-
- assert!(store.pre_create_aspects.lock().unwrap().is_empty());
- assert!(store.post_create_aspects.lock().unwrap().is_empty());
- assert!(store.pre_retrieve_aspects.lock().unwrap().is_empty());
- assert!(store.post_retrieve_aspects.lock().unwrap().is_empty());
- assert!(store.pre_update_aspects.lock().unwrap().is_empty());
- assert!(store.post_update_aspects.lock().unwrap().is_empty());
- assert!(store.pre_delete_aspects.lock().unwrap().is_empty());
- assert!(store.post_delete_aspects.lock().unwrap().is_empty());
- assert!(store.pre_move_aspects.lock().unwrap().is_empty());
- assert!(store.post_move_aspects.lock().unwrap().is_empty());
}
#[test]
@@ -1775,476 +1400,3 @@ mod store_tests {
}
-#[cfg(test)]
-mod store_hook_tests {
-
- mod test_hook {
- use hook::Hook;
- use hook::accessor::HookDataAccessor;
- use hook::accessor::HookDataAccessorProvider;
- use hook::position::HookPosition;
-
- use self::accessor::TestHookAccessor as DHA;
-
- use toml::Value;
-
- #[derive(Debug)]
- pub struct TestHook {
- position: HookPosition,
- accessor: DHA,
- }
-
- impl TestHook {
-
- pub fn new(pos: HookPosition, succeed: bool, error_aborting: bool) -> TestHook {
- TestHook { position: pos.clone(), accessor: DHA::new(pos, succeed, error_aborting) }
- }
-
- }
-
- impl Hook for TestHook {
- fn name(&self) -> &'static str { "testhook_succeeding" }
- fn set_config(&mut self, _: &Value) { }
- }
-
- impl HookDataAccessorProvider for TestHook {
-
- fn accessor(&self) -> HookDataAccessor {
- use hook::position::HookPosition as HP;
- use hook::accessor::HookDataAccessor as HDA;
-
- match self.position {
- HP::StoreUnload |
- HP::PreCreate |
- HP::PreRetrieve |
- HP::PreDelete |
- HP::PostDelete => HDA::StoreIdAccess(&self.accessor),
- HP::PostCreate |
- HP::PostRetrieve |
- HP::PreUpdate |
- HP::PostUpdate => HDA::MutableAccess(&self.accessor),
- }
- }
-
- }
-
- pub mod accessor {
- use hook::result::HookResult;
- use hook::accessor::MutableHookDataAccessor;
- use hook::accessor::NonMutableHookDataAccessor;
- use hook::accessor::StoreIdAccessor;
- use hook::position::HookPosition;
- use store::FileLockEntry;
- use storeid::StoreId;
- use hook::error::HookErrorKind as HEK;
- use hook::error::CustomData;
- use libimagerror::into::IntoError;
-
- #[derive(Debug)]
- pub struct TestHookAccessor {
- pos: HookPosition,
- succeed: bool,
- error_aborting: bool
- }
-
- impl TestHookAccessor {
-
- pub fn new(position: HookPosition, succeed: bool, error_aborting: bool)
- -> TestHookAccessor
- {
- TestHookAccessor {
- pos: position,
- succeed: succeed,
- error_aborting: error_aborting,
- }
- }
-
- }
-
- fn get_result(succeed: bool, abort: bool) -> HookResult<()> {
- println!("Generting result: succeed = {}, abort = {}", succeed, abort);
- if succeed {
- println!("Generating result: Ok(())");
- Ok(())
- } else {
- if abort {
- println!("Generating result: Err(_), aborting");
- Err(HEK::HookExecutionError.into_error())
- } else {
- println!("Generating result: Err(_), not aborting");
- let custom = CustomData::default().aborting(false);
- Err(HEK::HookExecutionError.into_error().with_custom_data(custom))
- }
- }
- }
-
- impl StoreIdAccessor for TestHookAccessor {
-
- fn access(&self, _: &StoreId) -> HookResult<()> {
- get_result(self.succeed, self.error_aborting)
- }
-
- }
-
- impl MutableHookDataAccessor for TestHookAccessor {
-
- fn access_mut(&self, _: &mut FileLockEntry) -> HookResult<()> {
- get_result(self.succeed, self.error_aborting)
- }
-
- }
-
- impl NonMutableHookDataAccessor for TestHookAccessor {
-
- fn access(&self, _: &FileLockEntry) -> HookResult<()> {
- get_result(self.succeed, self.error_aborting)
- }
-
- }
-
- }
-
- }
-
- use std::path::PathBuf;
-
- use hook::position::HookPosition as HP;
- use storeid::StoreId;
- use store::Store;
-
- use self::test_hook::TestHook;
-
- fn get_store_with_config() -> Store {
- use toml::de::from_str;
-
- let cfg : ::toml::Value = from_str(mini_config()).unwrap();
- println!("Config parsed: {:?}", cfg);
- Store::new(PathBuf::from("/"), Some(cfg.get("store").cloned().unwrap())).unwrap()
- }
-
- fn mini_config() -> &'static str {
- r#"
-[store]
-store-unload-hook-aspects = [ "test" ]
-pre-create-hook-aspects = [ "test" ]
-post-create-hook-aspects = [ "test" ]
-pre-move-hook-aspects = [ "test" ]
-post-move-hook-aspects = [ "test" ]
-pre-retrieve-hook-aspects = [ "test" ]
-post-retrieve-hook-aspects = [ "test" ]
-pre-update-hook-aspects = [ "test" ]
-post-update-hook-aspects = [ "test" ]
-pre-delete-hook-aspects = [ "test" ]
-post-delete-hook-aspects = [ "test" ]
-
-[store.aspects.test]
-parallel = false
-mutable_hooks = true
-
-[store.hooks.testhook_succeeding]
-aspect = "test"
- "#
- }
-
- fn test_hook_execution(hook_positions: &[HP], storeid_name: &str) {
- let mut store = get_store_with_config();
-
- println!("Registering hooks...");
- for pos in hook_positions {
- let hook = TestHook::new(pos.clone(), true, false);
- println!("\tRegistering: {:?}", pos);
- assert!(store.register_hook(pos.clone(), "test", Box::new(hook))
- .map_err(|e| println!("{:?}", e))
- .is_ok()
- );
- }
- println!("... done.");
-
- let pb = StoreId::new_baseless(PathBuf::from(storeid_name)).unwrap();
- let pb_moved = StoreId::new_baseless(PathBuf::from(format!("{}-moved", storeid_name))).unwrap();
-
- println!("Creating {:?}", pb);
- assert!(store.create(pb.clone()).is_ok());
-
- {
- println!("Getting {:?} -> Some?", pb);
- assert!(match store.get(pb.clone()) {
- Ok(Some(_)) => true,
- _ => false,
- });
- }
-
- {
- println!("Getting {:?} -> None?", pb_moved);
- assert!(match store.get(pb_moved.clone()) {
- Ok(None) => true,
- _ => false,
- });
- }
-
- {
- println!("Moving {:?} -> {:?}", pb, pb_moved);
- assert!(store.move_by_id(pb.clone(), pb_moved.clone()).map_err(|e| println!("ERROR MOVING: {:?}", e)).is_ok());
- }
-
- {
- println!("Getting {:?} -> None", pb);
- assert!(match store.get(pb.clone()) {
- Ok(None) => true,
- _ => false,
- });
- }
-
- {
- println!("Getting {:?} -> Some", pb_moved);
- assert!(match store.get(pb_moved.clone()) {
- Ok(Some(_)) => true,
- _ => false,
- });
- }
-
- {
- println!("Getting {:?} -> Some -> updating", pb_moved);
- assert!(match store.get(pb_moved.clone()).map_err(|e| println!("ERROR GETTING: {:?}", e)) {
- Ok(Some(mut fle)) => store.update(&mut fle)
- .map_err(|e| println!("ERROR UPDATING: {:?}", e)).is_ok(),
- _ => false,
- });
- }
-
- println!("Deleting {:?}", pb_moved);
- assert!(store.delete(pb_moved).is_ok());
- }
-
- #[test]
- fn test_storeunload() {
- test_hook_execution(&[HP::StoreUnload], "test_storeunload");
- }
-
- #[test]
- fn test_precreate() {
- test_hook_execution(&[HP::PreCreate], "test_precreate");
- }
-
- #[test]
- fn test_postcreate() {
- test_hook_execution(&[HP::PostCreate], "test_postcreate");
- }
-
- #[test]
- fn test_preretrieve() {
- test_hook_execution(&[HP::PreRetrieve], "test_preretrieve");
- }
-
- #[test]
- fn test_postretrieve() {
- test_hook_execution(&[HP::PostRetrieve], "test_postretrieve");
- }
-
- #[test]
- fn test_preupdate() {
- test_hook_execution(&[HP::PreUpdate], "test_preupdate");
- }
-
- #[test]
- fn test_postupdate() {
- test_hook_execution(&[HP::PostUpdate], "test_postupdate");
- }
-
- #[test]
- fn test_predelete() {
- test_hook_execution(&[HP::PreDelete], "test_predelete");
- }
-
- #[test]
- fn test_postdelete() {
- test_hook_execution(&[HP::PostDelete], "test_postdelete");
- }
-
- #[test]
- fn test_multiple_same_position() {
- let positions = [ HP::StoreUnload, HP::PreCreate, HP::PostCreate, HP::PreRetrieve,
- HP::PostRetrieve, HP::PreUpdate, HP::PostUpdate, HP::PreDelete, HP::PostDelete ];
-
- for position in positions.iter() {
- for n in 2..10 {
- let mut v = Vec::with_capacity(n);
- for _ in 0..n { v.push(position.clone()); }
-
- test_hook_execution(&v, "test_multiple_same_position");
- }
- }
- }
-
-
- fn get_store_with_aborting_hook_at_pos(pos: HP) -> Store {
- let mut store = get_store_with_config();
- let hook = TestHook::new(pos.clone(), false, true);
-
- assert!(store.register_hook(pos, "test", Box::new(hook)).map_err(|e| println!("{:?}", e)).is_ok());
- store
- }
-
- #[test]
- fn test_pre_create_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_create_error")).unwrap();
- let store = get_store_with_aborting_hook_at_pos(HP::PreCreate);
- assert!(store.create(storeid).is_err());
- }
-
- #[test]
- fn test_pre_retrieve_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_retrieve_error")).unwrap();
- let store = get_store_with_aborting_hook_at_pos(HP::PreRetrieve);
- assert!(store.retrieve(storeid).is_err());
- }
-
- #[test]
- fn test_pre_delete_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_delete_error")).unwrap();
- let store = get_store_with_aborting_hook_at_pos(HP::PreDelete);
- assert!(store.delete(storeid).is_err());
- }
-
- #[test]
- fn test_pre_update_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_update_error")).unwrap();
- let store = get_store_with_aborting_hook_at_pos(HP::PreUpdate);
- let mut fle = store.create(storeid).unwrap();
-
- assert!(store.update(&mut fle).is_err());
- }
-
- #[test]
- fn test_post_create_error() {
- let store = get_store_with_aborting_hook_at_pos(HP::PostCreate);
- let pb = StoreId::new_baseless(PathBuf::from("test_post_create_error")).unwrap();
-
- assert!(store.create(pb.clone()).is_err());
-
- // But the entry exists, as the hook fails post-create
- assert!(store.entries.read().unwrap().get(&pb.with_base(store.path().clone())).is_some());
- }
-
- #[test]
- fn test_post_retrieve_error() {
- let store = get_store_with_aborting_hook_at_pos(HP::PostRetrieve);
- let pb = StoreId::new_baseless(PathBuf::from("test_post_retrieve_error")).unwrap();
-
- assert!(store.retrieve(pb.clone()).is_err());
-
- // But the entry exists, as the hook fails post-retrieve
- assert!(store.entries.read().unwrap().get(&pb.with_base(store.path().clone())).is_some());
- }
-
- #[test]
- fn test_post_delete_error() {
- let store = get_store_with_aborting_hook_at_pos(HP::PostDelete);
- let pb = StoreId::new_baseless(PathBuf::from("test_post_delete_error")).unwrap();
-
- assert!(store.create(pb.clone()).is_ok());
- let pb = pb.with_base(store.path().clone());
- assert!(store.entries.read().unwrap().get(&pb).is_some());
-
- assert!(store.delete(pb.clone()).is_err());
- // But the entry is removed, as we fail post-delete
- assert!(store.entries.read().unwrap().get(&pb).is_none());
- }
-
- #[test]
- fn test_post_update_error() {
- let store = get_store_with_aborting_hook_at_pos(HP::PostUpdate);
- let pb = StoreId::new_baseless(PathBuf::from("test_post_update_error")).unwrap();
- let mut fle = store.create(pb.clone()).unwrap();
- let pb = pb.with_base(store.path().clone());
-
- assert!(store.entries.read().unwrap().get(&pb).is_some());
- assert!(store.update(&mut fle).is_err());
- }
-
- fn get_store_with_allowed_error_hook_at_pos(pos: HP) -> Store {
- let mut store = get_store_with_config();
- let hook = TestHook::new(pos.clone(), false, false);
-
- assert!(store.register_hook(pos, "test", Box::new(hook)).map_err(|e| println!("{:?}", e)).is_ok());
- store
- }
-
- #[test]
- fn test_pre_create_allowed_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_create_allowed_error")).unwrap();
- let store = get_store_with_allowed_error_hook_at_pos(HP::PreCreate);
- assert!(store.create(storeid).is_ok());
- }
-
- #[test]
- fn test_pre_retrieve_allowed_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_retrieve_allowed_error")).unwrap();
- let store = get_store_with_allowed_error_hook_at_pos(HP::PreRetrieve);
- assert!(store.retrieve(storeid).is_ok());
- }
-
- #[test]
- fn test_pre_delete_allowed_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_delete_allowed_error")).unwrap();
- let store = get_store_with_allowed_error_hook_at_pos(HP::PreDelete);
- assert!(store.retrieve(storeid.clone()).is_ok());
- assert!(store.delete(storeid).map_err(|e| println!("{:?}", e)).is_ok());
- }
-
- #[test]
- fn test_pre_update_allowed_error() {
- let storeid = StoreId::new_baseless(PathBuf::from("test_pre_update_allowed_error")).unwrap();
- let store = get_store_with_allowed_error_hook_at_pos(HP::PreUpdate);
- let mut fle = store.create(storeid).unwrap();
-
- assert!(store.update(&mut fle).is_ok());
- }
-
- #[test]
- fn test_post_create_allowed_error() {
- let store = get_store_with_allowed_error_hook_at_pos(HP::PostCreate);
- let pb = StoreId::new_baseless(PathBuf::from("test_pre_create_allowed_error")).unwrap();
-
- assert!(store.create(pb.clone()).is_ok());
-
- // But the entry exists, as the hook fails post-create
- assert!(store.entries.read().unwrap().get(&pb.with_base(store.path().clone())).is_some());
- }
-
- #[test]
- fn test_post_retrieve_allowed_error() {
- let store = get_store_with_allowed_error_hook_at_pos(HP::PostRetrieve);
- let pb = StoreId::new_baseless(PathBuf::from("test_pre_retrieve_allowed_error")).unwrap();
-
- assert!(store.retrieve(pb.clone()).is_ok());
-
- // But the entry exists, as the hook fails post-retrieve
- assert!(store.entries.read().unwrap().get(&pb.with_base(store.path().clone())).is_some());
- }
-
- #[test]
- fn test_post_delete_allowed_error() {
- let store = get_store_with_allowed_error_hook_at_pos(HP::PostDelete);
- let pb = StoreId::new_baseless(PathBuf::from("test_post_delete_allowed_error")).unwrap();
-
- assert!(store.create(pb.clone()).is_ok());
- let pb = pb.with_base(store.path().clone());
- assert!(store.entries.read().unwrap().get(&pb).is_some());
-
- assert!(store.delete(pb.clone()).is_ok());
- // But the entry is removed, as we fail post-delete
- assert!(store.entries.read().unwrap().get(&pb).is_none());
- }
-
- #[test]
- fn test_post_update_allowed_error() {
- let store = get_store_with_allowed_error_hook_at_pos(HP::PostUpdate);
- let pb = StoreId::new_baseless(PathBuf::from("test_pre_update_allowed_error")).unwrap();
- let mut fle = store.create(pb.clone()).unwrap();
- let pb = pb.with_base(store.path().clone());
-
- assert!(store.entries.read().unwrap().get(&pb).is_some());
- assert!(store.update(&mut fle).is_ok());
- }
-}