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

View file

@ -13,7 +13,7 @@ license = { workspace = true }
workspace = true
[dependencies]
async-compression = { workspace = true, features = ["gzip"] }
async-compression = { workspace = true, features = ["gzip", "zstd"] }
async_zip = { workspace = true, features = ["tokio"] }
fs-err = { workspace = true, features = ["tokio"] }
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"))
})
{
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(());
}

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`.
///
/// 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,
target: impl AsRef<Path>,
) -> Result<(), Error> {
@ -163,6 +163,22 @@ pub async fn untar<R: tokio::io::AsyncRead + Unpin>(
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`.
pub async fn archive<R: tokio::io::AsyncRead + Unpin>(
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"))
})
{
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(());
}