11//! Gets metadata about a workspace from Cargo
22
3- use std:: collections:: { BTreeMap , BTreeSet } ;
3+ use std:: collections:: BTreeMap ;
44use std:: ffi:: { OsStr , OsString } ;
55use std:: path:: Path ;
66
@@ -23,13 +23,18 @@ pub enum Error {
2323 RunningVendor ,
2424}
2525
26- /// Describes one of our dependencies
26+ /// Uniquely describes a package on crates.io
2727#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
28- pub struct Dependency {
28+ pub struct Package {
2929 /// The name of the package
3030 pub name : String ,
3131 /// The version number
3232 pub version : String ,
33+ }
34+
35+ /// Extra data about a package
36+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
37+ pub struct PackageMetadata {
3338 /// The license it is under
3439 pub license : String ,
3540 /// The list of authors from the package metadata
@@ -40,20 +45,44 @@ pub struct Dependency {
4045 pub notices : BTreeMap < OsString , String > ,
4146}
4247
43- /// Use `cargo` to get a list of dependencies and their license data.
48+ /// Use `cargo metadata` and `cargo vendor ` to get a list of dependencies and their license data.
4449///
4550/// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can
4651/// grab the license files.
4752///
4853/// Any dependency with a path beginning with `root_path` is ignored, as we
4954/// assume `reuse` has covered it already.
50- pub fn get (
55+ pub fn get_metadata_and_notices (
5156 cargo : & Path ,
5257 dest : & Path ,
5358 root_path : & Path ,
5459 manifest_paths : & [ & Path ] ,
55- ) -> Result < BTreeSet < Dependency > , Error > {
56- let mut temp_set = BTreeSet :: new ( ) ;
60+ ) -> Result < BTreeMap < Package , PackageMetadata > , Error > {
61+ let mut output = get_metadata ( cargo, root_path, manifest_paths) ?;
62+
63+ // Now do a cargo-vendor and grab everything
64+ let vendor_path = dest. join ( "vendor" ) ;
65+ println ! ( "Vendoring deps into {}..." , vendor_path. display( ) ) ;
66+ run_cargo_vendor ( cargo, & vendor_path, manifest_paths) ?;
67+
68+ // Now for each dependency we found, go and grab any important looking files
69+ for ( package, metadata) in output. iter_mut ( ) {
70+ load_important_files ( package, metadata, & vendor_path) ?;
71+ }
72+
73+ Ok ( output)
74+ }
75+
76+ /// Use `cargo metadata` to get a list of dependencies and their license data.
77+ ///
78+ /// Any dependency with a path beginning with `root_path` is ignored, as we
79+ /// assume `reuse` has covered it already.
80+ pub fn get_metadata (
81+ cargo : & Path ,
82+ root_path : & Path ,
83+ manifest_paths : & [ & Path ] ,
84+ ) -> Result < BTreeMap < Package , PackageMetadata > , Error > {
85+ let mut output = BTreeMap :: new ( ) ;
5786 // Look at the metadata for each manifest
5887 for manifest_path in manifest_paths {
5988 if manifest_path. file_name ( ) != Some ( OsStr :: new ( "Cargo.toml" ) ) {
@@ -71,7 +100,7 @@ pub fn get(
71100 . and_then ( |v| v. as_str ( ) )
72101 . map ( Path :: new)
73102 . ok_or_else ( || Error :: MissingJsonElement ( "package.manifest_path" ) ) ?;
74- if manifest_path. starts_with ( & root_path) {
103+ if manifest_path. starts_with ( root_path) {
75104 // it's an in-tree dependency and reuse covers it
76105 continue ;
77106 }
@@ -93,28 +122,14 @@ pub fn get(
93122 . ok_or_else ( || Error :: MissingJsonElement ( "package.authors" ) ) ?;
94123 let authors: Vec < String > =
95124 authors_list. iter ( ) . filter_map ( |v| v. as_str ( ) ) . map ( |s| s. to_owned ( ) ) . collect ( ) ;
96- temp_set. insert ( Dependency {
97- name : name. to_owned ( ) ,
98- version : version. to_owned ( ) ,
99- license : license. to_owned ( ) ,
100- authors,
101- notices : BTreeMap :: new ( ) ,
102- } ) ;
125+ let package = Package { name : name. to_owned ( ) , version : version. to_owned ( ) } ;
126+ output. insert (
127+ package. clone ( ) ,
128+ PackageMetadata { license : license. to_owned ( ) , authors, notices : BTreeMap :: new ( ) } ,
129+ ) ;
103130 }
104131 }
105132
106- // Now do a cargo-vendor and grab everything
107- let vendor_path = dest. join ( "vendor" ) ;
108- println ! ( "Vendoring deps into {}..." , vendor_path. display( ) ) ;
109- run_cargo_vendor ( cargo, & vendor_path, manifest_paths) ?;
110-
111- // Now for each dependency we found, go and grab any important looking files
112- let mut output = BTreeSet :: new ( ) ;
113- for mut dep in temp_set {
114- load_important_files ( & mut dep, & vendor_path) ?;
115- output. insert ( dep) ;
116- }
117-
118133 Ok ( output)
119134}
120135
@@ -128,7 +143,7 @@ fn get_metadata_json(cargo: &Path, manifest_path: &Path) -> Result<serde_json::V
128143 . arg ( manifest_path)
129144 . env ( "RUSTC_BOOTSTRAP" , "1" )
130145 . output ( )
131- . map_err ( |e| Error :: LaunchingMetadata ( e ) ) ?;
146+ . map_err ( Error :: LaunchingMetadata ) ?;
132147 if !metadata_output. status . success ( ) {
133148 return Err ( Error :: GettingMetadata (
134149 String :: from_utf8 ( metadata_output. stderr ) . expect ( "UTF-8 output from cargo" ) ,
@@ -151,7 +166,7 @@ fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Resu
151166 }
152167 vendor_command. arg ( dest) ;
153168
154- let vendor_status = vendor_command. status ( ) . map_err ( |e| Error :: LaunchingVendor ( e ) ) ?;
169+ let vendor_status = vendor_command. status ( ) . map_err ( Error :: LaunchingVendor ) ?;
155170
156171 if !vendor_status. success ( ) {
157172 return Err ( Error :: RunningVendor ) ;
@@ -164,8 +179,12 @@ fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Resu
164179///
165180/// Maybe one-day Cargo.toml will contain enough information that we don't need
166181/// to do this manual scraping.
167- fn load_important_files ( dep : & mut Dependency , vendor_root : & Path ) -> Result < ( ) , Error > {
168- let name_version = format ! ( "{}-{}" , dep. name, dep. version) ;
182+ fn load_important_files (
183+ package : & Package ,
184+ dep : & mut PackageMetadata ,
185+ vendor_root : & Path ,
186+ ) -> Result < ( ) , Error > {
187+ let name_version = format ! ( "{}-{}" , package. name, package. version) ;
169188 println ! ( "Scraping notices for {}..." , name_version) ;
170189 let dep_vendor_path = vendor_root. join ( name_version) ;
171190 for entry in std:: fs:: read_dir ( dep_vendor_path) ? {
0 commit comments