mirror of https://github.com/jdx/mise
fix: use shebang in run script to determine how arg escaping should work (#3455)
This commit is contained in:
parent
7556fb0c5a
commit
2f70a65ace
|
@ -13,9 +13,39 @@ assert "mise run shell" "using shell bash"
|
|||
assert_fail "mise run shell-invalid" "invalid shell"
|
||||
|
||||
cat <<EOF >mise.toml
|
||||
tasks.escapeme = "echo {{arg(name='a')}}"
|
||||
tasks.escapeme_var = "echo {{arg(name='a', var=true)}}"
|
||||
tasks.escapeme = "echo \"{{arg(name='a')}}\""
|
||||
tasks.escapeme_var = "echo \"{{arg(name='a', var=true)}}\""
|
||||
tasks.bashshebang1 = """
|
||||
#!/usr/bin/env -S bash
|
||||
echo "{{arg(name='a')}}"
|
||||
echo "{{arg(name='b', var=true)}}"
|
||||
"""
|
||||
tasks.bashshebang2 = """
|
||||
#!/usr/bin/env bash
|
||||
echo "{{arg(name='a')}}"
|
||||
echo "{{arg(name='b', var=true)}}"
|
||||
"""
|
||||
tasks.bashshebang3 = """
|
||||
#!/bin/bash
|
||||
echo "{{arg(name='a')}}"
|
||||
echo "{{arg(name='b', var=true)}}"
|
||||
"""
|
||||
tasks.escapenode = """
|
||||
#!/usr/bin/env -S node
|
||||
console.log("{{arg(name='a')}}")
|
||||
console.log("{{arg(name='b', var=true)}}")
|
||||
"""
|
||||
EOF
|
||||
|
||||
assert "mise run escapeme 'hello world'" "hello world"
|
||||
assert "mise run escapeme_var hello 'world of mise'" "hello world of mise"
|
||||
assert "mise run escapeme 'hello world'" "'hello world'"
|
||||
assert "mise run escapeme_var hello 'world of mise'" "hello 'world of mise'"
|
||||
assert "mise run bashshebang1 'a with space' hello 'world of mise'" "'a with space'
|
||||
hello 'world of mise'"
|
||||
assert "mise run bashshebang2 my_a hello 'world of mise'" "my_a
|
||||
hello 'world of mise'"
|
||||
assert "mise run bashshebang3 my_a hello 'world of mise'" "my_a
|
||||
hello 'world of mise'"
|
||||
assert "mise run escapenode my_a hello 'world of mise'" "my_a
|
||||
hello 'world of mise'"
|
||||
assert "mise run escapenode 'a with space' hello 'world of mise'" "a with space
|
||||
hello 'world of mise'"
|
||||
|
|
|
@ -6,6 +6,7 @@ use eyre::Result;
|
|||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::once;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use usage::parse::ParseValue;
|
||||
|
@ -300,21 +301,6 @@ pub fn replace_template_placeholders_with_args(
|
|||
scripts: &[String],
|
||||
args: &[String],
|
||||
) -> Result<Vec<String>> {
|
||||
let shell_type: Option<ShellType> = task.shell().unwrap_or(SETTINGS.default_inline_shell()?)[0]
|
||||
.parse()
|
||||
.ok();
|
||||
let escape = |v: &ParseValue| match v {
|
||||
ParseValue::MultiString(_) => {
|
||||
// these are already escaped
|
||||
v.to_string()
|
||||
}
|
||||
_ => match shell_type {
|
||||
Some(ShellType::Zsh | ShellType::Bash | ShellType::Fish) => {
|
||||
shell_words::quote(&v.to_string()).to_string()
|
||||
}
|
||||
_ => v.to_string(),
|
||||
},
|
||||
};
|
||||
let args = vec!["".to_string()]
|
||||
.into_iter()
|
||||
.chain(args.iter().cloned())
|
||||
|
@ -323,6 +309,23 @@ pub fn replace_template_placeholders_with_args(
|
|||
let mut out = vec![];
|
||||
let re = regex!(r"MISE_TASK_ARG:(\w+):MISE_TASK_ARG");
|
||||
for script in scripts {
|
||||
let shell_type: Option<ShellType> = shell_from_shebang(script)
|
||||
.or(task.shell())
|
||||
.unwrap_or(SETTINGS.default_inline_shell()?)[0]
|
||||
.parse()
|
||||
.ok();
|
||||
let escape = |v: &ParseValue| match v {
|
||||
ParseValue::MultiString(_) => {
|
||||
// these are already escaped
|
||||
v.to_string()
|
||||
}
|
||||
_ => match shell_type {
|
||||
Some(ShellType::Zsh | ShellType::Bash | ShellType::Fish) => {
|
||||
shell_words::quote(&v.to_string()).to_string()
|
||||
}
|
||||
_ => v.to_string(),
|
||||
},
|
||||
};
|
||||
let mut script = script.clone();
|
||||
for (arg, value) in &m.args {
|
||||
script = script.replace(
|
||||
|
@ -346,6 +349,16 @@ pub fn has_any_args_defined(spec: &usage::Spec) -> bool {
|
|||
!spec.cmd.args.is_empty() || !spec.cmd.flags.is_empty()
|
||||
}
|
||||
|
||||
fn shell_from_shebang(script: &str) -> Option<Vec<String>> {
|
||||
let shebang = script.lines().next()?.strip_prefix("#!")?;
|
||||
let shebang = shebang.strip_prefix("/usr/bin/env -S").unwrap_or(shebang);
|
||||
let shebang = shebang.strip_prefix("/usr/bin/env").unwrap_or(shebang);
|
||||
let mut parts = shebang.split_whitespace();
|
||||
let shell = parts.next()?;
|
||||
let args = parts.map(|s| s.to_string()).collect_vec();
|
||||
Some(once(shell.to_string()).chain(args).collect())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in New Issue