mirror of
				https://github.com/astral-sh/uv.git
				synced 2025-11-03 21:23:54 +00:00 
			
		
		
		
	Add extract support for zstd (#2861)
We need this to extract toolchain downloads
This commit is contained in:
		
							parent
							
								
									c46772eec5
								
							
						
					
					
						commit
						bdeab55193
					
				
					 4 changed files with 80 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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 }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue