@@ -25,6 +25,7 @@ use flate2::{Compression, GzBuilder};
25
25
use log:: debug;
26
26
use serde:: Serialize ;
27
27
use tar:: { Archive , Builder , EntryType , Header , HeaderMode } ;
28
+ use unicase:: Ascii as UncasedAscii ;
28
29
29
30
pub struct PackageOpts < ' cfg > {
30
31
pub config : & ' cfg Config ,
@@ -227,70 +228,84 @@ fn build_ar_list(
227
228
src_files : Vec < PathBuf > ,
228
229
vcs_info : Option < VcsInfo > ,
229
230
) -> CargoResult < Vec < ArchiveFile > > {
230
- let mut result = Vec :: new ( ) ;
231
+ let mut result = HashMap :: new ( ) ;
231
232
let root = pkg. root ( ) ;
232
233
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
+ } ) ?;
243
240
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
- }
259
241
"Cargo.lock" => continue ,
260
242
VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow:: bail!(
261
243
"invalid inclusion of reserved file name {} in package source" ,
262
244
rel_str
263
245
) ,
264
246
_ => {
265
- result. push ( ArchiveFile {
266
- rel_path,
267
- rel_str,
268
- contents : FileContents :: OnDisk ( src_file) ,
269
- } ) ;
247
+ result
248
+ . entry ( UncasedAscii :: 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
+ } ) ;
270
255
}
271
256
}
272
257
}
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 ( & UncasedAscii :: new ( "Cargo.toml" ) ) . is_some ( ) {
262
+ result
263
+ . entry ( UncasedAscii :: 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 ( UncasedAscii :: 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 {
274
279
ws. config ( ) . shell ( ) . warn ( & format ! (
275
280
"no `Cargo.toml` file found when packaging `{}` (note the case of the file name)." ,
276
281
pkg. name( )
277
282
) ) ?;
278
283
}
279
284
280
285
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 ( UncasedAscii :: 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
+ } ) ;
286
295
}
287
296
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 ( UncasedAscii :: 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 ( ) ;
294
309
if let Some ( license_file) = & pkg. manifest ( ) . metadata ( ) . license_file {
295
310
let license_path = Path :: new ( license_file) ;
296
311
let abs_file_path = paths:: normalize_path ( & pkg. root ( ) . join ( license_path) ) ;
0 commit comments