Add config and improve variable handling

Signed-off-by: trivernis <trivernis@protonmail.com>
integration-not-installation
trivernis 2 years ago
parent 662d3f749c
commit bf2f0a5b83
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -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,
}

@ -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<S: Script>(&self, args: S::Args) -> AppResult<()> {
self.loader.load::<S>()?.execute(args).await
async fn execute<S: Script>(&self, args: &S::Args) -> AppResult<()> {
self.loader.load::<S>()?.execute(&args).await
}
}

@ -24,7 +24,7 @@ async fn main() -> miette::Result<()> {
},
],
};
executor.setup_users(user_cfg).await?;
executor.setup_users(&user_cfg).await?;
Ok(())
}

@ -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: ToString>(s: S) -> Self {
Self::String(s.to_string())
}
}
/// An executor for nu scripts
pub struct NuExecutor {
script_path: PathBuf,
args: Vec<RecordValue>,
global_vars: HashMap<String, VarValue>,
global_vars: HashMap<String, RecordValue>,
}
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<S: ToString>(&mut self, name: S, value: VarValue) -> &mut Self {
pub fn add_global_var<S: ToString>(&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::<HashMap<_, _>>();
add_variables_to_state(vars, &mut engine_state, &mut stack);
@ -226,14 +212,3 @@ fn create_call(decl_id: DeclId, args: Vec<RecordValue>) -> 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 },
}
}

@ -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,

@ -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<RecordValue>;
fn get_args(&self) -> Vec<RecordValue>;
}
impl<T: Serialize> ScriptArgs for T {
fn get_args(self) -> Vec<RecordValue> {
fn get_args(&self) -> Vec<RecordValue> {
let mut serializer = RecordSerializer::default();
let val = self.serialize(&mut serializer).unwrap();
match val {
@ -55,19 +59,17 @@ impl<S: Script> NuScript<S> {
/// 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")
}
}
};

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script;
script!(ConfigureLocaleScript {
file = "configure-locale.nu"
file = "configure-locale"
args = LocaleConfig
});

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script;
script!(ConfigureNetworkScript {
file = "configure-network.nu"
file = "configure-network"
args = NetworkConfig
});

@ -5,7 +5,7 @@ use serde::Serialize;
use crate::script;
script!(CreatePartitionsScript {
file = "create-partitions.nu"
file = "create-partitions"
args = PartitionsConfig
});

@ -1,7 +1,7 @@
use crate::script;
script!(InstallBaseScript {
file = "install-base.nu"
file = "install-base"
args = InstallBaseArgs
});

@ -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,
}

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script;
script!(InstallDesktopScript {
file = "install-desktop.nu"
file = "install-desktop"
args = DesktopConfig
});

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script;
script!(SetupUsersScript {
file = "setup-users.nu"
file = "setup-users"
args = UsersConfig
});

@ -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");
}

Loading…
Cancel
Save