From 138c3fcfddb6b74d938c8422417b6f02df7bc02d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Sat, 27 Jul 2024 10:00:45 -0400 Subject: [PATCH] http_client: Replace `build_tarball_url` with a more extensible function (#15332) This PR replaces the `build_tarball_url` with `build_asset_url` that accepts an `AssetKind` enum to support downloading different kinds of assets from GitHub. Right now the only asset kind we support is still `.tar.gz`, but the new structure is more amenable to adding more asset kinds. Release Notes: - N/A --- crates/http_client/src/github.rs | 25 +++++++++++++++++-------- crates/languages/src/typescript.rs | 19 ++++++++++++++----- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/crates/http_client/src/github.rs b/crates/http_client/src/github.rs index f4d330090ba7d6b08f64a96ef93e82f3620a69e1..a3293ed2398146ac522d10dc8fe153c86cae8081 100644 --- a/crates/http_client/src/github.rs +++ b/crates/http_client/src/github.rs @@ -117,32 +117,41 @@ pub async fn get_release_by_tag_name( Ok(release) } -pub fn build_tarball_url(repo_name_with_owner: &str, tag: &str) -> Result { +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum AssetKind { + TarGz, +} + +pub fn build_asset_url(repo_name_with_owner: &str, tag: &str, kind: AssetKind) -> Result { let mut url = Url::parse(&format!( "https://github.com/{repo_name_with_owner}/archive/refs/tags", ))?; // We're pushing this here, because tags may contain `/` and other characters // that need to be escaped. - let tarball_filename = format!("{}.tar.gz", tag); + let asset_filename = format!( + "{tag}.{extension}", + extension = match kind { + AssetKind::TarGz => "tar.gz", + } + ); url.path_segments_mut() .map_err(|_| anyhow!("cannot modify url path segments"))? - .push(&tarball_filename); + .push(&asset_filename); Ok(url.to_string()) } #[cfg(test)] mod tests { - use crate::github::build_tarball_url; + use crate::github::{build_asset_url, AssetKind}; #[test] - fn test_build_tarball_url() { + fn test_build_asset_url() { let tag = "release/2.3.5"; let repo_name_with_owner = "microsoft/vscode-eslint"; - let have = build_tarball_url(repo_name_with_owner, tag).unwrap(); - + let tarball = build_asset_url(repo_name_with_owner, tag, AssetKind::TarGz).unwrap(); assert_eq!( - have, + tarball, "https://github.com/microsoft/vscode-eslint/archive/refs/tags/release%2F2.3.5.tar.gz" ); } diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index 0f6b2bfec802ff4334a8e7622848578421a68cb2..46c6a75b848087291791a0209154ecd7e50248aa 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -4,7 +4,7 @@ use async_tar::Archive; use async_trait::async_trait; use collections::HashMap; use gpui::AsyncAppContext; -use http_client::github::{build_tarball_url, GitHubLspBinaryVersion}; +use http_client::github::{build_asset_url, AssetKind, GitHubLspBinaryVersion}; use language::{LanguageServerName, LspAdapter, LspAdapterDelegate}; use lsp::{CodeActionKind, LanguageServerBinary}; use node_runtime::NodeRuntime; @@ -296,6 +296,7 @@ pub struct EsLintLspAdapter { impl EsLintLspAdapter { const CURRENT_VERSION: &'static str = "release/2.4.4"; + const GITHUB_ASSET_KIND: AssetKind = AssetKind::TarGz; const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js"; const SERVER_NAME: &'static str = "eslint"; @@ -406,7 +407,11 @@ impl LspAdapter for EsLintLspAdapter { &self, _delegate: &dyn LspAdapterDelegate, ) -> Result> { - let url = build_tarball_url("microsoft/vscode-eslint", Self::CURRENT_VERSION)?; + let url = build_asset_url( + "microsoft/vscode-eslint", + Self::CURRENT_VERSION, + Self::GITHUB_ASSET_KIND, + )?; Ok(Box::new(GitHubLspBinaryVersion { name: Self::CURRENT_VERSION.into(), @@ -432,9 +437,13 @@ impl LspAdapter for EsLintLspAdapter { .get(&version.url, Default::default(), true) .await .map_err(|err| anyhow!("error downloading release: {}", err))?; - let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut())); - let archive = Archive::new(decompressed_bytes); - archive.unpack(&destination_path).await?; + match Self::GITHUB_ASSET_KIND { + AssetKind::TarGz => { + let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut())); + let archive = Archive::new(decompressed_bytes); + archive.unpack(&destination_path).await?; + } + } let mut dir = fs::read_dir(&destination_path).await?; let first = dir.next().await.ok_or(anyhow!("missing first file"))??;