terminal: Fix python venv path when spawning tasks on windows (#35909)

I haven't found any issues related to this, but it seems like currently
the wrong directory is added to the path when spawning tasks on windows
with a python virtual environment. I also deduplicated the logic at a
few places. The same constant exists in the languages crate, but we
don't want to pull an additional dependency just for this.

-1 papercut

Release Notes:

- Fix python venv path when spawning tasks on windows
This commit is contained in:
tidely 2025-08-19 01:03:16 +03:00 committed by GitHub
parent bb640c6a1c
commit e7b7c206a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -23,6 +23,13 @@ use util::{
paths::{PathStyle, RemotePathBuf}, paths::{PathStyle, RemotePathBuf},
}; };
/// The directory inside a Python virtual environment that contains executables
const PYTHON_VENV_BIN_DIR: &str = if cfg!(target_os = "windows") {
"Scripts"
} else {
"bin"
};
pub struct Terminals { pub struct Terminals {
pub(crate) local_handles: Vec<WeakEntity<terminal::Terminal>>, pub(crate) local_handles: Vec<WeakEntity<terminal::Terminal>>,
} }
@ -368,7 +375,8 @@ impl Project {
} }
None => { None => {
if let Some(venv_path) = &python_venv_directory { if let Some(venv_path) = &python_venv_directory {
add_environment_path(&mut env, &venv_path.join("bin")).log_err(); add_environment_path(&mut env, &venv_path.join(PYTHON_VENV_BIN_DIR))
.log_err();
} }
let shell = if let Some(program) = spawn_task.command { let shell = if let Some(program) = spawn_task.command {
@ -478,16 +486,12 @@ impl Project {
venv_settings: &terminal_settings::VenvSettingsContent, venv_settings: &terminal_settings::VenvSettingsContent,
cx: &App, cx: &App,
) -> Option<PathBuf> { ) -> Option<PathBuf> {
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
_ => "bin",
};
venv_settings venv_settings
.directories .directories
.iter() .iter()
.map(|name| abs_path.join(name)) .map(|name| abs_path.join(name))
.find(|venv_path| { .find(|venv_path| {
let bin_path = venv_path.join(bin_dir_name); let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
self.find_worktree(&bin_path, cx) self.find_worktree(&bin_path, cx)
.and_then(|(worktree, relative_path)| { .and_then(|(worktree, relative_path)| {
worktree.read(cx).entry_for_path(&relative_path) worktree.read(cx).entry_for_path(&relative_path)
@ -504,16 +508,12 @@ impl Project {
) -> Option<PathBuf> { ) -> Option<PathBuf> {
let (worktree, _) = self.find_worktree(abs_path, cx)?; let (worktree, _) = self.find_worktree(abs_path, cx)?;
let fs = worktree.read(cx).as_local()?.fs(); let fs = worktree.read(cx).as_local()?.fs();
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
_ => "bin",
};
venv_settings venv_settings
.directories .directories
.iter() .iter()
.map(|name| abs_path.join(name)) .map(|name| abs_path.join(name))
.find(|venv_path| { .find(|venv_path| {
let bin_path = venv_path.join(bin_dir_name); let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
// One-time synchronous check is acceptable for terminal/task initialization // One-time synchronous check is acceptable for terminal/task initialization
smol::block_on(fs.metadata(&bin_path)) smol::block_on(fs.metadata(&bin_path))
.ok() .ok()
@ -589,10 +589,7 @@ impl Project {
if venv_settings.venv_name.is_empty() { if venv_settings.venv_name.is_empty() {
let path = venv_base_directory let path = venv_base_directory
.join(match std::env::consts::OS { .join(PYTHON_VENV_BIN_DIR)
"windows" => "Scripts",
_ => "bin",
})
.join(activate_script_name) .join(activate_script_name)
.to_string_lossy() .to_string_lossy()
.to_string(); .to_string();