Add extract support for zstd (#2861)

We need this to extract toolchain downloads
This commit is contained in:
Zanie Blue 2024-04-08 15:34:08 -05:00 committed by GitHub
parent c46772eec5
commit bdeab55193
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 80 additions and 4 deletions

30
Cargo.lock generated
View File

@ -211,6 +211,8 @@ dependencies = [
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
"zstd",
"zstd-safe",
] ]
[[package]] [[package]]
@ -5382,3 +5384,31 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
"flate2", "flate2",
] ]
[[package]]
name = "zstd"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.10+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
dependencies = [
"cc",
"pkg-config",
]

View File

@ -13,7 +13,7 @@ license = { workspace = true }
workspace = true workspace = true
[dependencies] [dependencies]
async-compression = { workspace = true, features = ["gzip"] } async-compression = { workspace = true, features = ["gzip", "zstd"] }
async_zip = { workspace = true, features = ["tokio"] } async_zip = { workspace = true, features = ["tokio"] }
fs-err = { workspace = true, features = ["tokio"] } fs-err = { workspace = true, features = ["tokio"] }
futures = { workspace = true } futures = { workspace = true }

View File

@ -107,7 +107,22 @@ pub async fn archive<R: tokio::io::AsyncRead + tokio::io::AsyncSeek + Unpin>(
.is_some_and(|ext| ext.eq_ignore_ascii_case("tar")) .is_some_and(|ext| ext.eq_ignore_ascii_case("tar"))
}) })
{ {
crate::stream::untar(reader, target).await?; crate::stream::untar_gz(reader, target).await?;
return Ok(());
}
// `.tar.zst`
if source
.as_ref()
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("zst"))
&& source.as_ref().file_stem().is_some_and(|stem| {
Path::new(stem)
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("tar"))
})
{
crate::stream::untar_zst(reader, target).await?;
return Ok(()); return Ok(());
} }

View File

@ -151,7 +151,7 @@ async fn untar_in<R: tokio::io::AsyncRead + Unpin, P: AsRef<Path>>(
/// Unzip a `.tar.gz` archive into the target directory, without requiring `Seek`. /// Unzip a `.tar.gz` archive into the target directory, without requiring `Seek`.
/// ///
/// This is useful for unpacking files as they're being downloaded. /// This is useful for unpacking files as they're being downloaded.
pub async fn untar<R: tokio::io::AsyncRead + Unpin>( pub async fn untar_gz<R: tokio::io::AsyncRead + Unpin>(
reader: R, reader: R,
target: impl AsRef<Path>, target: impl AsRef<Path>,
) -> Result<(), Error> { ) -> Result<(), Error> {
@ -163,6 +163,22 @@ pub async fn untar<R: tokio::io::AsyncRead + Unpin>(
Ok(untar_in(&mut archive, target.as_ref()).await?) Ok(untar_in(&mut archive, target.as_ref()).await?)
} }
/// Unzip a `.tar.zst` archive into the target directory, without requiring `Seek`.
///
/// This is useful for unpacking files as they're being downloaded.
pub async fn untar_zst<R: tokio::io::AsyncRead + Unpin>(
reader: R,
target: impl AsRef<Path>,
) -> Result<(), Error> {
let reader = tokio::io::BufReader::new(reader);
let decompressed_bytes = async_compression::tokio::bufread::ZstdDecoder::new(reader);
let mut archive = tokio_tar::ArchiveBuilder::new(decompressed_bytes)
.set_preserve_mtime(false)
.build();
Ok(untar_in(&mut archive, target.as_ref()).await?)
}
/// Unzip a `.zip` or `.tar.gz` archive into the target directory, without requiring `Seek`. /// Unzip a `.zip` or `.tar.gz` archive into the target directory, without requiring `Seek`.
pub async fn archive<R: tokio::io::AsyncRead + Unpin>( pub async fn archive<R: tokio::io::AsyncRead + Unpin>(
reader: R, reader: R,
@ -190,7 +206,22 @@ pub async fn archive<R: tokio::io::AsyncRead + Unpin>(
.is_some_and(|ext| ext.eq_ignore_ascii_case("tar")) .is_some_and(|ext| ext.eq_ignore_ascii_case("tar"))
}) })
{ {
untar(reader, target).await?; untar_gz(reader, target).await?;
return Ok(());
}
// `.tar.zst`
if source
.as_ref()
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("zst"))
&& source.as_ref().file_stem().is_some_and(|stem| {
Path::new(stem)
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("tar"))
})
{
untar_zst(reader, target).await?;
return Ok(()); return Ok(());
} }