use std::path::PathBuf; use embed_nu::{Argument, CommandGroupConfig, Context, ValueIntoExpression}; use tokio::fs; use crate::{distro::OSConfig, error::ScriptError, utils::CFG_PATH}; pub struct ExecBuilder { pub script: PathBuf, pub os_config: OSConfig, pub task_config: embed_nu::Value, } impl ExecBuilder { #[tracing::instrument(level = "trace", skip_all)] pub async fn exec(self) -> Result<(), ScriptError> { let script_contents = self.get_script_contents().await?; let mut ctx = Context::builder() .with_command_groups(CommandGroupConfig::default().all_groups(true))? .add_var("TRM_CONFIG", self.os_config)? .add_script(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)] async fn get_script_contents(&self) -> Result { let path = CFG_PATH.join(&self.script); if path.exists() { fs::read_to_string(path).await.map_err(ScriptError::from) } else { Err(ScriptError::ScriptNotFound(path)) } } }