use std::path::{Path, PathBuf}; use embed_nu::{Argument, CommandGroupConfig, Context, ValueIntoExpression}; use std::fs; use crate::{distro::OSConfig, error::ScriptError, utils::CFG_PATH}; #[derive(Clone)] pub struct ExecBuilder { script: PathBuf, script_contents: String, os_config: OSConfig, task_config: embed_nu::Value, } impl ExecBuilder { pub fn create( script: PathBuf, os_config: OSConfig, task_config: embed_nu::Value, ) -> Result { let script_contents = Self::get_script_contents(&script)?; Ok(Self { script, script_contents, os_config, task_config, }) } #[tracing::instrument(level = "trace", skip_all)] pub fn exec(self) -> Result<(), ScriptError> { let mut ctx = Context::builder() .with_command_groups(CommandGroupConfig::default().all_groups(true))? .add_parent_env_vars() .add_var("TRM_CONFIG", self.os_config)? .add_script(self.script_contents)? .build()?; if ctx.has_fn("main") { let pipeline = ctx.call_fn( "main", vec![Argument::Positional(self.task_config.into_expression())], )?; ctx.print_pipeline_stderr(pipeline)?; Ok(()) } else { Err(ScriptError::MissingMain(self.script)) } } #[tracing::instrument(level = "trace", skip_all)] fn get_script_contents(path: &Path) -> Result { let path = CFG_PATH.join(path); if path.exists() { fs::read_to_string(path).map_err(ScriptError::from) } else { Err(ScriptError::ScriptNotFound(path)) } } }