Detailed changes
@@ -1,4 +1,4 @@
-use std::{path::Path, pin::Pin, task::Poll};
+use std::{future::Future, path::Path, pin::Pin, task::Poll};
use anyhow::{Context, Result};
use async_compression::futures::bufread::GzipDecoder;
@@ -85,6 +85,65 @@ pub async fn download_server_binary(
Ok(())
}
+pub async fn fetch_github_binary_with_digest_check<ValidityCheck, ValidityCheckFuture>(
+ binary_path: &Path,
+ metadata_path: &Path,
+ expected_digest: Option<String>,
+ url: &str,
+ asset_kind: AssetKind,
+ download_destination: &Path,
+ http_client: &dyn HttpClient,
+ validity_check: ValidityCheck,
+) -> Result<()>
+where
+ ValidityCheck: FnOnce() -> ValidityCheckFuture,
+ ValidityCheckFuture: Future<Output = Result<()>>,
+{
+ let metadata = GithubBinaryMetadata::read_from_file(metadata_path)
+ .await
+ .ok();
+
+ if let Some(metadata) = metadata {
+ let validity_check_result = validity_check().await;
+
+ if let (Some(actual_digest), Some(expected_digest_ref)) =
+ (&metadata.digest, &expected_digest)
+ {
+ if actual_digest == expected_digest_ref {
+ if validity_check_result.is_ok() {
+ return Ok(());
+ }
+ } else {
+ log::info!(
+ "SHA-256 mismatch for {binary_path:?} asset, downloading new asset. Expected: {expected_digest_ref}, Got: {actual_digest}"
+ );
+ }
+ } else if validity_check_result.is_ok() {
+ return Ok(());
+ }
+ }
+
+ download_server_binary(
+ http_client,
+ url,
+ expected_digest.as_deref(),
+ download_destination,
+ asset_kind,
+ )
+ .await?;
+
+ GithubBinaryMetadata::write_to_file(
+ &GithubBinaryMetadata {
+ metadata_version: 1,
+ digest: expected_digest,
+ },
+ metadata_path,
+ )
+ .await?;
+
+ Ok(())
+}
+
async fn stream_response_archive(
response: impl AsyncRead + Unpin,
url: &str,
@@ -3,7 +3,7 @@ use async_trait::async_trait;
use futures::StreamExt;
use gpui::{App, AsyncApp};
use http_client::github::{AssetKind, GitHubLspBinaryVersion, latest_github_release};
-use http_client::github_download::{GithubBinaryMetadata, download_server_binary};
+use http_client::github_download::fetch_github_binary_with_digest_check;
pub use language::*;
use lsp::{InitializeParams, LanguageServerBinary, LanguageServerName};
use project::lsp_store::clangd_ext;
@@ -85,56 +85,33 @@ impl LspInstaller for CLspAdapter {
};
let metadata_path = version_dir.join("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
+
+ let binary_path_for_check = binary_path.clone();
+ fetch_github_binary_with_digest_check(
+ &binary_path,
+ &metadata_path,
+ expected_digest,
+ &url,
+ AssetKind::Zip,
+ &container_dir,
+ &*delegate.http_client(),
+ || async move {
delegate
.try_exec(LanguageServerBinary {
- path: binary_path.clone(),
+ path: binary_path_for_check,
arguments: vec!["--version".into()],
env: None,
})
.await
.inspect_err(|err| {
- log::warn!("Unable to run {binary_path:?} asset, redownloading: {err:#}",)
+ log::warn!("Unable to run clangd asset, redownloading: {err:#}")
})
- };
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
- }
- } else {
- log::info!(
- "SHA-256 mismatch for {binary_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
- }
- } else if validity_check().await.is_ok() {
- return Ok(binary);
- }
- }
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &container_dir,
- AssetKind::Zip,
- )
- .await?;
- remove_matching(&container_dir, |entry| entry != version_dir).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
},
- &metadata_path,
)
.await?;
+ remove_matching(&container_dir, |entry| entry != version_dir).await;
+
Ok(binary)
}
@@ -5,7 +5,7 @@ use futures::StreamExt;
use gpui::{App, AppContext, AsyncApp, SharedString, Task};
use http_client::github::AssetKind;
use http_client::github::{GitHubLspBinaryVersion, latest_github_release};
-use http_client::github_download::{GithubBinaryMetadata, download_server_binary};
+use http_client::github_download::fetch_github_binary_with_digest_check;
pub use language::*;
use lsp::{InitializeParams, LanguageServerBinary};
use project::lsp_store::rust_analyzer_ext::CARGO_DIAGNOSTICS_SOURCE_NAME;
@@ -514,64 +514,34 @@ impl LspInstaller for RustLspAdapter {
AssetKind::Zip => destination_path.clone().join("rust-analyzer.exe"), // zip contains a .exe
};
- let binary = LanguageServerBinary {
- path: server_path.clone(),
- env: None,
- arguments: Default::default(),
- };
-
let metadata_path = destination_path.with_extension("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
+
+ let server_path_for_check = server_path.clone();
+ fetch_github_binary_with_digest_check(
+ &server_path,
+ &metadata_path,
+ expected_digest,
+ &url,
+ Self::GITHUB_ASSET_KIND,
+ &destination_path,
+ &*delegate.http_client(),
+ || async move {
delegate
.try_exec(LanguageServerBinary {
- path: server_path.clone(),
+ path: server_path_for_check,
arguments: vec!["--version".into()],
env: None,
})
.await
.inspect_err(|err| {
- log::warn!("Unable to run {server_path:?} asset, redownloading: {err:#}",)
+ log::warn!("Unable to run rust-analyzer asset, redownloading: {err:#}")
})
- };
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
- }
- } else {
- log::info!(
- "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
- }
- } else if validity_check().await.is_ok() {
- return Ok(binary);
- }
- }
-
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &destination_path,
- Self::GITHUB_ASSET_KIND,
+ },
)
.await?;
+
make_file_executable(&server_path).await?;
remove_matching(&container_dir, |path| path != destination_path).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
- },
- &metadata_path,
- )
- .await?;
Ok(LanguageServerBinary {
path: server_path,