diff --git a/e2e/tasks/test_task_env_propagation_depends b/e2e/tasks/test_task_env_propagation_depends new file mode 100644 index 0000000000..be86d620f9 --- /dev/null +++ b/e2e/tasks/test_task_env_propagation_depends @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +cat <mise.toml +[tasks.echo] +env = { "SUB_TASK" = "sub_task_env" } +run = 'echo "\$SUB_TASK \$MY_VAR"' + + +[tasks.propagation] +depends = ["echo"] +run = "echo \$MY_VAR" +env = { "MY_VAR" = "my_variable" } +EOF + +assert_contains "mise run echo" "sub_task_env " # with trailing space +res_with_newline="$(printf "sub_task_env my_variable\nmy_variable")" +assert_contains "mise run propagation" "$res_with_newline" diff --git a/src/cli/run.rs b/src/cli/run.rs index 823b5b2ae6..5eb2ffcd46 100644 --- a/src/cli/run.rs +++ b/src/cli/run.rs @@ -856,7 +856,7 @@ impl Run { match rx.try_recv() { Ok(Some(task)) => { any = true; - let task = task.derive_env(&task_env_directives); + let task = task.derive_env(&task_env_directives.as_slice().into()); trace!("inject initial leaf: {} {}", task.name, task.args.join(" ")); let _ = sched_tx.send((task, sub_deps_clone.clone())); } @@ -887,7 +887,7 @@ impl Run { task.name, task.args.join(" ") ); - let task = task.derive_env(&task_env_directives); + let task = task.derive_env(&task_env_directives.as_slice().into()); let _ = sched_tx.send((task, sub_deps_clone.clone())); } None => { @@ -1861,9 +1861,13 @@ pub async fn resolve_depends(config: &Arc, tasks: Vec) -> Result>()) + .map(|parent_task| { + let env_list = parent_task.env.clone(); + let depends = parent_task + .all_depends(&all_tasks_map)? + .into_iter() + .map(|t| t.derive_env(&env_list)); + Ok(once(parent_task).chain(depends).collect::>()) }) .flatten_ok() .collect() diff --git a/src/cli/tasks/info.rs b/src/cli/tasks/info.rs index 2eed3ba6c3..c1c38ee2d8 100644 --- a/src/cli/tasks/info.rs +++ b/src/cli/tasks/info.rs @@ -89,7 +89,7 @@ impl TasksInfo { if !task.env.is_empty() { let env_display = task .env - .0 + .inner() .iter() .map(|directive| directive.to_string()) .collect::>() @@ -113,7 +113,7 @@ impl TasksInfo { "depends": task.depends, "depends_post": task.depends_post, "wait_for": task.wait_for, - "env": task.env.0.iter().map(|d| d.to_string()).collect::>(), + "env": task.env.inner().iter().map(|d| d.to_string()).collect::>(), "dir": task.dir, "hide": task.hide, "raw": task.raw, diff --git a/src/cli/tasks/ls.rs b/src/cli/tasks/ls.rs index eece139b0f..87629c1aef 100644 --- a/src/cli/tasks/ls.rs +++ b/src/cli/tasks/ls.rs @@ -178,7 +178,7 @@ impl TasksLs { "depends": task.depends, "depends_post": task.depends_post, "wait_for": task.wait_for, - "env": task.env.0.iter().map(|d| d.to_string()).collect::>(), + "env": task.env.inner().iter().map(|d| d.to_string()).collect::>(), "dir": task.dir, "hide": task.hide, "raw": task.raw, diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index c32c0a3436..3ebfb27a33 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -90,12 +90,27 @@ pub struct MiseTomlTool { pub struct Tasks(pub BTreeMap); #[derive(Debug, Default, Clone)] -pub struct EnvList(pub(crate) Vec); +pub struct EnvList(Vec); impl EnvList { + pub fn from_env_directives(env_directives: &[EnvDirective]) -> Self { + Self(env_directives.to_vec()) + } pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn inner(&self) -> &Vec { + &self.0 + } + pub fn inner_mut(&mut self) -> &mut Vec { + &mut self.0 + } +} + +impl From<&[EnvDirective]> for EnvList { + fn from(env_directives: &[EnvDirective]) -> Self { + EnvList::from_env_directives(env_directives) + } } impl MiseToml { @@ -424,7 +439,7 @@ impl ConfigFile for MiseToml { } fn env_entries(&self) -> eyre::Result> { - let env_entries = self.env.0.iter().cloned(); + let env_entries = self.env.inner().iter().cloned(); let path_entries = self .env_path .iter() diff --git a/src/task/mod.rs b/src/task/mod.rs index 3c0433e35f..3d1ca402a9 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -1,7 +1,7 @@ use crate::cli::version::VERSION; use crate::config::config_file::mise_toml::EnvList; use crate::config::config_file::toml::{TomlParser, deserialize_arr}; -use crate::config::env_directive::{EnvDirective, EnvResolveOptions, EnvResults, ToolsFilter}; +use crate::config::env_directive::{EnvResolveOptions, EnvResults, ToolsFilter}; use crate::config::{self, Config}; use crate::path_env::PathEnv; use crate::task::task_script_parser::{TaskScriptParser, has_any_args_defined}; @@ -241,9 +241,9 @@ impl Task { Ok(task) } - pub fn derive_env(&self, env_directives: &[EnvDirective]) -> Self { + pub fn derive_env(&self, env_list: &EnvList) -> Self { let mut new_task = self.clone(); - new_task.env.0.extend_from_slice(env_directives); + new_task.env.inner_mut().extend_from_slice(env_list.inner()); new_task } @@ -651,7 +651,7 @@ impl Task { // Use the config file path as source for proper path resolution let env_directives = self .env - .0 + .inner() .iter() .map(|directive| (directive.clone(), self.config_source.clone())) .collect();