@@ -7,38 +7,35 @@ use crate::cache::INTERNER;
77use crate :: util:: output;
88use crate :: { Build , Crate } ;
99
10- #[ derive( Deserialize ) ]
10+ /// For more information, see the output of
11+ /// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
12+ #[ derive( Debug , Deserialize ) ]
1113struct Output {
1214 packages : Vec < Package > ,
1315}
1416
15- #[ derive( Deserialize ) ]
17+ /// For more information, see the output of
18+ /// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
19+ #[ derive( Debug , Deserialize ) ]
1620struct Package {
1721 name : String ,
1822 source : Option < String > ,
1923 manifest_path : String ,
2024 dependencies : Vec < Dependency > ,
2125}
2226
23- #[ derive( Deserialize ) ]
27+ /// For more information, see the output of
28+ /// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
29+ #[ derive( Debug , Deserialize ) ]
2430struct Dependency {
2531 name : String ,
2632 source : Option < String > ,
2733}
2834
35+ /// Collects and stores package metadata of each workspace members into `build`,
36+ /// by executing `cargo metadata` commands.
2937pub fn build ( build : & mut Build ) {
30- // Run `cargo metadata` to figure out what crates we're testing.
31- let mut cargo = Command :: new ( & build. initial_cargo ) ;
32- cargo
33- . arg ( "metadata" )
34- . arg ( "--format-version" )
35- . arg ( "1" )
36- . arg ( "--no-deps" )
37- . arg ( "--manifest-path" )
38- . arg ( build. src . join ( "Cargo.toml" ) ) ;
39- let output = output ( & mut cargo) ;
40- let output: Output = serde_json:: from_str ( & output) . unwrap ( ) ;
41- for package in output. packages {
38+ for package in workspace_members ( build) {
4239 if package. source . is_none ( ) {
4340 let name = INTERNER . intern_string ( package. name ) ;
4441 let mut path = PathBuf :: from ( package. manifest_path ) ;
@@ -57,3 +54,35 @@ pub fn build(build: &mut Build) {
5754 }
5855 }
5956}
57+
58+ /// Invokes `cargo metadata` to get package metadata of each workspace member.
59+ ///
60+ /// Note that `src/tools/cargo` is no longer a workspace member but we still
61+ /// treat it as one here, by invoking an additional `cargo metadata` command.
62+ fn workspace_members ( build : & Build ) -> impl Iterator < Item = Package > {
63+ let cmd_metadata = |manifest_path| {
64+ let mut cargo = Command :: new ( & build. initial_cargo ) ;
65+ cargo
66+ . arg ( "metadata" )
67+ . arg ( "--format-version" )
68+ . arg ( "1" )
69+ . arg ( "--no-deps" )
70+ . arg ( "--manifest-path" )
71+ . arg ( manifest_path) ;
72+ cargo
73+ } ;
74+
75+ // Collects `metadata.packages` from the root workspace.
76+ let root_manifest_path = build. src . join ( "Cargo.toml" ) ;
77+ let root_output = output ( & mut cmd_metadata ( & root_manifest_path) ) ;
78+ let Output { packages, .. } = serde_json:: from_str ( & root_output) . unwrap ( ) ;
79+
80+ // Collects `metadata.packages` from src/tools/cargo separately.
81+ let cargo_manifest_path = build. src . join ( "src/tools/cargo/Cargo.toml" ) ;
82+ let cargo_output = output ( & mut cmd_metadata ( & cargo_manifest_path) ) ;
83+ let Output { packages : cargo_packages, .. } = serde_json:: from_str ( & cargo_output) . unwrap ( ) ;
84+
85+ // We only care about the root package from `src/tool/cargo` workspace.
86+ let cargo_package = cargo_packages. into_iter ( ) . find ( |pkg| pkg. name == "cargo" ) . into_iter ( ) ;
87+ packages. into_iter ( ) . chain ( cargo_package)
88+ }
0 commit comments