Propagate custom env from language task config into the terminal

It still does not work, as the terminal task is run via `sh -c` and does not pick up the env variables of a parent process

co-authored-by: Piotr Osiewicz <piotr@zed.dev>
This commit is contained in:
Kirill Bulatov 2024-08-29 19:50:20 +03:00
parent fc4c533d0a
commit 71d19975f1
10 changed files with 69 additions and 29 deletions

View file

@ -32,6 +32,9 @@
},
"Rust": {
"tasks": {
"extra_env": {
"RUST_BACKTRACE": "0"
},
"variables": {
"RUST_DEFAULT_PACKAGE_RUN": "zed"
}

2
Cargo.lock generated
View file

@ -1554,7 +1554,7 @@ dependencies = [
"bitflags 2.6.0",
"cexpr",
"clang-sys",
"itertools 0.12.1",
"itertools 0.13.0",
"log",
"prettyplease",
"proc-macro2",

View file

@ -747,6 +747,13 @@
},
// Different settings for specific languages.
"languages": {
"Rust": {
"tasks": {
"extra_env": {
"RUST_BACKTRACE": "0"
}
}
},
"Astro": {
"prettier": {
"allowed": true,

View file

@ -767,8 +767,11 @@ fn scroll_debounce_ms() -> u64 {
}
/// The task settings for a particular language.
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize, JsonSchema)]
#[derive(Default, Debug, Clone, Deserialize, PartialEq, Serialize, JsonSchema)]
#[serde(default)]
pub struct LanguageTaskConfig {
/// Extra environment variables to set for a particular language.
pub extra_env: HashMap<String, String>,
/// Extra task variables to set for a particular language.
pub variables: HashMap<String, String>,
}

View file

@ -471,15 +471,18 @@ impl ContextProvider for RustContextProvider {
RUST_PACKAGE_TASK_VARIABLE.template_value(),
VariableName::Symbol.template_value(),
),
command: "cargo".into(),
args: vec![
"test".into(),
"-p".into(),
RUST_PACKAGE_TASK_VARIABLE.template_value(),
VariableName::Symbol.template_value(),
"--".into(),
"--nocapture".into(),
],
// TODO kb
//command: "cargo".into(),
// args: vec![
// "test".into(),
// "-p".into(),
// RUST_PACKAGE_TASK_VARIABLE.template_value(),
// VariableName::Symbol.template_value(),
// "--".into(),
// "--nocapture".into(),
// ],
command: "echo".into(),
args: vec!["$RUST_BACKTRACE".into()],
tags: vec!["rust-test".to_owned()],
cwd: Some("$ZED_DIRNAME".to_owned()),
..TaskTemplate::default()

View file

@ -9278,7 +9278,7 @@ impl Project {
})?;
let task_context = context_task.await.unwrap_or_default();
Ok(proto::TaskContext {
project_env: task_context.project_env.into_iter().collect(),
project_env: task_context.extra_env.into_iter().collect(),
cwd: task_context
.cwd
.map(|cwd| cwd.to_string_lossy().to_string()),
@ -10292,6 +10292,16 @@ impl Project {
location: Location,
cx: &mut ModelContext<'_, Project>,
) -> Task<Option<TaskContext>> {
let extra_env = location.buffer.update(cx, |buffer, cx| {
language_settings(
buffer.language_at(location.range.start).as_ref(),
buffer.file(),
cx,
)
.tasks
.extra_env
.clone()
});
if self.is_local_or_ssh() {
let (worktree_id, worktree_abs_path) = if let Some(worktree) = self.task_worktree(cx) {
(
@ -10328,11 +10338,14 @@ impl Project {
.ok()?
.await;
Some(TaskContext {
project_env: project_env.unwrap_or_default(),
let mut project_env = project_env.unwrap_or_default();
project_env.extend(extra_env);
let task_context = TaskContext {
extra_env: project_env,
cwd: worktree_abs_path.map(|p| p.to_path_buf()),
task_variables,
})
};
Some(task_context)
})
} else if let Some(project_id) = self
.remote_id()
@ -10348,8 +10361,13 @@ impl Project {
});
cx.background_executor().spawn(async move {
let task_context = task_context.await.log_err()?;
let mut new_extra_env = task_context
.project_env
.into_iter()
.collect::<HashMap<_, _>>();
new_extra_env.extend(extra_env);
Some(TaskContext {
project_env: task_context.project_env.into_iter().collect(),
extra_env: new_extra_env,
cwd: task_context.cwd.map(PathBuf::from),
task_variables: task_context
.task_variables

View file

@ -239,10 +239,11 @@ pub struct TaskContext {
pub cwd: Option<PathBuf>,
/// Additional environment variables associated with a given task.
pub task_variables: TaskVariables,
/// TODO kb: fill in info about environment from settings
/// Environment variables obtained when loading the project into Zed.
/// This is the environment one would get when `cd`ing in a terminal
/// into the project's root directory.
pub project_env: HashMap<String, String>,
pub extra_env: HashMap<String, String>,
}
/// This is a new type representing a 'tag' on a 'runnable symbol', typically a test of main() function, found via treesitter.

View file

@ -184,7 +184,7 @@ impl TaskTemplate {
let env = {
// Start with the project environment as the base.
let mut env = cx.project_env.clone();
let mut env = cx.extra_env.clone();
// Extend that environment with what's defined in the TaskTemplate
env.extend(self.env.clone());
@ -403,7 +403,7 @@ mod tests {
let cx = TaskContext {
cwd: None,
task_variables: TaskVariables::default(),
project_env: HashMap::default(),
extra_env: HashMap::default(),
};
assert_eq!(
resolved_task(&task_without_cwd, &cx).cwd,
@ -415,7 +415,7 @@ mod tests {
let cx = TaskContext {
cwd: Some(context_cwd.clone()),
task_variables: TaskVariables::default(),
project_env: HashMap::default(),
extra_env: HashMap::default(),
};
assert_eq!(
resolved_task(&task_without_cwd, &cx).cwd,
@ -431,7 +431,7 @@ mod tests {
let cx = TaskContext {
cwd: None,
task_variables: TaskVariables::default(),
project_env: HashMap::default(),
extra_env: HashMap::default(),
};
assert_eq!(
resolved_task(&task_with_cwd, &cx).cwd,
@ -442,7 +442,7 @@ mod tests {
let cx = TaskContext {
cwd: Some(context_cwd.clone()),
task_variables: TaskVariables::default(),
project_env: HashMap::default(),
extra_env: HashMap::default(),
};
assert_eq!(
resolved_task(&task_with_cwd, &cx).cwd,
@ -518,7 +518,7 @@ mod tests {
&TaskContext {
cwd: None,
task_variables: TaskVariables::from_iter(all_variables.clone()),
project_env: HashMap::default(),
extra_env: HashMap::default(),
},
).unwrap_or_else(|| panic!("Should successfully resolve task {task_with_all_variables:?} with variables {all_variables:?}"));
@ -606,7 +606,7 @@ mod tests {
&TaskContext {
cwd: None,
task_variables: TaskVariables::from_iter(not_all_variables),
project_env: HashMap::default(),
extra_env: HashMap::default(),
},
);
assert_eq!(resolved_task_attempt, None, "If any of the Zed task variables is not substituted, the task should not be resolved, but got some resolution without the variable {removed_variable:?} (index {i})");
@ -659,7 +659,7 @@ mod tests {
VariableName::Symbol,
"test_symbol".to_string(),
))),
project_env: HashMap::default(),
extra_env: HashMap::default(),
};
for (i, symbol_dependent_task) in [
@ -787,7 +787,7 @@ mod tests {
let context = TaskContext {
cwd: None,
task_variables: TaskVariables::from_iter(all_variables.clone()),
project_env,
extra_env: project_env,
};
let resolved = template

View file

@ -307,7 +307,7 @@ mod tests {
(VariableName::Row, "1".into()),
(VariableName::Column, "1".into()),
]),
project_env: HashMap::default(),
extra_env: HashMap::default(),
}
);
@ -334,7 +334,7 @@ mod tests {
(VariableName::SelectedText, "is_i".into()),
(VariableName::Symbol, "this_is_a_rust_file".into()),
]),
project_env: HashMap::default(),
extra_env: HashMap::default(),
}
);
@ -359,7 +359,7 @@ mod tests {
(VariableName::Column, "1".into()),
(VariableName::Symbol, "this_is_a_test".into()),
]),
project_env: HashMap::default(),
extra_env: HashMap::default(),
}
);
}

View file

@ -320,6 +320,11 @@ impl TerminalBuilder {
completion_tx: Sender<()>,
cx: &mut AppContext,
) -> Result<TerminalBuilder> {
if task.is_some() {
// TODO kb we set the correct env vars to be RUST_BACTRACE=0, but Alacritty(?) does not propagate that inside our
// '/bin/zsh -i -c `BLAH`' command. How to override this?
dbg!(&env);
};
// TODO: Properly set the current locale,
env.entry("LC_ALL".to_string())
.or_insert_with(|| "en_US.UTF-8".to_string());