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

allow specifying #! inside shell

fixes #51
This commit is contained in:
Robin Appelman 2026-09-20 16:21:57 +02:00
commit d398b9f9e1
4 changed files with 60 additions and 17 deletions

View file

@ -1,3 +1,7 @@
## Unreleased
- Support having a `#!` inside a haze script to specify the interperter to use
## 2.4.1 ## 2.4.1
- Show database location on start - Show database location on start

View file

@ -447,8 +447,19 @@ script can be overriden by running the script with
## Nushell scripts ## Nushell scripts
By default, the script contents are executed as a `bash` script, you can instead By default, the script contents are executed as either `bash` script, or `nu` script based on the extension.
execute the script as a `nushell` script by using `.nu` as the file extention.
You can overwrite the interpreter used to execute the script by adding an extra `#!` line to the script, for example:
```bash
#! /usr/bin/env -S haze script
#! haze shell pgsql s3
#! php -f
<?php
print("Hello");
```
Note that the interpreter used needs to already be available inside the haze container.
## Configuration ## Configuration

View file

@ -1,5 +1,6 @@
#! /usr/bin/env -S haze script #! /usr/bin/env -S haze script
#! haze shell pgsql s3 #! haze shell pgsql s3
#! /usr/bin/env nu
echo 'test' | occ file:put '-' /admin/files/test.txt echo 'test' | occ file:put '-' /admin/files/test.txt
FILE_ID=$(occ info:file /admin/files/test.txt | grep fileid: | grep -oE '[0-9]+') FILE_ID=$(occ info:file /admin/files/test.txt | grep fileid: | grep -oE '[0-9]+')

View file

@ -1,4 +1,4 @@
use std::fs::read_to_string; use std::{fs::read_to_string, iter::once};
use bollard::Docker; use bollard::Docker;
use camino::Utf8PathBuf; use camino::Utf8PathBuf;
@ -36,15 +36,17 @@ pub async fn run_script(
let contents = read_to_string(&path) let contents = read_to_string(&path)
.into_diagnostic() .into_diagnostic()
.wrap_err_with(|| format!("Failed to read script file {path}"))?; .wrap_err_with(|| format!("Failed to read script file {path}"))?;
let (mut options, mode) = parse_script(&contents, config) let script = parse_script(&contents, config)
.wrap_err_with(|| format!("Failed to parse script file {path}"))?; .wrap_err_with(|| format!("Failed to parse script file {path}"))?;
let mode = mode_override.unwrap_or(mode);
let mode = mode_override.unwrap_or(script.mode);
let mut options = script.options;
let target_path = Utf8PathBuf::from(format!("/{}", path.file_name().unwrap())); let target_path = Utf8PathBuf::from(format!("/{}", path.file_name().unwrap()));
let shell = if path.extension() == Some("nu") { let shell = match (script.shell, path.extension()) {
"nu" (Some(shell), _) => shell,
} else { (None, Some("nu")) => vec!["nu".into()],
"bash" _ => vec!["bash".into()],
}; };
options.mappings.push( options.mappings.push(
@ -61,7 +63,10 @@ pub async fn run_script(
cloud cloud
.exec( .exec(
docker, docker,
vec![shell.to_string(), target_path.into_string()], shell
.into_iter()
.chain(once(target_path.into_string()))
.collect(),
true, true,
get_forward_env(), get_forward_env(),
) )
@ -74,14 +79,22 @@ pub async fn run_script(
Ok(()) Ok(())
} }
fn parse_script(script: &str, config: &HazeConfig) -> Result<(CloudOptions, ScriptMode)> { #[derive(Debug)]
let (options, mode) = script struct Script {
options: CloudOptions,
mode: ScriptMode,
shell: Option<Vec<String>>,
}
fn parse_script(script: &str, config: &HazeConfig) -> Result<Script> {
let (options, mode, line_num) = script
.lines() .lines()
.find_map(|line| line.strip_prefix("#! haze ")) .enumerate()
.find_map(|(i, line)| Some((i, line.strip_prefix("#! haze ")?)))
.and_then( .and_then(
|line| match (line.strip_prefix("shell"), line.strip_prefix("start")) { |(i, line)| match (line.strip_prefix("shell"), line.strip_prefix("start")) {
(Some(shell_options), None) => Some((shell_options.trim(), ScriptMode::Shell)), (Some(shell_options), None) => Some((shell_options.trim(), ScriptMode::Shell, i)),
(None, Some(script_options)) => Some((script_options.trim(), ScriptMode::Start)), (None, Some(script_options)) => Some((script_options.trim(), ScriptMode::Start, i)),
_ => None, _ => None,
}, },
) )
@ -90,5 +103,19 @@ fn parse_script(script: &str, config: &HazeConfig) -> Result<(CloudOptions, Scri
let options = let options =
CloudOptions::parse(config, &mut options).wrap_err("Failed to parse shell options")?; CloudOptions::parse(config, &mut options).wrap_err("Failed to parse shell options")?;
Ok((options, mode))
let first_content_line = script.lines().nth(line_num + 1).unwrap_or_default();
let shell = first_content_line.strip_prefix("#!").map(|bang| {
bang.split(" ")
.map(str::trim)
.filter(|s| !s.is_empty())
.map(String::from)
.collect()
});
Ok(Script {
options,
mode,
shell,
})
} }