diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2017-01-22 14:57:23 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2017-01-22 15:44:21 +0100 |
commit | 34cd5d9c875bebdfaacc6463752bf9b46a9ebb39 (patch) | |
tree | dc663b87b2544a6a3f7d6e73312b25d2235a3d0a | |
parent | 54deef3dde276c7112dae73fc0e421e7bceea2be (diff) | |
download | imag-34cd5d9c875bebdfaacc6463752bf9b46a9ebb39.zip imag-34cd5d9c875bebdfaacc6463752bf9b46a9ebb39.tar.gz |
Add Store::new() function interface
-rw-r--r-- | libimagruby/Cargo.toml | 5 | ||||
-rw-r--r-- | libimagruby/src/lib.rs | 1 | ||||
-rw-r--r-- | libimagruby/src/store.rs | 137 | ||||
-rw-r--r-- | libimagruby/test/test_ruby.rb | 1 |
4 files changed, 143 insertions, 1 deletions
diff --git a/libimagruby/Cargo.toml b/libimagruby/Cargo.toml index 664a87c..2d98a08 100644 --- a/libimagruby/Cargo.toml +++ b/libimagruby/Cargo.toml @@ -22,7 +22,7 @@ lazy_static = "0.2" log = "0.3" env_logger = "0.3" toml = "0.2" -uuid = "0.3" +uuid = { version = "0.3", features = ["v4"] } [dependencies.libimagerror] path = "../libimagerror" @@ -33,6 +33,9 @@ path = "../libimagrt" [dependencies.libimagstore] path = "../libimagstore" +[dependencies.libimagstorestdhook] +path = "../libimagstorestdhook" + [dependencies.libimagutil] path = "../libimagutil" diff --git a/libimagruby/src/lib.rs b/libimagruby/src/lib.rs index 7ff0a28..95ec767 100644 --- a/libimagruby/src/lib.rs +++ b/libimagruby/src/lib.rs @@ -26,6 +26,7 @@ extern crate uuid; #[macro_use] extern crate libimagerror; extern crate libimagstore; +extern crate libimagstorestdhook; extern crate libimagrt; #[macro_use] extern crate libimagutil; diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs index 5830b0a..32a69c2 100644 --- a/libimagruby/src/store.rs +++ b/libimagruby/src/store.rs @@ -144,6 +144,142 @@ methods!( RStore, itself, + // Build a new Store object, return a handle to it. + // + // This function takes a boolean whether the store should include debugging functionality + // (namingly the debug hooks) and a runtimepath, where the store lifes. + // It then builds a Store object (raising errors on failure and returning Nil) and a handle for + // it. + // It puts the store object and the handle in the cache and returns the handle as object to the + // Ruby code. + // + // # Returns + // + // Nil on failure (including raising an error) + // StoreHandle on success + // + fn new(store_debugging: Boolean, rtp: RString) -> AnyObject { + use std::path::PathBuf; + use libimagerror::into::IntoError; + use libimagerror::trace::trace_error; + use libimagerror::trace::trace_error_dbg; + use libimagerror::trace::trace_error_exit; + use libimagrt::configuration::ConfigErrorKind; + use libimagrt::configuration::Configuration; + use libimagrt::error::RuntimeErrorKind; + use libimagstore::error::StoreErrorKind; + use libimagstore::hook::Hook; + use libimagstore::hook::position::HookPosition as HP; + use libimagstorestdhook::debug::DebugHook; + use libimagstorestdhook::vcs::git::delete::DeleteHook as GitDeleteHook; + use libimagstorestdhook::vcs::git::store_unload::StoreUnloadHook as GitStoreUnloadHook; + use libimagstorestdhook::vcs::git::update::UpdateHook as GitUpdateHook; + + use cache::RUBY_STORE_CACHE; + + let store_debugging = typecheck!(store_debugging or return any NilClass::new()).to_bool(); + let rtp = PathBuf::from(typecheck!(rtp or return any NilClass::new()).to_string()); + + if !rtp.exists() || !rtp.is_dir() { + VM::raise(Class::from_existing("RuntimeError"), "Runtimepath not a directory"); + return NilClass::new().to_any_object(); + } + + let store_config = match Configuration::new(&rtp) { + Ok(mut cfg) => cfg.store_config().cloned(), + Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound { + VM::raise(Class::from_existing("RuntimeError"), e.description()); + return NilClass::new().to_any_object(); + } else { + warn!("No config file found."); + warn!("Continuing without configuration file"); + None + }, + }; + + let storepath = { + let mut spath = rtp.clone(); + spath.push("store"); + spath + }; + + let store = Store::new(storepath.clone(), store_config).map(|mut store| { + // If we are debugging, generate hooks for all positions + if store_debugging { + let hooks : Vec<(Box<Hook>, &str, HP)> = vec![ + (Box::new(DebugHook::new(HP::PreCreate)) , "debug", HP::PreCreate), + (Box::new(DebugHook::new(HP::PostCreate)) , "debug", HP::PostCreate), + (Box::new(DebugHook::new(HP::PreRetrieve)) , "debug", HP::PreRetrieve), + (Box::new(DebugHook::new(HP::PostRetrieve)) , "debug", HP::PostRetrieve), + (Box::new(DebugHook::new(HP::PreUpdate)) , "debug", HP::PreUpdate), + (Box::new(DebugHook::new(HP::PostUpdate)) , "debug", HP::PostUpdate), + (Box::new(DebugHook::new(HP::PreDelete)) , "debug", HP::PreDelete), + (Box::new(DebugHook::new(HP::PostDelete)) , "debug", HP::PostDelete), + ]; + + // If hook registration fails, trace the error and warn, but continue. + for (hook, aspectname, position) in hooks { + if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) { + if e.err_type() == StoreErrorKind::HookRegisterError { + trace_error_dbg(&e); + warn!("Registering debug hook with store failed"); + } else { + trace_error(&e); + }; + } + } + } + + let sp = storepath; + + let hooks : Vec<(Box<Hook>, &str, HP)> = vec![ + (Box::new(GitDeleteHook::new(sp.clone(), HP::PostDelete)), "vcs", HP::PostDelete), + (Box::new(GitUpdateHook::new(sp.clone(), HP::PostUpdate)), "vcs", HP::PostUpdate), + (Box::new(GitStoreUnloadHook::new(sp)), "vcs", HP::StoreUnload), + ]; + + for (hook, aspectname, position) in hooks { + if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) { + if e.err_type() == StoreErrorKind::HookRegisterError { + trace_error_dbg(&e); + warn!("Registering git hook with store failed"); + } else { + trace_error(&e); + }; + } + } + + store + }); + + let store = match store { + Ok(s) => s, + Err(e) => { + VM::raise(Class::from_existing("RuntimeError"), e.description()); + return NilClass::new().to_any_object(); + }, + }; + + let store_handle = StoreHandle::new(); + + let arc = RUBY_STORE_CACHE.clone(); + { + let lock = arc.lock(); + match lock { + Ok(mut hm) => { + hm.insert(store_handle.clone(), store); + return store_handle.wrap().to_any_object(); + }, + Err(e) => { + VM::raise(Class::from_existing("RuntimeError"), e.description()); + return NilClass::new().to_any_object(); + } + } + } + + } + + // Create an FileLockEntry in the store // // # Returns: @@ -406,6 +542,7 @@ methods!( pub fn setup() -> Class { let mut class = Class::new("RStore", None); class.define(|itself| { + itself.def_self("new" , new); itself.def("create" , create); itself.def("retrieve" , retrieve); itself.def("get" , get); diff --git a/libimagruby/test/test_ruby.rb b/libimagruby/test/test_ruby.rb index 082271a..c1a32fd 100644 --- a/libimagruby/test/test_ruby.rb +++ b/libimagruby/test/test_ruby.rb @@ -37,6 +37,7 @@ end puts "---" works "RStoreId.new_baseless" , (not RStoreId.new_baseless("test").nil?) +works "RStore.respond_to? :new" , (RStore.respond_to? :new) works "RStore.instance_methods.include? :create" , (RStore.instance_methods.include? :create) works "RStore.instance_methods.include? :get" , (RStore.instance_methods.include? :get) works "RStore.instance_methods.include? :retrieve" , (RStore.instance_methods.include? :retrieve) |