mirror of
https://github.com/zed-industries/zed.git
synced 2026-07-10 00:13:29 +00:00
Add .tar.bz2 archive support for ACP agent server downloads (#52188)
## Summary - Added `TarBz2` variant to `AssetKind` enum for `.tar.bz2` / `.tbz2` archives - Implemented `extract_tar_bz2` using the `bzip2` feature of `async-compression` (already a workspace dependency, just enabled the feature flag) - Wired up both streaming and file-based extraction paths in `github_download.rs` - Added `.tar.bz2` / `.tbz2` URL detection in both `LocalExtensionArchiveAgent` and `LocalRegistryArchiveAgent` This unblocks ACP registry entries (like Goose) that only ship `.tar.bz2` archives. Reference: https://github.com/block/goose/issues/8047 ## Test plan - [ ] Verify `cargo check` and `clippy` pass (confirmed locally) - [ ] Test downloading an ACP agent that ships a `.tar.bz2` archive (e.g., Goose) - [ ] Verify existing `.tar.gz` and `.zip` agent downloads still work Release Notes: - Added support for `.tar.bz2` archives in ACP agent server downloads, unblocking registry entries like Goose that only ship bzip2-compressed tarballs. --------- Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This commit is contained in:
parent
32161265d3
commit
3d5ec540f3
8 changed files with 52 additions and 12 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
|
@ -2435,6 +2435,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
|
||||
dependencies = [
|
||||
"libbz2-rs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.13+1.0.8"
|
||||
|
|
@ -3465,6 +3474,7 @@ version = "0.4.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23"
|
||||
dependencies = [
|
||||
"bzip2 0.6.1",
|
||||
"compression-core",
|
||||
"deflate64",
|
||||
"flate2",
|
||||
|
|
@ -9706,6 +9716,12 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
||||
|
||||
[[package]]
|
||||
name = "libbz2-rs-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.182"
|
||||
|
|
@ -22447,7 +22463,7 @@ checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
|||
dependencies = [
|
||||
"aes",
|
||||
"byteorder",
|
||||
"bzip2",
|
||||
"bzip2 0.4.4",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ ashpd = { version = "0.13", default-features = false, features = [
|
|||
] }
|
||||
async-channel = "2.5.0"
|
||||
async-compat = "0.2.1"
|
||||
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
|
||||
async-compression = { version = "0.4", features = ["bzip2", "gzip", "futures-io"] }
|
||||
async-dispatcher = "0.1"
|
||||
async-fs = "2.1"
|
||||
async-lock = "2.1"
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ pub async fn get_release_by_tag_name(
|
|||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum AssetKind {
|
||||
TarGz,
|
||||
TarBz2,
|
||||
Gz,
|
||||
Zip,
|
||||
}
|
||||
|
|
@ -158,6 +159,7 @@ pub fn build_asset_url(repo_name_with_owner: &str, tag: &str, kind: AssetKind) -
|
|||
"{tag}.{extension}",
|
||||
extension = match kind {
|
||||
AssetKind::TarGz => "tar.gz",
|
||||
AssetKind::TarBz2 => "tar.bz2",
|
||||
AssetKind::Gz => "gz",
|
||||
AssetKind::Zip => "zip",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use async_compression::futures::bufread::GzipDecoder;
|
||||
use async_compression::futures::bufread::{BzDecoder, GzipDecoder};
|
||||
use futures::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, io::BufReader};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ async fn extract_to_staging(
|
|||
|
||||
fn staging_path(parent: &Path, asset_kind: AssetKind) -> Result<PathBuf> {
|
||||
match asset_kind {
|
||||
AssetKind::TarGz | AssetKind::Zip => {
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Zip => {
|
||||
let dir = tempfile::Builder::new()
|
||||
.prefix(".tmp-github-download-")
|
||||
.tempdir_in(parent)
|
||||
|
|
@ -141,7 +141,7 @@ fn staging_path(parent: &Path, asset_kind: AssetKind) -> Result<PathBuf> {
|
|||
|
||||
async fn cleanup_staging_path(staging_path: &Path, asset_kind: AssetKind) {
|
||||
match asset_kind {
|
||||
AssetKind::TarGz | AssetKind::Zip => {
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Zip => {
|
||||
if let Err(err) = async_fs::remove_dir_all(staging_path).await {
|
||||
log::warn!("failed to remove staging directory {staging_path:?}: {err:?}");
|
||||
}
|
||||
|
|
@ -170,6 +170,7 @@ async fn stream_response_archive(
|
|||
) -> Result<()> {
|
||||
match asset_kind {
|
||||
AssetKind::TarGz => extract_tar_gz(destination_path, url, response).await?,
|
||||
AssetKind::TarBz2 => extract_tar_bz2(destination_path, url, response).await?,
|
||||
AssetKind::Gz => extract_gz(destination_path, url, response).await?,
|
||||
AssetKind::Zip => {
|
||||
util::archive::extract_zip(destination_path, response).await?;
|
||||
|
|
@ -186,6 +187,7 @@ async fn stream_file_archive(
|
|||
) -> Result<()> {
|
||||
match asset_kind {
|
||||
AssetKind::TarGz => extract_tar_gz(destination_path, url, file_archive).await?,
|
||||
AssetKind::TarBz2 => extract_tar_bz2(destination_path, url, file_archive).await?,
|
||||
AssetKind::Gz => extract_gz(destination_path, url, file_archive).await?,
|
||||
#[cfg(not(windows))]
|
||||
AssetKind::Zip => {
|
||||
|
|
@ -213,6 +215,20 @@ async fn extract_tar_gz(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn extract_tar_bz2(
|
||||
destination_path: &Path,
|
||||
url: &str,
|
||||
from: impl AsyncRead + Unpin,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let decompressed_bytes = BzDecoder::new(BufReader::new(from));
|
||||
let archive = async_tar::Archive::new(decompressed_bytes);
|
||||
archive
|
||||
.unpack(&destination_path)
|
||||
.await
|
||||
.with_context(|| format!("extracting {url} to {destination_path:?}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn extract_gz(
|
||||
destination_path: &Path,
|
||||
url: &str,
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ impl LspInstaller for TyLspAdapter {
|
|||
async_fs::create_dir_all(&destination_path).await?;
|
||||
|
||||
let server_path = match Self::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => destination_path
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
|
||||
.join(Self::build_asset_name()?.0)
|
||||
.join("ty"),
|
||||
AssetKind::Zip => destination_path.clone().join("ty.exe"),
|
||||
|
|
@ -538,7 +538,7 @@ impl LspInstaller for TyLspAdapter {
|
|||
|
||||
let path = last.context("no cached binary")?;
|
||||
let path = match TyLspAdapter::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => {
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => {
|
||||
path.join(Self::build_asset_name()?.0).join("ty")
|
||||
}
|
||||
AssetKind::Zip => path.join("ty.exe"),
|
||||
|
|
@ -2520,7 +2520,7 @@ impl LspInstaller for RuffLspAdapter {
|
|||
} = latest_version;
|
||||
let destination_path = container_dir.join(format!("ruff-{name}"));
|
||||
let server_path = match Self::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => destination_path
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
|
||||
.join(Self::build_asset_name()?.0)
|
||||
.join("ruff"),
|
||||
AssetKind::Zip => destination_path.clone().join("ruff.exe"),
|
||||
|
|
@ -2610,7 +2610,7 @@ impl LspInstaller for RuffLspAdapter {
|
|||
|
||||
let path = last.context("no cached binary")?;
|
||||
let path = match Self::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => {
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => {
|
||||
path.join(Self::build_asset_name()?.0).join("ruff")
|
||||
}
|
||||
AssetKind::Zip => path.join("ruff.exe"),
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ impl RustLspAdapter {
|
|||
async fn build_asset_name() -> String {
|
||||
let extension = match Self::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz => "tar.gz",
|
||||
AssetKind::TarBz2 => "tar.bz2",
|
||||
AssetKind::Gz => "gz",
|
||||
AssetKind::Zip => "zip",
|
||||
};
|
||||
|
|
@ -706,7 +707,7 @@ impl LspInstaller for RustLspAdapter {
|
|||
} = version;
|
||||
let destination_path = container_dir.join(format!("rust-analyzer-{name}"));
|
||||
let server_path = match Self::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => destination_path.clone(), // Tar and gzip extract in place.
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path.clone(), // Tar and gzip extract in place.
|
||||
AssetKind::Zip => destination_path.clone().join("rust-analyzer.exe"), // zip contains a .exe
|
||||
};
|
||||
|
||||
|
|
@ -1273,8 +1274,8 @@ async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServ
|
|||
None => return Ok(None),
|
||||
};
|
||||
let path = match RustLspAdapter::GITHUB_ASSET_KIND {
|
||||
AssetKind::TarGz | AssetKind::Gz => path, // Tar and gzip extract in place.
|
||||
AssetKind::Zip => path.join("rust-analyzer.exe"), // zip contains a .exe
|
||||
AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => path, // Tar and gzip extract in place.
|
||||
AssetKind::Zip => path.join("rust-analyzer.exe"), // zip contains a .exe
|
||||
};
|
||||
|
||||
anyhow::Ok(Some(LanguageServerBinary {
|
||||
|
|
|
|||
|
|
@ -1125,6 +1125,8 @@ impl ExternalAgentServer for LocalExtensionArchiveAgent {
|
|||
AssetKind::Zip
|
||||
} else if archive_url.ends_with(".tar.gz") || archive_url.ends_with(".tgz") {
|
||||
AssetKind::TarGz
|
||||
} else if archive_url.ends_with(".tar.bz2") || archive_url.ends_with(".tbz2") {
|
||||
AssetKind::TarBz2
|
||||
} else {
|
||||
anyhow::bail!("unsupported archive type in URL: {}", archive_url);
|
||||
};
|
||||
|
|
@ -1311,6 +1313,8 @@ impl ExternalAgentServer for LocalRegistryArchiveAgent {
|
|||
AssetKind::Zip
|
||||
} else if archive_url.ends_with(".tar.gz") || archive_url.ends_with(".tgz") {
|
||||
AssetKind::TarGz
|
||||
} else if archive_url.ends_with(".tar.bz2") || archive_url.ends_with(".tbz2") {
|
||||
AssetKind::TarBz2
|
||||
} else {
|
||||
anyhow::bail!("unsupported archive type in URL: {}", archive_url);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ accepted = [
|
|||
"OpenSSL",
|
||||
"Zlib",
|
||||
"BSL-1.0",
|
||||
"bzip2-1.0.6",
|
||||
]
|
||||
|
||||
[procinfo.clarify]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue