You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tourmaline/src/task/exec_builder.rs

79 lines
2.4 KiB
Rust

use std::path::{Path, PathBuf};
use embed_nu::{Argument, CommandGroupConfig, ValueIntoExpression};
use std::fs;
use crate::{distro::OSConfig, error::ScriptError, utils::CFG_PATH};
use miette::{Context, IntoDiagnostic, Result};
use super::commands::{DebugCommand, InfoCommand, RunCommand};
#[derive(Clone)]
pub struct ExecBuilder {
task_config: embed_nu::Value,
ctx: embed_nu::Context,
}
impl ExecBuilder {
pub fn create(
script: PathBuf,
os_config: OSConfig,
task_config: embed_nu::Value,
) -> Result<Self> {
let script_contents = Self::get_script_contents(&script)?;
let mut ctx = embed_nu::Context::builder()
.with_command_groups(CommandGroupConfig::default().all_groups(true))?
.add_command(RunCommand)?
.add_command(InfoCommand)?
.add_command(DebugCommand)?
.add_env_var("PWD", std::env::var("PWD").unwrap_or(String::from("/")))
.add_env_var(
"PATH",
std::env::var("PATH").unwrap_or(String::from("/usr/bin")),
)
.add_parent_env_vars()
.add_var("TRM_CONFIG", os_config)?
.add_script(script_contents)?
.build()?;
if !ctx.has_fn("main") {
Err(ScriptError::MissingMain(script).into())
} else {
Ok(Self { ctx, task_config })
}
}
#[tracing::instrument(level = "trace", skip_all)]
pub fn exec(mut self) -> Result<()> {
let pipeline = self.ctx.call_fn(
"main",
vec![Argument::Positional(self.task_config.into_expression())],
)?;
self.ctx.print_pipeline_stderr(pipeline)?;
Ok(())
}
/// Returns if the script needs to be run inside the new root
pub fn requires_chroot(&self) -> bool {
self.ctx
.get_var("RUN_IN_CHROOT")
.and_then(|v| v.as_bool().ok())
.unwrap_or(false)
}
#[tracing::instrument(level = "trace", skip_all)]
fn get_script_contents(path: &Path) -> Result<String> {
let path = CFG_PATH.join(path);
if path.exists() {
fs::read_to_string(path)
.map_err(ScriptError::from)
.into_diagnostic()
.context("reading script contents")
} else {
Err(ScriptError::ScriptNotFound(path).into())
}
}
}