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
|
@ -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,118 +0,0 @@
|
|||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_zip::base::read::stream::ZipFileReader;
|
||||
use futures::{AsyncRead, io::BufReader};
|
||||
|
||||
pub async fn extract_zip<R: AsyncRead + Unpin>(destination: &Path, reader: R) -> Result<()> {
|
||||
let mut reader = ZipFileReader::new(BufReader::new(reader));
|
||||
|
||||
let destination = &destination
|
||||
.canonicalize()
|
||||
.unwrap_or_else(|_| destination.to_path_buf());
|
||||
|
||||
while let Some(mut item) = reader.next_with_entry().await? {
|
||||
let entry_reader = item.reader_mut();
|
||||
let entry = entry_reader.entry();
|
||||
let path = destination.join(entry.filename().as_str().unwrap());
|
||||
|
||||
if entry.dir().unwrap() {
|
||||
std::fs::create_dir_all(&path)?;
|
||||
} else {
|
||||
let parent_dir = path.parent().expect("failed to get parent directory");
|
||||
std::fs::create_dir_all(parent_dir)?;
|
||||
let mut file = smol::fs::File::create(&path).await?;
|
||||
futures::io::copy(entry_reader, &mut file).await?;
|
||||
}
|
||||
|
||||
reader = item.skip().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use async_zip::ZipEntryBuilder;
|
||||
use async_zip::base::write::ZipFileWriter;
|
||||
use futures::AsyncWriteExt;
|
||||
use smol::io::Cursor;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use super::*;
|
||||
|
||||
async fn compress_zip(src_dir: &Path, dst: &Path) -> Result<()> {
|
||||
let mut out = smol::fs::File::create(dst).await?;
|
||||
let mut writer = ZipFileWriter::new(&mut out);
|
||||
|
||||
for entry in walkdir::WalkDir::new(src_dir) {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
if path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let relative_path = path.strip_prefix(src_dir)?;
|
||||
let data = smol::fs::read(&path).await?;
|
||||
|
||||
let filename = relative_path.display().to_string();
|
||||
let builder = ZipEntryBuilder::new(filename.into(), async_zip::Compression::Deflate);
|
||||
|
||||
writer.write_entry_whole(builder, &data).await?;
|
||||
}
|
||||
|
||||
writer.close().await?;
|
||||
out.flush().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn assert_file_content(path: &Path, content: &str) {
|
||||
assert!(path.exists(), "file not found: {:?}", path);
|
||||
let actual = std::fs::read_to_string(path).unwrap();
|
||||
assert_eq!(actual, content);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn make_test_data() -> TempDir {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let dst = dir.path();
|
||||
|
||||
std::fs::write(dst.join("test"), "Hello world.").unwrap();
|
||||
std::fs::create_dir_all(dst.join("foo/bar")).unwrap();
|
||||
std::fs::write(dst.join("foo/bar.txt"), "Foo bar.").unwrap();
|
||||
std::fs::write(dst.join("foo/dar.md"), "Bar dar.").unwrap();
|
||||
std::fs::write(dst.join("foo/bar/dar你好.txt"), "你好世界").unwrap();
|
||||
|
||||
dir
|
||||
}
|
||||
|
||||
async fn read_archive(path: &PathBuf) -> impl AsyncRead + Unpin {
|
||||
let data = smol::fs::read(&path).await.unwrap();
|
||||
Cursor::new(data)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_zip() {
|
||||
let test_dir = make_test_data();
|
||||
let zip_file = test_dir.path().join("test.zip");
|
||||
|
||||
smol::block_on(async {
|
||||
compress_zip(test_dir.path(), &zip_file).await.unwrap();
|
||||
let reader = read_archive(&zip_file).await;
|
||||
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let dst = dir.path();
|
||||
extract_zip(dst, reader).await.unwrap();
|
||||
|
||||
assert_file_content(&dst.join("test"), "Hello world.");
|
||||
assert_file_content(&dst.join("foo/bar.txt"), "Foo bar.");
|
||||
assert_file_content(&dst.join("foo/dar.md"), "Bar dar.");
|
||||
assert_file_content(&dst.join("foo/bar/dar你好.txt"), "你好世界");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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?,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue