From bf2f0a5b83b2c1e80aae80c2f2f65c68a40eb91e Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 24 Sep 2022 16:23:00 +0200 Subject: [PATCH] Add config and improve variable handling Signed-off-by: trivernis --- src/config.rs | 15 +++++++++++++ src/lib.rs | 7 +++--- src/main.rs | 2 +- src/scripting/executor.rs | 31 +++------------------------ src/scripting/record.rs | 35 +++++++++++++++++++++++++++++- src/scripting/script.rs | 38 +++++++++++++++++++++------------ src/tasks/configure_locale.rs | 2 +- src/tasks/configure_network.rs | 2 +- src/tasks/create_partitions.rs | 2 +- src/tasks/install_base.rs | 2 +- src/tasks/install_bootloader.rs | 6 +++--- src/tasks/install_desktop.rs | 2 +- src/tasks/setup_users.rs | 2 +- src/utils.rs | 1 + 14 files changed, 91 insertions(+), 56 deletions(-) create mode 100644 src/config.rs diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..0d0e0f9 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,15 @@ +use serde::Serialize; + +use crate::tasks::{ + BootloaderConfig, DesktopConfig, LocaleConfig, NetworkConfig, PartitionsConfig, UsersConfig, +}; + +#[derive(Clone, Debug, Serialize)] +pub struct Config { + pub local: LocaleConfig, + pub network: NetworkConfig, + pub partitions: PartitionsConfig, + pub bootloader: BootloaderConfig, + pub desktop: DesktopConfig, + pub users: UsersConfig, +} diff --git a/src/lib.rs b/src/lib.rs index 8f46a85..492f739 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ use error::AppResult; use scripting::{loader::ScriptLoader, script::Script}; use tasks::*; +pub mod config; pub mod error; pub(crate) mod scripting; pub mod tasks; @@ -15,7 +16,7 @@ macro_rules! tasks { ($($function:ident => $script:ident),+) => { $( #[tracing::instrument(level = "trace", skip(self))] - pub async fn $function(&self, cfg: <$script as crate::scripting::script::Script>::Args) -> AppResult<()> { + pub async fn $function(&self, cfg: &<$script as crate::scripting::script::Script>::Args) -> AppResult<()> { self.execute::<$script>(cfg).await } )+ @@ -34,8 +35,8 @@ impl TaskExecutor { ); #[inline] - async fn execute(&self, args: S::Args) -> AppResult<()> { - self.loader.load::()?.execute(args).await + async fn execute(&self, args: &S::Args) -> AppResult<()> { + self.loader.load::()?.execute(&args).await } } diff --git a/src/main.rs b/src/main.rs index 8290f48..05608f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ async fn main() -> miette::Result<()> { }, ], }; - executor.setup_users(user_cfg).await?; + executor.setup_users(&user_cfg).await?; Ok(()) } diff --git a/src/scripting/executor.rs b/src/scripting/executor.rs index 9df6f9a..c1dbaf2 100644 --- a/src/scripting/executor.rs +++ b/src/scripting/executor.rs @@ -19,25 +19,11 @@ use crate::error::{AppError, AppResult}; use super::record::RecordValue; -#[derive(Clone, Debug)] -pub enum VarValue { - String(String), - Integer(i64), - Float(f64), - Boolean(bool), -} - -impl VarValue { - pub fn string(s: S) -> Self { - Self::String(s.to_string()) - } -} - /// An executor for nu scripts pub struct NuExecutor { script_path: PathBuf, args: Vec, - global_vars: HashMap, + global_vars: HashMap, } impl NuExecutor { @@ -67,7 +53,7 @@ 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: VarValue) -> &mut Self { + pub fn add_global_var(&mut self, name: S, value: RecordValue) -> &mut Self { self.global_vars.insert(name.to_string(), value); self @@ -85,7 +71,7 @@ impl NuExecutor { let vars = mem::take(&mut self.global_vars); let vars = vars .into_iter() - .map(|(k, v)| (k, map_var_to_value(v))) + .map(|(k, v)| (k, v.into_protocol_value())) .collect::>(); add_variables_to_state(vars, &mut engine_state, &mut stack); @@ -226,14 +212,3 @@ fn create_call(decl_id: DeclId, args: Vec) -> Block { fn empty_pipeline() -> PipelineData { PipelineData::new(Span::new(0, 0)) } - -fn map_var_to_value(var: VarValue) -> Value { - let span = Span::new(0, 0); - - match var { - VarValue::String(val) => Value::String { val, span }, - VarValue::Integer(val) => Value::Int { val, span }, - VarValue::Float(val) => Value::Float { val, span }, - VarValue::Boolean(val) => Value::Bool { val, span }, - } -} diff --git a/src/scripting/record.rs b/src/scripting/record.rs index a3afa98..38a707d 100644 --- a/src/scripting/record.rs +++ b/src/scripting/record.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::HashMap}; use nu_protocol::{ ast::{Expr, Expression}, - Span, Type, + Span, Type, Value, }; #[derive(Clone, Debug)] @@ -18,6 +18,7 @@ pub enum RecordValue { } impl RecordValue { + /// Creates an expresion for this value pub fn into_expr(self) -> Expr { match self { RecordValue::Int(i) => Expr::Int(i), @@ -37,6 +38,7 @@ impl RecordValue { } } + /// Creates a new wrapped expression for this value pub fn into_expression(self) -> Expression { let nu_type = self.get_type(); let expr = self.into_expr(); @@ -49,6 +51,37 @@ impl RecordValue { } } + /// Creates a nu protocol value from this value + pub fn into_protocol_value(self) -> Value { + let span = Span::new(0, 0); + + match self { + RecordValue::Int(val) => Value::Int { val, span }, + RecordValue::Float(val) => Value::Float { val, span }, + RecordValue::String(val) => Value::String { val, span }, + RecordValue::Bytes(val) => Value::Binary { val, span }, + RecordValue::Boolean(val) => Value::Bool { val, span }, + RecordValue::Null => Value::Nothing { span }, + RecordValue::Map(m) => { + let mut cols = Vec::new(); + let mut vals = Vec::new(); + for (key, val) in m { + cols.push(key.to_string()); + vals.push(val.into_protocol_value()); + } + Value::Record { cols, vals, span } + } + RecordValue::List(l) => Value::List { + vals: l + .into_iter() + .map(RecordValue::into_protocol_value) + .collect(), + span, + }, + } + } + + /// Returns the type of this value fn get_type(&self) -> Type { match &self { RecordValue::Int(_) => Type::Int, diff --git a/src/scripting/script.rs b/src/scripting/script.rs index 026e5af..ec2e652 100644 --- a/src/scripting/script.rs +++ b/src/scripting/script.rs @@ -5,11 +5,7 @@ use serde::Serialize; use crate::error::AppResult; -use super::{ - executor::{NuExecutor, VarValue}, - record::RecordValue, - record_serializer::RecordSerializer, -}; +use super::{executor::NuExecutor, record::RecordValue, record_serializer::RecordSerializer}; /// A trait implemented for a given nu script type to /// associate arguments @@ -20,16 +16,24 @@ pub trait Script { /// This function is used by the loader to load the associated file /// The name needs to include the file extension fn get_name() -> &'static str; + + /// Returns the name of the script file that get's executed before + /// the actual script. This has to be the full file name including the extension. + fn get_pre_hook() -> &'static str; + + /// Returns the name of the script file that get's executed after + /// the actual script. This has to be the full file name including the extension. + fn get_post_hook() -> &'static str; } /// Script arguments that can be collected in a Vec to /// be passed to the script pub trait ScriptArgs { - fn get_args(self) -> Vec; + fn get_args(&self) -> Vec; } impl ScriptArgs for T { - fn get_args(self) -> Vec { + fn get_args(&self) -> Vec { let mut serializer = RecordSerializer::default(); let val = self.serialize(&mut serializer).unwrap(); match val { @@ -55,19 +59,17 @@ impl NuScript { /// Executes the script with the given args #[tracing::instrument(level = "trace", skip(self))] - pub async fn execute(&self, args: S::Args) -> AppResult<()> { + pub async fn execute(&self, args: &S::Args) -> AppResult<()> { NuExecutor::new(&self.path) .add_args(args.get_args()) - .add_global_var("BY_TOURMALINE", VarValue::string("Hello from Tourmaline!")) - .add_global_var( - "ANOTHER_ONE", - VarValue::string("This variable was provided by tourmaline"), - ) .execute() .await } } +/// Defines a script +/// This macro doesn't accept a file extension for the script name +/// as it is reused for the hook name #[macro_export] macro_rules! script { ($script:ident { @@ -80,7 +82,15 @@ macro_rules! script { type Args = $argtype; fn get_name() -> &'static str { - $name + concat!($name, ".nu") + } + + fn get_pre_hook() -> &'static str { + concat!("name", ".pre.nu") + } + + fn get_post_hook() -> &'static str { + concat!("name", ".post.nu") } } }; diff --git a/src/tasks/configure_locale.rs b/src/tasks/configure_locale.rs index bad5362..9c7a19a 100644 --- a/src/tasks/configure_locale.rs +++ b/src/tasks/configure_locale.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::script; script!(ConfigureLocaleScript { - file = "configure-locale.nu" + file = "configure-locale" args = LocaleConfig }); diff --git a/src/tasks/configure_network.rs b/src/tasks/configure_network.rs index 773d398..d95b968 100644 --- a/src/tasks/configure_network.rs +++ b/src/tasks/configure_network.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::script; script!(ConfigureNetworkScript { - file = "configure-network.nu" + file = "configure-network" args = NetworkConfig }); diff --git a/src/tasks/create_partitions.rs b/src/tasks/create_partitions.rs index dfc5bb3..2bfb7f9 100644 --- a/src/tasks/create_partitions.rs +++ b/src/tasks/create_partitions.rs @@ -5,7 +5,7 @@ use serde::Serialize; use crate::script; script!(CreatePartitionsScript { - file = "create-partitions.nu" + file = "create-partitions" args = PartitionsConfig }); diff --git a/src/tasks/install_base.rs b/src/tasks/install_base.rs index 7552edc..8856f95 100644 --- a/src/tasks/install_base.rs +++ b/src/tasks/install_base.rs @@ -1,7 +1,7 @@ use crate::script; script!(InstallBaseScript { - file = "install-base.nu" + file = "install-base" args = InstallBaseArgs }); diff --git a/src/tasks/install_bootloader.rs b/src/tasks/install_bootloader.rs index d9ef33f..7545bb1 100644 --- a/src/tasks/install_bootloader.rs +++ b/src/tasks/install_bootloader.rs @@ -5,12 +5,12 @@ use serde::Serialize; use crate::script; script!(InstallBootloaderScript { - file = "install-bootloader.nu" - args = BooloaderConfig + file = "install-bootloader" + args = BootloaderConfig }); #[derive(Clone, Debug, Serialize)] -pub struct BooloaderConfig { +pub struct BootloaderConfig { preset: BootloaderPreset, location: PathBuf, } diff --git a/src/tasks/install_desktop.rs b/src/tasks/install_desktop.rs index 9c6f07a..910f067 100644 --- a/src/tasks/install_desktop.rs +++ b/src/tasks/install_desktop.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::script; script!(InstallDesktopScript { - file = "install-desktop.nu" + file = "install-desktop" args = DesktopConfig }); diff --git a/src/tasks/setup_users.rs b/src/tasks/setup_users.rs index 23fd4c4..3fb5152 100644 --- a/src/tasks/setup_users.rs +++ b/src/tasks/setup_users.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::script; script!(SetupUsersScript { - file = "setup-users.nu" + file = "setup-users" args = UsersConfig }); diff --git a/src/utils.rs b/src/utils.rs index 67f11dc..3469a0d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,4 +5,5 @@ const DEFAULT_CONFIG_DIR: &str = "/etc"; lazy_static::lazy_static! { pub static ref CFG_PATH: PathBuf = env::var("TRM_CFG_PATH").map(PathBuf::from).unwrap_or_else(|_| PathBuf::from(DEFAULT_CONFIG_DIR).join("tourmaline")); pub static ref SCRIPT_PATH: PathBuf = CFG_PATH.join("scripts"); + pub static ref HOOK_PATH: PathBuf = CFG_PATH.join("hooks"); }