@@ -317,8 +317,7 @@ pub struct Package {
317317 name : String ,
318318 vers : String ,
319319 deps : Vec < Dependency > ,
320- files : Vec < ( String , String ) > ,
321- extra_files : Vec < ( String , String ) > ,
320+ files : Vec < PackageFile > ,
322321 yanked : bool ,
323322 features : HashMap < String , Vec < String > > ,
324323 local : bool ,
@@ -342,6 +341,20 @@ pub struct Dependency {
342341 optional : bool ,
343342}
344343
344+ /// A file to be created in a package.
345+ struct PackageFile {
346+ path : String ,
347+ contents : String ,
348+ /// The Unix mode for the file. Note that when extracted on Windows, this
349+ /// is mostly ignored since it doesn't have the same style of permissions.
350+ mode : u32 ,
351+ /// If `true`, the file is created in the root of the tarfile, used for
352+ /// testing invalid packages.
353+ extra : bool ,
354+ }
355+
356+ const DEFAULT_MODE : u32 = 0o644 ;
357+
345358/// Initializes the on-disk registry and sets up the config so that crates.io
346359/// is replaced with the one on disk.
347360pub fn init ( ) {
@@ -379,7 +392,6 @@ impl Package {
379392 vers : vers. to_string ( ) ,
380393 deps : Vec :: new ( ) ,
381394 files : Vec :: new ( ) ,
382- extra_files : Vec :: new ( ) ,
383395 yanked : false ,
384396 features : HashMap :: new ( ) ,
385397 local : false ,
@@ -416,7 +428,17 @@ impl Package {
416428
417429 /// Adds a file to the package.
418430 pub fn file ( & mut self , name : & str , contents : & str ) -> & mut Package {
419- self . files . push ( ( name. to_string ( ) , contents. to_string ( ) ) ) ;
431+ self . file_with_mode ( name, DEFAULT_MODE , contents)
432+ }
433+
434+ /// Adds a file with a specific Unix mode.
435+ pub fn file_with_mode ( & mut self , path : & str , mode : u32 , contents : & str ) -> & mut Package {
436+ self . files . push ( PackageFile {
437+ path : path. to_string ( ) ,
438+ contents : contents. to_string ( ) ,
439+ mode,
440+ extra : false ,
441+ } ) ;
420442 self
421443 }
422444
@@ -425,9 +447,13 @@ impl Package {
425447 /// Normal files are automatically placed within a directory named
426448 /// `$PACKAGE-$VERSION`. This allows you to override that behavior,
427449 /// typically for testing invalid behavior.
428- pub fn extra_file ( & mut self , name : & str , contents : & str ) -> & mut Package {
429- self . extra_files
430- . push ( ( name. to_string ( ) , contents. to_string ( ) ) ) ;
450+ pub fn extra_file ( & mut self , path : & str , contents : & str ) -> & mut Package {
451+ self . files . push ( PackageFile {
452+ path : path. to_string ( ) ,
453+ contents : contents. to_string ( ) ,
454+ mode : DEFAULT_MODE ,
455+ extra : true ,
456+ } ) ;
431457 self
432458 }
433459
@@ -639,19 +665,30 @@ impl Package {
639665 let f = t ! ( File :: create( & dst) ) ;
640666 let mut a = Builder :: new ( GzEncoder :: new ( f, Compression :: default ( ) ) ) ;
641667
642- if !self . files . iter ( ) . any ( |( name, _) | name == "Cargo.toml" ) {
668+ if !self
669+ . files
670+ . iter ( )
671+ . any ( |PackageFile { path, .. } | path == "Cargo.toml" )
672+ {
643673 self . append_manifest ( & mut a) ;
644674 }
645675 if self . files . is_empty ( ) {
646- self . append ( & mut a, "src/lib.rs" , "" ) ;
676+ self . append ( & mut a, "src/lib.rs" , DEFAULT_MODE , "" ) ;
647677 } else {
648- for & ( ref name, ref contents) in self . files . iter ( ) {
649- self . append ( & mut a, name, contents) ;
678+ for PackageFile {
679+ path,
680+ contents,
681+ mode,
682+ extra,
683+ } in & self . files
684+ {
685+ if * extra {
686+ self . append_raw ( & mut a, path, * mode, contents) ;
687+ } else {
688+ self . append ( & mut a, path, * mode, contents) ;
689+ }
650690 }
651691 }
652- for & ( ref name, ref contents) in self . extra_files . iter ( ) {
653- self . append_extra ( & mut a, name, contents) ;
654- }
655692 }
656693
657694 fn append_manifest < W : Write > ( & self , ar : & mut Builder < W > ) {
@@ -704,21 +741,23 @@ impl Package {
704741 manifest. push_str ( "[lib]\n proc-macro = true\n " ) ;
705742 }
706743
707- self . append ( ar, "Cargo.toml" , & manifest) ;
744+ self . append ( ar, "Cargo.toml" , DEFAULT_MODE , & manifest) ;
708745 }
709746
710- fn append < W : Write > ( & self , ar : & mut Builder < W > , file : & str , contents : & str ) {
711- self . append_extra (
747+ fn append < W : Write > ( & self , ar : & mut Builder < W > , file : & str , mode : u32 , contents : & str ) {
748+ self . append_raw (
712749 ar,
713750 & format ! ( "{}-{}/{}" , self . name, self . vers, file) ,
751+ mode,
714752 contents,
715753 ) ;
716754 }
717755
718- fn append_extra < W : Write > ( & self , ar : & mut Builder < W > , path : & str , contents : & str ) {
756+ fn append_raw < W : Write > ( & self , ar : & mut Builder < W > , path : & str , mode : u32 , contents : & str ) {
719757 let mut header = Header :: new_ustar ( ) ;
720758 header. set_size ( contents. len ( ) as u64 ) ;
721759 t ! ( header. set_path( path) ) ;
760+ header. set_mode ( mode) ;
722761 header. set_cksum ( ) ;
723762 t ! ( ar. append( & header, contents. as_bytes( ) ) ) ;
724763 }
0 commit comments