1- use std:: fmt:: Display ;
21use std:: path:: { Component , Path , PathBuf } ;
32use std:: pin:: Pin ;
43
54use async_zip:: base:: read:: cd:: Entry ;
65use async_zip:: error:: ZipError ;
7- use async_zip:: { Compression , ZipEntry } ;
86use futures:: { AsyncReadExt , StreamExt } ;
97use rustc_hash:: { FxHashMap , FxHashSet } ;
108use tokio_util:: compat:: { FuturesAsyncReadCompatExt , TokioAsyncReadCompatExt } ;
119use tracing:: { debug, warn} ;
1210
1311use uv_distribution_filename:: SourceDistExtension ;
14- use uv_warnings:: warn_user_once;
1512
1613use crate :: { Error , insecure_no_validate, validate_archive_member_name} ;
1714
@@ -46,24 +43,10 @@ struct ComputedEntry {
4643/// This is useful for unzipping files as they're being downloaded. If the archive
4744/// is already fully on disk, consider using `unzip_archive`, which can use multiple
4845/// threads to work faster in that case.
49- ///
50- /// `source_hint` is used for warning messages, to identify the source of the ZIP archive
51- /// beneath the reader. It might be a URL, a file path, or something else.
52- pub async fn unzip < D : Display , R : tokio:: io:: AsyncRead + Unpin > (
53- source_hint : D ,
46+ pub async fn unzip < R : tokio:: io:: AsyncRead + Unpin > (
5447 reader : R ,
5548 target : impl AsRef < Path > ,
5649) -> Result < ( ) , Error > {
57- /// Returns `true` if the entry uses a well-known compression method.
58- ///
59- /// This currently means just stored (no compression), DEFLATE, or zstd.
60- fn entry_has_well_known_compression ( entry : & ZipEntry ) -> bool {
61- matches ! (
62- entry. compression( ) ,
63- Compression :: Stored | Compression :: Deflate | Compression :: Zstd
64- )
65- }
66-
6750 /// Ensure the file path is safe to use as a [`Path`].
6851 ///
6952 /// See: <https://docs.rs/zip/latest/zip/read/struct.ZipFile.html#method.enclosed_name>
@@ -96,19 +79,8 @@ pub async fn unzip<D: Display, R: tokio::io::AsyncRead + Unpin>(
9679 let mut offset = 0 ;
9780
9881 while let Some ( mut entry) = zip. next_with_entry ( ) . await ? {
99- let zip_entry = entry. reader ( ) . entry ( ) ;
100-
101- // Check for unexpected compression methods.
102- // A future version of uv will reject instead of warning about these.
103- if !entry_has_well_known_compression ( zip_entry) {
104- warn_user_once ! (
105- "One or more file entries in '{source_hint}' use the '{compression_method:?}' compression method, which is not widely supported. A future version of uv will reject ZIP archives containing entries compressed with this method." ,
106- compression_method = zip_entry. compression( )
107- ) ;
108- }
109-
11082 // Construct the (expected) path to the file on-disk.
111- let path = match zip_entry . filename ( ) . as_str ( ) {
83+ let path = match entry . reader ( ) . entry ( ) . filename ( ) . as_str ( ) {
11284 Ok ( path) => path,
11385 Err ( ZipError :: StringNotUtf8 ) => return Err ( Error :: LocalHeaderNotUtf8 { offset } ) ,
11486 Err ( err) => return Err ( err. into ( ) ) ,
@@ -135,14 +107,14 @@ pub async fn unzip<D: Display, R: tokio::io::AsyncRead + Unpin>(
135107 continue ;
136108 } ;
137109
138- let file_offset = zip_entry . file_offset ( ) ;
139- let expected_compressed_size = zip_entry . compressed_size ( ) ;
140- let expected_uncompressed_size = zip_entry . uncompressed_size ( ) ;
141- let expected_data_descriptor = zip_entry . data_descriptor ( ) ;
110+ let file_offset = entry . reader ( ) . entry ( ) . file_offset ( ) ;
111+ let expected_compressed_size = entry . reader ( ) . entry ( ) . compressed_size ( ) ;
112+ let expected_uncompressed_size = entry . reader ( ) . entry ( ) . uncompressed_size ( ) ;
113+ let expected_data_descriptor = entry . reader ( ) . entry ( ) . data_descriptor ( ) ;
142114
143115 // Either create the directory or write the file to disk.
144116 let path = target. join ( & relpath) ;
145- let is_dir = zip_entry . dir ( ) ?;
117+ let is_dir = entry . reader ( ) . entry ( ) . dir ( ) ?;
146118 let computed = if is_dir {
147119 if directories. insert ( path. clone ( ) ) {
148120 fs_err:: tokio:: create_dir_all ( path)
@@ -151,23 +123,23 @@ pub async fn unzip<D: Display, R: tokio::io::AsyncRead + Unpin>(
151123 }
152124
153125 // If this is a directory, we expect the CRC32 to be 0.
154- if zip_entry . crc32 ( ) != 0 {
126+ if entry . reader ( ) . entry ( ) . crc32 ( ) != 0 {
155127 if !skip_validation {
156128 return Err ( Error :: BadCrc32 {
157129 path : relpath. clone ( ) ,
158130 computed : 0 ,
159- expected : zip_entry . crc32 ( ) ,
131+ expected : entry . reader ( ) . entry ( ) . crc32 ( ) ,
160132 } ) ;
161133 }
162134 }
163135
164136 // If this is a directory, we expect the uncompressed size to be 0.
165- if zip_entry . uncompressed_size ( ) != 0 {
137+ if entry . reader ( ) . entry ( ) . uncompressed_size ( ) != 0 {
166138 if !skip_validation {
167139 return Err ( Error :: BadUncompressedSize {
168140 path : relpath. clone ( ) ,
169141 computed : 0 ,
170- expected : zip_entry . uncompressed_size ( ) ,
142+ expected : entry . reader ( ) . entry ( ) . uncompressed_size ( ) ,
171143 } ) ;
172144 }
173145 }
@@ -192,7 +164,7 @@ pub async fn unzip<D: Display, R: tokio::io::AsyncRead + Unpin>(
192164 {
193165 Ok ( file) => {
194166 // Write the file to disk.
195- let size = zip_entry . uncompressed_size ( ) ;
167+ let size = entry . reader ( ) . entry ( ) . uncompressed_size ( ) ;
196168 let mut writer = if let Ok ( size) = usize:: try_from ( size) {
197169 tokio:: io:: BufWriter :: with_capacity ( std:: cmp:: min ( size, 1024 * 1024 ) , file)
198170 } else {
@@ -772,18 +744,14 @@ pub async fn untar<R: tokio::io::AsyncRead + Unpin>(
772744
773745/// Unpack a `.zip`, `.tar.gz`, `.tar.bz2`, `.tar.zst`, or `.tar.xz` archive into the target directory,
774746/// without requiring `Seek`.
775- ///
776- /// `source_hint` is used for warning messages, to identify the source of the archive
777- /// beneath the reader. It might be a URL, a file path, or something else.
778- pub async fn archive < D : Display , R : tokio:: io:: AsyncRead + Unpin > (
779- source_hint : D ,
747+ pub async fn archive < R : tokio:: io:: AsyncRead + Unpin > (
780748 reader : R ,
781749 ext : SourceDistExtension ,
782750 target : impl AsRef < Path > ,
783751) -> Result < ( ) , Error > {
784752 match ext {
785753 SourceDistExtension :: Zip => {
786- unzip ( source_hint , reader, target) . await ?;
754+ unzip ( reader, target) . await ?;
787755 }
788756 SourceDistExtension :: Tar => {
789757 untar ( reader, target) . await ?;
0 commit comments