Fix unzipping clangd and codelldb on Windows (#31080)
Closes https://github.com/zed-industries/zed/pull/30454 Release Notes: - N/A
This commit is contained in:
parent
c8f56e38b1
commit
6e5996a815
19 changed files with 93 additions and 70 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -4056,6 +4056,7 @@ dependencies = [
|
|||
"paths",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"task",
|
||||
"util",
|
||||
"workspace-hack",
|
||||
|
@ -10077,7 +10078,6 @@ dependencies = [
|
|||
"async-tar",
|
||||
"async-trait",
|
||||
"async-watch",
|
||||
"async_zip",
|
||||
"futures 0.3.31",
|
||||
"http_client",
|
||||
"log",
|
||||
|
@ -10086,9 +10086,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"tempfile",
|
||||
"util",
|
||||
"walkdir",
|
||||
"which 6.0.3",
|
||||
"workspace-hack",
|
||||
]
|
||||
|
@ -17030,6 +17028,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs",
|
||||
"async_zip",
|
||||
"collections",
|
||||
"dirs 4.0.0",
|
||||
"dunce",
|
||||
|
@ -17051,6 +17050,7 @@ dependencies = [
|
|||
"tendril",
|
||||
"unicase",
|
||||
"util_macros",
|
||||
"walkdir",
|
||||
"workspace-hack",
|
||||
]
|
||||
|
||||
|
@ -19138,6 +19138,7 @@ dependencies = [
|
|||
"aho-corasick",
|
||||
"anstream",
|
||||
"arrayvec",
|
||||
"async-compression",
|
||||
"async-std",
|
||||
"async-tungstenite",
|
||||
"aws-config",
|
||||
|
|
|
@ -598,7 +598,7 @@ unindent = "0.2.0"
|
|||
url = "2.2"
|
||||
urlencoding = "2.1.2"
|
||||
uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] }
|
||||
walkdir = "2.3"
|
||||
walkdir = "2.5"
|
||||
wasi-preview1-component-adapter-provider = "29"
|
||||
wasm-encoder = "0.221"
|
||||
wasmparser = "0.221"
|
||||
|
|
|
@ -12,7 +12,7 @@ use language::{LanguageName, LanguageToolchainStore};
|
|||
use node_runtime::NodeRuntime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::WorktreeId;
|
||||
use smol::{self, fs::File};
|
||||
use smol::fs::File;
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
ffi::OsStr,
|
||||
|
@ -23,6 +23,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
use task::{AttachRequest, DebugRequest, DebugScenario, LaunchRequest, TcpArgumentsTemplate};
|
||||
use util::archive::extract_zip;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum DapStatus {
|
||||
|
@ -358,17 +359,13 @@ pub async fn download_adapter_from_github(
|
|||
}
|
||||
DownloadedFileType::Zip | DownloadedFileType::Vsix => {
|
||||
let zip_path = version_path.with_extension("zip");
|
||||
|
||||
let mut file = File::create(&zip_path).await?;
|
||||
futures::io::copy(response.body_mut(), &mut file).await?;
|
||||
|
||||
// we cannot check the status as some adapter include files with names that trigger `Illegal byte sequence`
|
||||
util::command::new_smol_command("unzip")
|
||||
.arg(&zip_path)
|
||||
.arg("-d")
|
||||
.arg(&version_path)
|
||||
.output()
|
||||
.await?;
|
||||
let file = File::open(&zip_path).await?;
|
||||
extract_zip(&version_path, BufReader::new(file))
|
||||
.await
|
||||
// we cannot check the status as some adapter include files with names that trigger `Illegal byte sequence`
|
||||
.ok();
|
||||
|
||||
util::fs::remove_matching(&adapter_path, |entry| {
|
||||
entry
|
||||
|
|
|
@ -30,6 +30,7 @@ language.workspace = true
|
|||
paths.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
smol.workspace = true
|
||||
task.workspace = true
|
||||
util.workspace = true
|
||||
workspace-hack.workspace = true
|
||||
|
|
|
@ -136,6 +136,34 @@ impl DebugAdapter for CodeLldbDebugAdapter {
|
|||
};
|
||||
let adapter_dir = version_path.join("extension").join("adapter");
|
||||
let path = adapter_dir.join("codelldb").to_string_lossy().to_string();
|
||||
// todo("windows")
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
use smol::fs;
|
||||
|
||||
fs::set_permissions(
|
||||
&path,
|
||||
<fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755),
|
||||
)
|
||||
.await
|
||||
.with_context(|| format!("Settings executable permissions to {path:?}"))?;
|
||||
|
||||
let lldb_binaries_dir = version_path.join("extension").join("lldb").join("bin");
|
||||
let mut lldb_binaries =
|
||||
fs::read_dir(&lldb_binaries_dir).await.with_context(|| {
|
||||
format!("reading lldb binaries dir contents {lldb_binaries_dir:?}")
|
||||
})?;
|
||||
while let Some(binary) = lldb_binaries.next().await {
|
||||
let binary_entry = binary?;
|
||||
let path = binary_entry.path();
|
||||
fs::set_permissions(
|
||||
&path,
|
||||
<fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755),
|
||||
)
|
||||
.await
|
||||
.with_context(|| format!("Settings executable permissions to {path:?}"))?;
|
||||
}
|
||||
}
|
||||
self.path_to_codelldb.set(path.clone()).ok();
|
||||
command = Some(path);
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
use util::archive::extract_zip;
|
||||
use util::maybe;
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
|
@ -543,9 +544,9 @@ impl ExtensionImports for WasmState {
|
|||
}
|
||||
DownloadedFileType::Zip => {
|
||||
futures::pin_mut!(body);
|
||||
node_runtime::extract_zip(&destination_path, body)
|
||||
extract_zip(&destination_path, body)
|
||||
.await
|
||||
.with_context(|| format!("failed to unzip {} archive", path.display()))?;
|
||||
.with_context(|| format!("unzipping {path:?} archive"))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
use util::maybe;
|
||||
use util::{archive::extract_zip, maybe};
|
||||
use wasmtime::component::{Linker, Resource};
|
||||
|
||||
pub const MIN_VERSION: SemanticVersion = SemanticVersion::new(0, 6, 0);
|
||||
|
@ -906,9 +906,9 @@ impl ExtensionImports for WasmState {
|
|||
}
|
||||
DownloadedFileType::Zip => {
|
||||
futures::pin_mut!(body);
|
||||
node_runtime::extract_zip(&destination_path, body)
|
||||
extract_zip(&destination_path, body)
|
||||
.await
|
||||
.with_context(|| format!("failed to unzip {} archive", path.display()))?;
|
||||
.with_context(|| format!("unzipping {path:?} archive"))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ pub use language::*;
|
|||
use lsp::{DiagnosticTag, InitializeParams, LanguageServerBinary, LanguageServerName};
|
||||
use project::lsp_store::clangd_ext;
|
||||
use serde_json::json;
|
||||
use smol::fs::{self, File};
|
||||
use smol::{fs, io::BufReader};
|
||||
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
|
||||
use util::{ResultExt, fs::remove_matching, maybe, merge_json_value_into};
|
||||
use util::{ResultExt, archive::extract_zip, fs::remove_matching, maybe, merge_json_value_into};
|
||||
|
||||
pub struct CLspAdapter;
|
||||
|
||||
|
@ -32,7 +32,7 @@ impl super::LspAdapter for CLspAdapter {
|
|||
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
|
||||
Some(LanguageServerBinary {
|
||||
path,
|
||||
arguments: vec![],
|
||||
arguments: Vec::new(),
|
||||
env: None,
|
||||
})
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ impl super::LspAdapter for CLspAdapter {
|
|||
delegate: &dyn LspAdapterDelegate,
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
let zip_path = container_dir.join(format!("clangd_{}.zip", version.name));
|
||||
let version_dir = container_dir.join(format!("clangd_{}", version.name));
|
||||
let binary_path = version_dir.join("bin/clangd");
|
||||
|
||||
|
@ -79,28 +78,31 @@ impl super::LspAdapter for CLspAdapter {
|
|||
.get(&version.url, Default::default(), true)
|
||||
.await
|
||||
.context("error downloading release")?;
|
||||
let mut file = File::create(&zip_path).await?;
|
||||
anyhow::ensure!(
|
||||
response.status().is_success(),
|
||||
"download failed with status {}",
|
||||
response.status().to_string()
|
||||
);
|
||||
futures::io::copy(response.body_mut(), &mut file).await?;
|
||||
|
||||
let unzip_status = util::command::new_smol_command("unzip")
|
||||
.current_dir(&container_dir)
|
||||
.arg(&zip_path)
|
||||
.output()
|
||||
.await?
|
||||
.status;
|
||||
anyhow::ensure!(unzip_status.success(), "failed to unzip clangd archive");
|
||||
extract_zip(&container_dir, BufReader::new(response.body_mut()))
|
||||
.await
|
||||
.with_context(|| format!("unzipping clangd archive to {container_dir:?}"))?;
|
||||
remove_matching(&container_dir, |entry| entry != version_dir).await;
|
||||
|
||||
// todo("windows")
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
fs::set_permissions(
|
||||
&binary_path,
|
||||
<fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
env: None,
|
||||
arguments: vec![],
|
||||
arguments: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -306,7 +308,7 @@ impl super::LspAdapter for CLspAdapter {
|
|||
.map(move |diag| {
|
||||
let range =
|
||||
language::range_to_lsp(diag.range.to_point_utf16(&snapshot)).unwrap();
|
||||
let mut tags = vec![];
|
||||
let mut tags = Vec::with_capacity(1);
|
||||
if diag.diagnostic.is_unnecessary {
|
||||
tags.push(DiagnosticTag::UNNECESSARY);
|
||||
}
|
||||
|
@ -344,7 +346,7 @@ async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServ
|
|||
Ok(LanguageServerBinary {
|
||||
path: clangd_bin,
|
||||
env: None,
|
||||
arguments: vec![],
|
||||
arguments: Vec::new(),
|
||||
})
|
||||
})
|
||||
.await
|
||||
|
|
|
@ -26,7 +26,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
use task::{TaskTemplate, TaskTemplates, VariableName};
|
||||
use util::{ResultExt, fs::remove_matching, maybe, merge_json_value_into};
|
||||
use util::{ResultExt, archive::extract_zip, fs::remove_matching, maybe, merge_json_value_into};
|
||||
|
||||
const SERVER_PATH: &str =
|
||||
"node_modules/vscode-langservers-extracted/bin/vscode-json-language-server";
|
||||
|
@ -429,7 +429,7 @@ impl LspAdapter for NodeVersionAdapter {
|
|||
.await
|
||||
.context("downloading release")?;
|
||||
if version.url.ends_with(".zip") {
|
||||
node_runtime::extract_zip(
|
||||
extract_zip(
|
||||
&destination_container_path,
|
||||
BufReader::new(response.body_mut()),
|
||||
)
|
||||
|
|
|
@ -22,6 +22,7 @@ use std::{
|
|||
sync::{Arc, LazyLock},
|
||||
};
|
||||
use task::{TaskTemplate, TaskTemplates, TaskVariables, VariableName};
|
||||
use util::archive::extract_zip;
|
||||
use util::merge_json_value_into;
|
||||
use util::{ResultExt, fs::remove_matching, maybe};
|
||||
|
||||
|
@ -215,14 +216,11 @@ impl LspAdapter for RustLspAdapter {
|
|||
})?;
|
||||
}
|
||||
AssetKind::Zip => {
|
||||
node_runtime::extract_zip(
|
||||
&destination_path,
|
||||
BufReader::new(response.body_mut()),
|
||||
)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("unzipping {} to {:?}", version.url, destination_path)
|
||||
})?;
|
||||
extract_zip(&destination_path, BufReader::new(response.body_mut()))
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("unzipping {} to {:?}", version.url, destination_path)
|
||||
})?;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
use task::{TaskTemplate, TaskTemplates, VariableName};
|
||||
use util::archive::extract_zip;
|
||||
use util::{ResultExt, fs::remove_matching, maybe};
|
||||
|
||||
pub(super) fn typescript_task_context() -> ContextProviderWithTasks {
|
||||
|
@ -514,14 +515,11 @@ impl LspAdapter for EsLintLspAdapter {
|
|||
})?;
|
||||
}
|
||||
AssetKind::Zip => {
|
||||
node_runtime::extract_zip(
|
||||
&destination_path,
|
||||
BufReader::new(response.body_mut()),
|
||||
)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("unzipping {} to {:?}", version.url, destination_path)
|
||||
})?;
|
||||
extract_zip(&destination_path, BufReader::new(response.body_mut()))
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("unzipping {} to {:?}", version.url, destination_path)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ path = "src/node_runtime.rs"
|
|||
doctest = false
|
||||
|
||||
[features]
|
||||
test-support = ["tempfile"]
|
||||
test-support = []
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
|
@ -21,7 +21,6 @@ async-compression.workspace = true
|
|||
async-watch.workspace = true
|
||||
async-tar.workspace = true
|
||||
async-trait.workspace = true
|
||||
async_zip.workspace = true
|
||||
futures.workspace = true
|
||||
http_client.workspace = true
|
||||
log.workspace = true
|
||||
|
@ -30,14 +29,9 @@ semver.workspace = true
|
|||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
smol.workspace = true
|
||||
tempfile = { workspace = true, optional = true }
|
||||
util.workspace = true
|
||||
walkdir = "2.5.0"
|
||||
which.workspace = true
|
||||
workspace-hack.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
async-std = { version = "1.12.0", features = ["unstable"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile.workspace = true
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
mod archive;
|
||||
|
||||
use anyhow::{Context as _, Result, anyhow, bail};
|
||||
pub use archive::extract_zip;
|
||||
use async_compression::futures::bufread::GzipDecoder;
|
||||
use async_tar::Archive;
|
||||
use futures::{AsyncReadExt, FutureExt as _, channel::oneshot, future::Shared};
|
||||
|
@ -19,6 +16,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use util::archive::extract_zip;
|
||||
|
||||
const NODE_CA_CERTS_ENV_VAR: &str = "NODE_EXTRA_CA_CERTS";
|
||||
|
||||
|
@ -353,7 +351,7 @@ impl ManagedNodeRuntime {
|
|||
let archive = Archive::new(decompressed_bytes);
|
||||
archive.unpack(&node_containing_dir).await?;
|
||||
}
|
||||
ArchiveType::Zip => archive::extract_zip(&node_containing_dir, body).await?,
|
||||
ArchiveType::Zip => extract_zip(&node_containing_dir, body).await?,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -348,11 +348,11 @@ impl LocalLspStore {
|
|||
delegate.update_status(
|
||||
adapter.name(),
|
||||
BinaryStatus::Failed {
|
||||
error: format!("{err}\n-- stderr--\n{}", log),
|
||||
error: format!("{err}\n-- stderr--\n{log}"),
|
||||
},
|
||||
);
|
||||
log::error!("Failed to start language server {server_name:?}: {err}");
|
||||
log::error!("server stderr: {:?}", log);
|
||||
log::error!("Failed to start language server {server_name:?}: {err:#?}");
|
||||
log::error!("server stderr: {log}");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use anyhow::Result;
|
|||
use collections::HashMap;
|
||||
use fs::Fs;
|
||||
use gpui::{App, AppContext as _, Context, Entity, Task};
|
||||
use util::ResultExt;
|
||||
use util::{ResultExt, archive::extract_zip};
|
||||
|
||||
pub(crate) struct YarnPathStore {
|
||||
temp_dirs: HashMap<Arc<Path>, tempfile::TempDir>,
|
||||
|
@ -131,7 +131,7 @@ fn zip_path(path: &Path) -> Option<&Path> {
|
|||
async fn dump_zip(path: Arc<Path>, fs: Arc<dyn Fs>) -> Result<tempfile::TempDir> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
let contents = fs.load_bytes(&path).await?;
|
||||
node_runtime::extract_zip(dir.path(), futures::io::Cursor::new(contents)).await?;
|
||||
extract_zip(dir.path(), futures::io::Cursor::new(contents)).await?;
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ test-support = ["tempfile", "git2", "rand", "util_macros"]
|
|||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
async-fs.workspace = true
|
||||
async_zip.workspace = true
|
||||
collections.workspace = true
|
||||
dirs.workspace = true
|
||||
futures-lite.workspace = true
|
||||
|
@ -36,6 +37,7 @@ take-until.workspace = true
|
|||
tempfile = { workspace = true, optional = true }
|
||||
unicase.workspace = true
|
||||
util_macros = { workspace = true, optional = true }
|
||||
walkdir.workspace = true
|
||||
workspace-hack.workspace = true
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod arc_cow;
|
||||
pub mod archive;
|
||||
pub mod command;
|
||||
pub mod fs;
|
||||
pub mod markdown;
|
||||
|
|
|
@ -19,6 +19,7 @@ ahash = { version = "0.8", features = ["serde"] }
|
|||
aho-corasick = { version = "1" }
|
||||
anstream = { version = "0.6" }
|
||||
arrayvec = { version = "0.7", features = ["serde"] }
|
||||
async-compression = { version = "0.4", default-features = false, features = ["deflate", "deflate64", "futures-io", "gzip"] }
|
||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
||||
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
||||
|
@ -145,6 +146,7 @@ ahash = { version = "0.8", features = ["serde"] }
|
|||
aho-corasick = { version = "1" }
|
||||
anstream = { version = "0.6" }
|
||||
arrayvec = { version = "0.7", features = ["serde"] }
|
||||
async-compression = { version = "0.4", default-features = false, features = ["deflate", "deflate64", "futures-io", "gzip"] }
|
||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
||||
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue