@@ -25,6 +25,7 @@ use flate2::{Compression, GzBuilder};
2525use log:: debug;
2626use serde:: Serialize ;
2727use tar:: { Archive , Builder , EntryType , Header , HeaderMode } ;
28+ use unicase:: UniCase ;
2829
2930pub struct PackageOpts < ' cfg > {
3031 pub config : & ' cfg Config ,
@@ -227,70 +228,84 @@ fn build_ar_list(
227228 src_files : Vec < PathBuf > ,
228229 vcs_info : Option < VcsInfo > ,
229230) -> CargoResult < Vec < ArchiveFile > > {
230- let mut result = Vec :: new ( ) ;
231+ let mut result = HashMap :: new ( ) ;
231232 let root = pkg. root ( ) ;
232233
233- let mut manifest_found = false ;
234- for src_file in src_files {
235- let rel_path = src_file. strip_prefix ( & root) ?. to_path_buf ( ) ;
236- check_filename ( & rel_path, & mut ws. config ( ) . shell ( ) ) ?;
237- let rel_str = rel_path
238- . to_str ( )
239- . ok_or_else ( || {
240- anyhow:: format_err!( "non-utf8 path in source directory: {}" , rel_path. display( ) )
241- } ) ?
242- . to_string ( ) ;
234+ for src_file in & src_files {
235+ let rel_path = src_file. strip_prefix ( & root) ?;
236+ check_filename ( rel_path, & mut ws. config ( ) . shell ( ) ) ?;
237+ let rel_str = rel_path. to_str ( ) . ok_or_else ( || {
238+ anyhow:: format_err!( "non-utf8 path in source directory: {}" , rel_path. display( ) )
239+ } ) ?;
243240 match rel_str. as_ref ( ) {
244- "Cargo.toml" |
245- // normalize for case insensitive filesystems (like on Windows)
246- "cargo.toml" => {
247- manifest_found = true ;
248- result. push ( ArchiveFile {
249- rel_path : PathBuf :: from ( ORIGINAL_MANIFEST_FILE ) ,
250- rel_str : ORIGINAL_MANIFEST_FILE . to_string ( ) ,
251- contents : FileContents :: OnDisk ( src_file) ,
252- } ) ;
253- result. push ( ArchiveFile {
254- rel_path : PathBuf :: from ( "Cargo.toml" ) ,
255- rel_str : "Cargo.toml" . to_string ( ) ,
256- contents : FileContents :: Generated ( GeneratedFile :: Manifest ) ,
257- } ) ;
258- }
259241 "Cargo.lock" => continue ,
260242 VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow:: bail!(
261243 "invalid inclusion of reserved file name {} in package source" ,
262244 rel_str
263245 ) ,
264246 _ => {
265- result. push ( ArchiveFile {
266- rel_path,
267- rel_str,
268- contents : FileContents :: OnDisk ( src_file) ,
269- } ) ;
247+ result
248+ . entry ( UniCase :: new ( rel_str) )
249+ . or_insert_with ( Vec :: new)
250+ . push ( ArchiveFile {
251+ rel_path : rel_path. to_owned ( ) ,
252+ rel_str : rel_str. to_owned ( ) ,
253+ contents : FileContents :: OnDisk ( src_file. clone ( ) ) ,
254+ } ) ;
270255 }
271256 }
272257 }
273- if !manifest_found {
258+
259+ // Ensure we normalize for case insensitive filesystems (like on Windows) by removing the
260+ // existing entry, regardless of case, and adding in with the correct case
261+ if result. remove ( & UniCase :: new ( "Cargo.toml" ) ) . is_some ( ) {
262+ result
263+ . entry ( UniCase :: new ( ORIGINAL_MANIFEST_FILE ) )
264+ . or_insert_with ( Vec :: new)
265+ . push ( ArchiveFile {
266+ rel_path : PathBuf :: from ( ORIGINAL_MANIFEST_FILE ) ,
267+ rel_str : ORIGINAL_MANIFEST_FILE . to_string ( ) ,
268+ contents : FileContents :: OnDisk ( pkg. manifest_path ( ) . to_owned ( ) ) ,
269+ } ) ;
270+ result
271+ . entry ( UniCase :: new ( "Cargo.toml" ) )
272+ . or_insert_with ( Vec :: new)
273+ . push ( ArchiveFile {
274+ rel_path : PathBuf :: from ( "Cargo.toml" ) ,
275+ rel_str : "Cargo.toml" . to_string ( ) ,
276+ contents : FileContents :: Generated ( GeneratedFile :: Manifest ) ,
277+ } ) ;
278+ } else {
274279 ws. config ( ) . shell ( ) . warn ( & format ! (
275280 "no `Cargo.toml` file found when packaging `{}` (note the case of the file name)." ,
276281 pkg. name( )
277282 ) ) ?;
278283 }
279284
280285 if pkg. include_lockfile ( ) {
281- result. push ( ArchiveFile {
282- rel_path : PathBuf :: from ( "Cargo.lock" ) ,
283- rel_str : "Cargo.lock" . to_string ( ) ,
284- contents : FileContents :: Generated ( GeneratedFile :: Lockfile ) ,
285- } ) ;
286+ let rel_str = "Cargo.lock" ;
287+ result
288+ . entry ( UniCase :: new ( rel_str) )
289+ . or_insert_with ( Vec :: new)
290+ . push ( ArchiveFile {
291+ rel_path : PathBuf :: from ( rel_str) ,
292+ rel_str : rel_str. to_string ( ) ,
293+ contents : FileContents :: Generated ( GeneratedFile :: Lockfile ) ,
294+ } ) ;
286295 }
287296 if let Some ( vcs_info) = vcs_info {
288- result. push ( ArchiveFile {
289- rel_path : PathBuf :: from ( VCS_INFO_FILE ) ,
290- rel_str : VCS_INFO_FILE . to_string ( ) ,
291- contents : FileContents :: Generated ( GeneratedFile :: VcsInfo ( vcs_info) ) ,
292- } ) ;
293- }
297+ let rel_str = VCS_INFO_FILE ;
298+ result
299+ . entry ( UniCase :: new ( rel_str) )
300+ . or_insert_with ( Vec :: new)
301+ . push ( ArchiveFile {
302+ rel_path : PathBuf :: from ( rel_str) ,
303+ rel_str : rel_str. to_string ( ) ,
304+ contents : FileContents :: Generated ( GeneratedFile :: VcsInfo ( vcs_info) ) ,
305+ } ) ;
306+ }
307+
308+ let mut result = result. into_values ( ) . flatten ( ) . collect ( ) ;
294309 if let Some ( license_file) = & pkg. manifest ( ) . metadata ( ) . license_file {
295310 let license_path = Path :: new ( license_file) ;
296311 let abs_file_path = paths:: normalize_path ( & pkg. root ( ) . join ( license_path) ) ;
0 commit comments