Pass command as first argument to shell (#2061)

This commit is contained in:
Casey Rodarmor 2024-05-19 21:12:09 -07:00 committed by GitHub
parent c6612de760
commit 587843f09c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 32 additions and 5 deletions

View File

@ -1347,6 +1347,18 @@ file.
interpret `command` is the same shell that is used to evaluate recipe lines, interpret `command` is the same shell that is used to evaluate recipe lines,
and can be changed with `set shell := […]`. and can be changed with `set shell := […]`.
`command` is passed as the first argument, so if the command is `'echo $@'`,
the full command line, with the default shell command `shell -cu` and `args`
`'foo'` and `'bar'` will be:
```
'shell' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
```
This is so that `$@` works as expected, and `$1` refers to the first
argument. `$@` does not include the first positional argument, which is
expected to be the name of the program being run.
```just ```just
# arguments can be variables # arguments can be variables
file := '/sys/class/power_supply/BAT0/status' file := '/sys/class/power_supply/BAT0/status'
@ -1362,9 +1374,10 @@ full := shell('echo $1', 'foo')
``` ```
```just ```just
# using python as the shell # Using python as the shell. Since `python -c` sets `sys.argv[0]` to `'-c'`,
# the first "real" positional argument will be `sys.argv[2]`.
set shell := ["python3", "-c"] set shell := ["python3", "-c"]
olleh := shell('import sys; print(sys.argv[1][::-1]))', 'hello') olleh := shell('import sys; print(sys.argv[2][::-1]))', 'hello')
``` ```
#### Environment Variables #### Environment Variables

View File

@ -226,7 +226,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
}) })
} }
pub(crate) fn run_command(&self, command: &str, args: &[String]) -> Result<String, OutputError> { pub(crate) fn run_command(&self, command: &str, args: &[&str]) -> Result<String, OutputError> {
let mut cmd = self.settings.shell_command(self.config); let mut cmd = self.settings.shell_command(self.config);
cmd.arg(command); cmd.arg(command);
cmd.args(args); cmd.args(args);

View File

@ -460,8 +460,12 @@ fn sha256_file(evaluator: &Evaluator, path: &str) -> Result<String, String> {
} }
fn shell(evaluator: &Evaluator, command: &str, args: &[String]) -> Result<String, String> { fn shell(evaluator: &Evaluator, command: &str, args: &[String]) -> Result<String, String> {
let args = iter::once(command)
.chain(args.iter().map(String::as_str))
.collect::<Vec<&str>>();
evaluator evaluator
.run_command(command, args) .run_command(command, &args)
.map_err(|output_error| output_error.to_string()) .map_err(|output_error| output_error.to_string())
} }

View File

@ -779,7 +779,17 @@ fn shell_no_argument() {
#[test] #[test]
fn shell_minimal() { fn shell_minimal() {
assert_eval_eq("shell('echo $0 $1', 'justice', 'legs')", "justice legs"); assert_eval_eq("shell('echo $1 $2', 'justice', 'legs')", "justice legs");
}
#[test]
fn shell_args() {
assert_eval_eq("shell('echo $@', 'justice', 'legs')", "justice legs");
}
#[test]
fn shell_first_arg() {
assert_eval_eq("shell('echo $0')", "echo $0");
} }
#[test] #[test]