From d19f40591182b8fd97e0bee731469845e81b57ed Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 24 Sep 2022 16:50:39 +0200 Subject: [PATCH] Add hooks --- configs/crystal/hooks/setup-users.post.nu | 3 ++ configs/crystal/hooks/setup-users.pre.nu | 4 +++ src/lib.rs | 35 ++++++++++++++++++++--- src/scripting/executor.rs | 19 ++++++++++-- src/scripting/loader.rs | 27 +++++++++++++++-- src/scripting/script.rs | 20 +++++++++++-- 6 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 configs/crystal/hooks/setup-users.post.nu create mode 100644 configs/crystal/hooks/setup-users.pre.nu diff --git a/configs/crystal/hooks/setup-users.post.nu b/configs/crystal/hooks/setup-users.post.nu new file mode 100644 index 0000000..fbef04a --- /dev/null +++ b/configs/crystal/hooks/setup-users.post.nu @@ -0,0 +1,3 @@ +def main [cfg] { + echo "Running after creating users" +} \ No newline at end of file diff --git a/configs/crystal/hooks/setup-users.pre.nu b/configs/crystal/hooks/setup-users.pre.nu new file mode 100644 index 0000000..4b5e949 --- /dev/null +++ b/configs/crystal/hooks/setup-users.pre.nu @@ -0,0 +1,4 @@ +def main [cfg] { + echo "Running before creating users" + echo $TRM_VERSION +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 492f739..32d6082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ +use config::Config; use error::AppResult; -use scripting::{loader::ScriptLoader, script::Script}; +use scripting::{ + loader::{HookType, ScriptLoader}, + script::{NuScript, Script, ScriptArgs}, +}; use tasks::*; pub mod config; @@ -9,6 +13,7 @@ pub mod tasks; pub(crate) mod utils; pub struct TaskExecutor { + config: Option, loader: ScriptLoader, } @@ -17,7 +22,7 @@ macro_rules! tasks { $( #[tracing::instrument(level = "trace", skip(self))] pub async fn $function(&self, cfg: &<$script as crate::scripting::script::Script>::Args) -> AppResult<()> { - self.execute::<$script>(cfg).await + self.execute_task::<$script>(cfg).await } )+ } @@ -34,9 +39,30 @@ impl TaskExecutor { configure_local => ConfigureLocaleScript ); + async fn execute_task(&self, args: &S::Args) -> AppResult<()> { + if let Some(pre_hook) = self.loader.load_hook::(HookType::Pre) { + self.execute(pre_hook, args).await?; + } + let script = self.loader.load::()?; + self.execute(script, args).await?; + + if let Some(post_hook) = self.loader.load_hook::(HookType::Post) { + self.execute(post_hook, args).await?; + } + + Ok(()) + } + #[inline] - async fn execute(&self, args: &S::Args) -> AppResult<()> { - self.loader.load::()?.execute(&args).await + async fn execute(&self, mut script: NuScript, args: &S::Args) -> AppResult<()> { + if let Some(cfg) = self.config.as_ref() { + script.set_global_var("TRM_CONFIG", cfg.get_args()) + } else { + &mut script + } + .set_global_var("TRM_VERSION", env!("CARGO_PKG_VERSION")) + .execute(args) + .await } } @@ -44,6 +70,7 @@ impl Default for TaskExecutor { fn default() -> Self { Self { loader: ScriptLoader::new(), + config: None, } } } diff --git a/src/scripting/executor.rs b/src/scripting/executor.rs index c1dbaf2..ecb5b76 100644 --- a/src/scripting/executor.rs +++ b/src/scripting/executor.rs @@ -53,8 +53,23 @@ impl NuExecutor { /// Adds a global variable to the executor which can /// be accessed from within the script - pub fn add_global_var(&mut self, name: S, value: RecordValue) -> &mut Self { - self.global_vars.insert(name.to_string(), value); + pub fn add_global_var>( + &mut self, + name: S, + value: V, + ) -> &mut Self { + self.global_vars.insert(name.to_string(), value.into()); + + self + } + + /// Adds multiple global variables + pub fn add_global_vars, I: IntoIterator>( + &mut self, + vars: I, + ) -> &mut Self { + self.global_vars + .extend(&mut vars.into_iter().map(|(k, v)| (k.to_string(), v.into()))); self } diff --git a/src/scripting/loader.rs b/src/scripting/loader.rs index 6c9a5ae..21de652 100644 --- a/src/scripting/loader.rs +++ b/src/scripting/loader.rs @@ -6,21 +6,28 @@ use super::script::{NuScript, Script}; /// A loader for nu script files pub struct ScriptLoader { - base_dir: PathBuf, + script_dir: PathBuf, + hook_dir: PathBuf, +} + +pub enum HookType { + Pre, + Post, } impl ScriptLoader { /// Creates a new script loader with the default config dir pub fn new() -> Self { Self { - base_dir: crate::utils::SCRIPT_PATH.to_owned(), + script_dir: crate::utils::SCRIPT_PATH.to_owned(), + hook_dir: crate::utils::HOOK_PATH.to_owned(), } } /// Loads the given script file #[tracing::instrument(level = "trace", skip_all)] pub fn load(&self) -> AppResult> { - let script_path = self.base_dir.join(S::get_name()); + let script_path = self.script_dir.join(S::get_name()); if !script_path.exists() { Err(AppError::ScriptNotFound(script_path)) @@ -28,4 +35,18 @@ impl ScriptLoader { Ok(NuScript::new(script_path)) } } + + pub fn load_hook(&self, hook_type: HookType) -> Option> { + let script_name = match hook_type { + HookType::Pre => S::get_pre_hook(), + HookType::Post => S::get_post_hook(), + }; + let script_path = self.hook_dir.join(script_name); + + if !script_path.exists() { + None + } else { + Some(NuScript::new(script_path)) + } + } } diff --git a/src/scripting/script.rs b/src/scripting/script.rs index ec2e652..a101314 100644 --- a/src/scripting/script.rs +++ b/src/scripting/script.rs @@ -1,5 +1,5 @@ use core::fmt; -use std::{marker::PhantomData, path::PathBuf}; +use std::{collections::HashMap, marker::PhantomData, path::PathBuf}; use serde::Serialize; @@ -46,6 +46,7 @@ impl ScriptArgs for T { /// A nu script instance that can be executed pub struct NuScript { path: PathBuf, + vars: HashMap, __phantom: PhantomData, } @@ -53,15 +54,28 @@ impl NuScript { pub(crate) fn new(path: PathBuf) -> Self { Self { path, + vars: HashMap::new(), __phantom: PhantomData, } } + /// Adds a global variable + pub fn set_global_var>( + &mut self, + key: S1, + value: V, + ) -> &mut Self { + self.vars.insert(key.to_string(), value.into()); + + self + } + /// Executes the script with the given args #[tracing::instrument(level = "trace", skip(self))] pub async fn execute(&self, args: &S::Args) -> AppResult<()> { NuExecutor::new(&self.path) .add_args(args.get_args()) + .add_global_vars(self.vars.clone()) .execute() .await } @@ -86,11 +100,11 @@ macro_rules! script { } fn get_pre_hook() -> &'static str { - concat!("name", ".pre.nu") + concat!($name, ".pre.nu") } fn get_post_hook() -> &'static str { - concat!("name", ".post.nu") + concat!($name, ".post.nu") } } };