Replace a smol::block_on

This commit is contained in:
Lukas Wirth 2025-08-14 15:03:23 +02:00
parent dc0e81b13b
commit 7030465d04
2 changed files with 95 additions and 104 deletions

View file

@ -1008,6 +1008,7 @@ const BINARY_DIR: &str = if cfg!(target_os = "windows") {
"bin" "bin"
}; };
// TODO lw: this depends on the shell?
const ACTIVATE_PATH: &str = if cfg!(target_os = "windows") { const ACTIVATE_PATH: &str = if cfg!(target_os = "windows") {
"Scripts/activate.bat" "Scripts/activate.bat"
} else { } else {

View file

@ -1,7 +1,7 @@
use crate::{Project, ProjectPath}; use crate::{Project, ProjectPath};
use anyhow::Result; use anyhow::Result;
use collections::HashMap; use collections::HashMap;
use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity}; use gpui::{App, AppContext as _, AsyncApp, Context, Entity, Task, WeakEntity};
use itertools::Itertools; use itertools::Itertools;
use language::LanguageName; use language::LanguageName;
use remote::ssh_session::SshArgs; use remote::ssh_session::SshArgs;
@ -122,12 +122,12 @@ impl Project {
cx.spawn(async move |project, cx| { cx.spawn(async move |project, cx| {
let python_venv_directory = if let Some(path) = path { let python_venv_directory = if let Some(path) = path {
project match project.upgrade() {
.update(cx, |this, cx| { Some(project) => Self::python_venv_directory(project, path, venv.clone(), cx)
this.python_venv_directory(path, venv.clone(), cx) .await?
})? .zip(Some(venv)),
.await None => None,
.zip(Some(venv)) }
} else { } else {
None None
}; };
@ -166,27 +166,18 @@ impl Project {
}; };
let activate_keyword = match venv_settings.activate_script { let activate_keyword = match venv_settings.activate_script {
terminal_settings::ActivateScript::Default => match std::env::consts::OS { terminal_settings::ActivateScript::Default => ".",
"windows" => ".",
_ => ".",
},
terminal_settings::ActivateScript::Nushell => "overlay use", terminal_settings::ActivateScript::Nushell => "overlay use",
terminal_settings::ActivateScript::PowerShell => ".", terminal_settings::ActivateScript::PowerShell => ".",
terminal_settings::ActivateScript::Pyenv => "pyenv", terminal_settings::ActivateScript::Pyenv => "pyenv",
_ => "source", _ => "source",
}; };
let line_ending = match std::env::consts::OS { let line_ending = if cfg!(windows) { '\r' } else { 'n' };
"windows" => "\r",
_ => "\n",
};
if venv_settings.venv_name.is_empty() { if venv_settings.venv_name.is_empty() {
let path = python_venv_directory let path = python_venv_directory
.join(match std::env::consts::OS { .join(BINARY_DIR)
"windows" => "Scripts",
_ => "bin",
})
.join(activate_script_name) .join(activate_script_name)
.to_string_lossy() .to_string_lossy()
.to_string(); .to_string();
@ -486,98 +477,91 @@ impl Project {
}) })
} }
fn python_venv_directory( async fn python_venv_directory(
&self, this: Entity<Self>,
abs_path: Arc<Path>, abs_path: Arc<Path>,
venv_settings: VenvSettings, venv_settings: VenvSettings,
cx: &Context<Project>, cx: &mut AsyncApp,
) -> Task<Option<PathBuf>> { ) -> Result<Option<PathBuf>> {
cx.spawn(async move |this, cx| { let Some((worktree, relative_path)) =
if let Some((worktree, relative_path)) = this this.update(cx, |this, cx| this.find_worktree(&abs_path, cx))?
.update(cx, |this, cx| this.find_worktree(&abs_path, cx)) else {
.ok()? return Ok(None);
{ };
let toolchain = this let toolchain = this
.update(cx, |this, cx| { .update(cx, |this, cx| {
this.active_toolchain( this.active_toolchain(
ProjectPath { ProjectPath {
worktree_id: worktree.read(cx).id(), worktree_id: worktree.read(cx).id(),
path: relative_path.into(), path: relative_path.into(),
}, },
LanguageName::new("Python"), LanguageName::new("Python"),
cx, cx,
) )
}) })?
.ok()? .await;
.await;
if let Some(toolchain) = toolchain { if let Some(toolchain) = toolchain {
let toolchain_path = Path::new(toolchain.path.as_ref()); let toolchain_path = Path::new(toolchain.path.as_ref());
return Some(toolchain_path.parent()?.parent()?.to_path_buf()); return Ok(toolchain_path
.parent()
.and_then(|p| Some(p.parent()?.to_path_buf())));
}
let Some(venv_settings) = venv_settings.as_option() else {
return Ok(None);
};
let tool = this.update(cx, |this, cx| {
venv_settings
.directories
.iter()
.map(|name| abs_path.join(name))
.find(|venv_path| {
let bin_path = venv_path.join(BINARY_DIR);
this.find_worktree(&bin_path, cx)
.and_then(|(worktree, relative_path)| {
worktree.read(cx).entry_for_path(&relative_path)
})
.is_some_and(|entry| entry.is_dir())
})
})?;
if let Some(toolchain_path) = tool {
return Ok(Some(toolchain_path));
}
let r = this.update(cx, move |_, cx| {
let fs = worktree.read(cx).as_local()?.fs().clone();
let map: Vec<_> = venv_settings
.directories
.iter()
.map(|name| abs_path.join(name))
.collect();
Some(cx.spawn(async move |_, _| {
for venv_path in map {
let bin_path = venv_path.join(BINARY_DIR);
// One-time synchronous check is acceptable for terminal/task initialization
// we are within a spawned future anyways
let exists = fs
.metadata(&bin_path)
.await
.ok()
.flatten()
.map_or(false, |meta| meta.is_dir);
if exists {
return Some(venv_path);
}
} }
} None
let venv_settings = venv_settings.as_option()?; }))
this.update(cx, move |this, cx| { })?;
if let Some(path) = this.find_venv_in_worktree(&abs_path, &venv_settings, cx) { Ok(match r {
return Some(path); Some(task) => task.await,
} None => None,
this.find_venv_on_filesystem(&abs_path, &venv_settings, cx)
})
.ok()
.flatten()
}) })
} }
fn find_venv_in_worktree(
&self,
abs_path: &Path,
venv_settings: &terminal_settings::VenvSettingsContent,
cx: &App,
) -> Option<PathBuf> {
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
_ => "bin",
};
venv_settings
.directories
.iter()
.map(|name| abs_path.join(name))
.find(|venv_path| {
let bin_path = venv_path.join(bin_dir_name);
self.find_worktree(&bin_path, cx)
.and_then(|(worktree, relative_path)| {
worktree.read(cx).entry_for_path(&relative_path)
})
.is_some_and(|entry| entry.is_dir())
})
}
fn find_venv_on_filesystem(
&self,
abs_path: &Path,
venv_settings: &terminal_settings::VenvSettingsContent,
cx: &App,
) -> Option<PathBuf> {
let (worktree, _) = self.find_worktree(abs_path, cx)?;
let fs = worktree.read(cx).as_local()?.fs();
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
_ => "bin",
};
venv_settings
.directories
.iter()
.map(|name| abs_path.join(name))
.find(|venv_path| {
let bin_path = venv_path.join(bin_dir_name);
// One-time synchronous check is acceptable for terminal/task initialization
smol::block_on(fs.metadata(&bin_path))
.ok()
.flatten()
.map_or(false, |meta| meta.is_dir)
})
}
fn activate_script_kind(shell: Option<&str>) -> ActivateScript { fn activate_script_kind(shell: Option<&str>) -> ActivateScript {
let shell_env = std::env::var("SHELL").ok(); let shell_env = std::env::var("SHELL").ok();
let shell_path = shell.or_else(|| shell_env.as_deref()); let shell_path = shell.or_else(|| shell_env.as_deref());
@ -599,6 +583,12 @@ impl Project {
} }
} }
const BINARY_DIR: &str = if cfg!(target_os = "windows") {
"Scripts"
} else {
"bin"
};
pub fn wrap_for_ssh( pub fn wrap_for_ssh(
ssh_command: &SshCommand, ssh_command: &SshCommand,
command: Option<(&String, &Vec<String>)>, command: Option<(&String, &Vec<String>)>,