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,17 +477,17 @@ 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(
@ -507,74 +498,67 @@ impl Project {
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 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) {
return Some(path);
}
this.find_venv_on_filesystem(&abs_path, &venv_settings, cx)
})
.ok()
.flatten()
})
} }
fn find_venv_in_worktree( let Some(venv_settings) = venv_settings.as_option() else {
&self, return Ok(None);
abs_path: &Path,
venv_settings: &terminal_settings::VenvSettingsContent,
cx: &App,
) -> Option<PathBuf> {
let bin_dir_name = match std::env::consts::OS {
"windows" => "Scripts",
_ => "bin",
}; };
let tool = this.update(cx, |this, cx| {
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(BINARY_DIR);
self.find_worktree(&bin_path, cx) this.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)
}) })
.is_some_and(|entry| entry.is_dir()) .is_some_and(|entry| entry.is_dir())
}) })
})?;
if let Some(toolchain_path) = tool {
return Ok(Some(toolchain_path));
} }
fn find_venv_on_filesystem( let r = this.update(cx, move |_, cx| {
&self, let fs = worktree.read(cx).as_local()?.fs().clone();
abs_path: &Path, let map: Vec<_> = venv_settings
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 .directories
.iter() .iter()
.map(|name| abs_path.join(name)) .map(|name| abs_path.join(name))
.find(|venv_path| { .collect();
let bin_path = venv_path.join(bin_dir_name); 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 // One-time synchronous check is acceptable for terminal/task initialization
smol::block_on(fs.metadata(&bin_path)) // we are within a spawned future anyways
let exists = fs
.metadata(&bin_path)
.await
.ok() .ok()
.flatten() .flatten()
.map_or(false, |meta| meta.is_dir) .map_or(false, |meta| meta.is_dir);
if exists {
return Some(venv_path);
}
}
None
}))
})?;
Ok(match r {
Some(task) => task.await,
None => None,
}) })
} }
@ -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>)>,