@@ -333,24 +333,6 @@ pub async fn download_adapter_from_github(
Ok(version_path)
}
-pub async fn fetch_latest_adapter_version_from_github(
- github_repo: GithubRepo,
- delegate: &dyn DapDelegate,
-) -> Result<AdapterVersion> {
- let release = latest_github_release(
- &format!("{}/{}", github_repo.repo_owner, github_repo.repo_name),
- false,
- false,
- delegate.http_client(),
- )
- .await?;
-
- Ok(AdapterVersion {
- tag_name: release.tag_name,
- url: release.zipball_url,
- })
-}
-
#[async_trait(?Send)]
pub trait DebugAdapter: 'static + Send + Sync {
fn name(&self) -> DebugAdapterName;
@@ -1,7 +1,8 @@
use crate::*;
use anyhow::Context as _;
+use dap::adapters::latest_github_release;
use dap::{DebugRequest, StartDebuggingRequestArguments, adapters::DebugTaskDefinition};
-use gpui::{AsyncApp, SharedString};
+use gpui::{AppContext, AsyncApp, SharedString};
use json_dotpath::DotPaths;
use language::{LanguageName, Toolchain};
use serde_json::Value;
@@ -21,12 +22,13 @@ pub(crate) struct PythonDebugAdapter {
impl PythonDebugAdapter {
const ADAPTER_NAME: &'static str = "Debugpy";
+ const DEBUG_ADAPTER_NAME: DebugAdapterName =
+ DebugAdapterName(SharedString::new_static(Self::ADAPTER_NAME));
const ADAPTER_PACKAGE_NAME: &'static str = "debugpy";
const ADAPTER_PATH: &'static str = "src/debugpy/adapter";
const LANGUAGE_NAME: &'static str = "Python";
async fn generate_debugpy_arguments(
- &self,
host: &Ipv4Addr,
port: u16,
user_installed_path: Option<&Path>,
@@ -54,7 +56,7 @@ impl PythonDebugAdapter {
format!("--port={}", port),
])
} else {
- let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
+ let adapter_path = paths::debug_adapters_dir().join(Self::DEBUG_ADAPTER_NAME.as_ref());
let file_name_prefix = format!("{}_", Self::ADAPTER_NAME);
let debugpy_dir =
@@ -107,22 +109,21 @@ impl PythonDebugAdapter {
repo_owner: "microsoft".into(),
};
- adapters::fetch_latest_adapter_version_from_github(github_repo, delegate.as_ref()).await
+ fetch_latest_adapter_version_from_github(github_repo, delegate.as_ref()).await
}
async fn install_binary(
- &self,
+ adapter_name: DebugAdapterName,
version: AdapterVersion,
- delegate: &Arc<dyn DapDelegate>,
+ delegate: Arc<dyn DapDelegate>,
) -> Result<()> {
let version_path = adapters::download_adapter_from_github(
- self.name(),
+ adapter_name,
version,
- adapters::DownloadedFileType::Zip,
+ adapters::DownloadedFileType::GzipTar,
delegate.as_ref(),
)
.await?;
-
// only needed when you install the latest version for the first time
if let Some(debugpy_dir) =
util::fs::find_file_name_in_dir(version_path.as_path(), |file_name| {
@@ -171,14 +172,13 @@ impl PythonDebugAdapter {
let python_command = python_path.context("failed to find binary path for Python")?;
log::debug!("Using Python executable: {}", python_command);
- let arguments = self
- .generate_debugpy_arguments(
- &host,
- port,
- user_installed_path.as_deref(),
- installed_in_venv,
- )
- .await?;
+ let arguments = Self::generate_debugpy_arguments(
+ &host,
+ port,
+ user_installed_path.as_deref(),
+ installed_in_venv,
+ )
+ .await?;
log::debug!(
"Starting debugpy adapter with command: {} {}",
@@ -204,7 +204,7 @@ impl PythonDebugAdapter {
#[async_trait(?Send)]
impl DebugAdapter for PythonDebugAdapter {
fn name(&self) -> DebugAdapterName {
- DebugAdapterName(Self::ADAPTER_NAME.into())
+ Self::DEBUG_ADAPTER_NAME
}
fn adapter_language_name(&self) -> Option<LanguageName> {
@@ -635,7 +635,9 @@ impl DebugAdapter for PythonDebugAdapter {
if self.checked.set(()).is_ok() {
delegate.output_to_console(format!("Checking latest version of {}...", self.name()));
if let Some(version) = self.fetch_latest_adapter_version(delegate).await.log_err() {
- self.install_binary(version, delegate).await?;
+ cx.background_spawn(Self::install_binary(self.name(), version, delegate.clone()))
+ .await
+ .context("Failed to install debugpy")?;
}
}
@@ -644,6 +646,24 @@ impl DebugAdapter for PythonDebugAdapter {
}
}
+async fn fetch_latest_adapter_version_from_github(
+ github_repo: GithubRepo,
+ delegate: &dyn DapDelegate,
+) -> Result<AdapterVersion> {
+ let release = latest_github_release(
+ &format!("{}/{}", github_repo.repo_owner, github_repo.repo_name),
+ false,
+ false,
+ delegate.http_client(),
+ )
+ .await?;
+
+ Ok(AdapterVersion {
+ tag_name: release.tag_name,
+ url: release.tarball_url,
+ })
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -651,20 +671,18 @@ mod tests {
#[gpui::test]
async fn test_debugpy_install_path_cases() {
- let adapter = PythonDebugAdapter::default();
let host = Ipv4Addr::new(127, 0, 0, 1);
let port = 5678;
// Case 1: User-defined debugpy path (highest precedence)
let user_path = PathBuf::from("/custom/path/to/debugpy");
- let user_args = adapter
- .generate_debugpy_arguments(&host, port, Some(&user_path), false)
- .await
- .unwrap();
+ let user_args =
+ PythonDebugAdapter::generate_debugpy_arguments(&host, port, Some(&user_path), false)
+ .await
+ .unwrap();
// Case 2: Venv-installed debugpy (uses -m debugpy.adapter)
- let venv_args = adapter
- .generate_debugpy_arguments(&host, port, None, true)
+ let venv_args = PythonDebugAdapter::generate_debugpy_arguments(&host, port, None, true)
.await
.unwrap();
@@ -679,9 +697,4 @@ mod tests {
// Note: Case 3 (GitHub-downloaded debugpy) is not tested since this requires mocking the Github API.
}
-
- #[test]
- fn test_adapter_path_constant() {
- assert_eq!(PythonDebugAdapter::ADAPTER_PATH, "src/debugpy/adapter");
- }
}