1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-10-01 08:44:09 +02:00

add haze scripts

fixes #27
This commit is contained in:
Robin Appelman 2026-08-17 17:54:27 +02:00
commit 125b68e08a
7 changed files with 207 additions and 9 deletions

94
src/script.rs Normal file
View file

@ -0,0 +1,94 @@
use std::fs::read_to_string;
use bollard::Docker;
use camino::Utf8PathBuf;
use miette::{Context, IntoDiagnostic, Report, Result};
use strum::EnumString;
use crate::{
cloud::CloudOptions,
config::HazeConfig,
get_forward_env,
mapping::{Mapping, MappingSourceType},
setup,
};
#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumString)]
#[strum(serialize_all = "lowercase")]
pub enum ScriptMode {
Shell,
Start,
}
pub async fn run_script(
path: String,
config: &HazeConfig,
docker: &Docker,
mode_override: Option<ScriptMode>,
) -> Result<()> {
let path: Utf8PathBuf = Utf8PathBuf::from(path)
.canonicalize()
.into_diagnostic()
.wrap_err("Failed to normalize script path")?
.try_into()
.into_diagnostic()
.wrap_err("Non-utf8 script path")?;
let contents = read_to_string(&path)
.into_diagnostic()
.wrap_err_with(|| format!("Failed to read script file {path}"))?;
let (mut options, mode) = parse_script(&contents, config)
.wrap_err_with(|| format!("Failed to parse script file {path}"))?;
let mode = mode_override.unwrap_or(mode);
let target_path = Utf8PathBuf::from(format!("/{}", path.file_name().unwrap()));
let shell = if path.extension() == Some("nu") {
"nu"
} else {
"bash"
};
options.mappings.push(
Mapping::owned(
MappingSourceType::Absolute,
path.clone(),
target_path.clone(),
)
.read_only()
.dont_create(),
);
let cloud = setup(docker, options, &config).await?;
cloud
.exec(
&docker,
vec![shell.to_string(), target_path.into_string()],
true,
get_forward_env(),
)
.await?;
if mode == ScriptMode::Shell {
cloud.destroy(&docker, &config).await?;
}
Ok(())
}
fn parse_script(script: &str, config: &HazeConfig) -> Result<(CloudOptions, ScriptMode)> {
let (options, mode) = script
.lines()
.find_map(|line| line.strip_prefix("#! haze "))
.and_then(
|line| match (line.strip_prefix("shell"), line.strip_prefix("start")) {
(Some(shell_options), None) => Some((shell_options.trim(), ScriptMode::Shell)),
(None, Some(script_options)) => Some((script_options.trim(), ScriptMode::Start)),
_ => None,
},
)
.ok_or_else(|| Report::msg("No '#! haze shell' or '#! haze start' found in script"))?;
let mut options = options.split(' ').peekable();
let options =
CloudOptions::parse(config, &mut options).wrap_err("Failed to parse shell options")?;
Ok((options, mode))
}