feat: set usage arguments and flags as environment variables for toml tasks (#4159)

Fixes #4070

@jdx I have tested it locally and everything seems to work fine, but
before merging the PR I would like to have your opinion if everything
seems ok. After that, I would like to add some e2e tests, but I do not
know whether it is better to add them to e2e/tasks/test_task_run_toml,
e2e/tasks/test_task_vars or to create a new test file just for this
feature. Where do you think it is best to add them?

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Giacomo Venturini 2025-02-08 14:11:35 +01:00 committed by GitHub
parent 1bf4a0f029
commit 26138291e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 8 deletions

View File

@ -44,3 +44,26 @@ arg "myarg" "myarg description" default="foo"
run = 'echo {{arg(name="myarg")}}'
EOF
assert "mise run a" "foo"
cat <<'EOF' >mise.toml
[tasks.usage-env]
usage = '''
arg "myarg" "myarg description" default="foo"
'''
run = 'echo myarg=$usage_myarg'
EOF
assert "mise run usage-env" "myarg=foo"
assert "mise run usage-env bar" "myarg=bar"
cat <<'EOF' >mise.toml
[tasks.usage-env]
usage = '''
flag "-m --myflag <myflag>" default="foo"
'''
run = 'echo myflag=$usage_myflag'
EOF
assert "mise run usage-env" "myflag=foo"
assert "mise run usage-env -m bar" "myflag=bar"
assert "mise run usage-env --myflag bar" "myflag=bar"

View File

@ -471,6 +471,8 @@ impl Run {
for (script, args) in
task.render_run_scripts_with_args(self.cd.clone(), &task.args, &env)?
{
let get_args = || task.run.iter().chain(task.args.iter()).cloned().collect();
self.parse_usage_spec_and_init_env(task, &mut env, get_args)?;
self.exec_script(&script, &args, task, &env, &prefix)?;
}
}
@ -585,14 +587,8 @@ impl Run {
let mut env = env.clone();
let command = file.to_string_lossy().to_string();
let args = task.args.iter().cloned().collect_vec();
let (spec, _) = task.parse_usage_spec(self.cd.clone(), &env)?;
if !spec.cmd.args.is_empty() || !spec.cmd.flags.is_empty() {
let args = once(command.clone()).chain(args.clone()).collect_vec();
let po = usage::parse(&spec, &args).map_err(|err| eyre!(err))?;
for (k, v) in po.as_env() {
env.insert(k, v);
}
}
let get_args = || once(command.clone()).chain(args.clone()).collect_vec();
self.parse_usage_spec_and_init_env(task, &mut env, get_args)?;
if !self.quiet(Some(task)) {
let cmd = format!("{} {}", display_path(file), args.join(" "))
@ -606,6 +602,24 @@ impl Run {
self.exec(file, &args, task, &env, prefix)
}
fn parse_usage_spec_and_init_env(
&self,
task: &Task,
env: &mut EnvMap,
get_args: impl Fn() -> Vec<String>,
) -> Result<()> {
let (spec, _) = task.parse_usage_spec(self.cd.clone(), env)?;
if !spec.cmd.args.is_empty() || !spec.cmd.flags.is_empty() {
let args: Vec<String> = get_args();
let po = usage::parse(&spec, &args).map_err(|err| eyre!(err))?;
for (k, v) in po.as_env() {
env.insert(k, v);
}
}
Ok(())
}
fn exec(
&self,
file: &Path,