11use std:: {
22 borrow:: { Borrow , Cow } ,
3- collections:: { HashSet , VecDeque } ,
3+ collections:: { HashMap , HashSet , VecDeque } ,
44 fmt:: Display ,
55} ;
66
7- use cargo_metadata:: { Metadata , Package , semver:: Version } ;
7+ use cargo_metadata:: {
8+ Metadata , Package ,
9+ semver:: { Version , VersionReq } ,
10+ } ;
811use itertools:: { Either , Itertools } ;
912use log:: error;
1013
1114#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
15+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
1216pub struct CrateName ( pub ( crate ) String ) ;
1317
1418impl < ' a , T : Borrow < Package > > From < & ' a T > for CrateName {
@@ -17,6 +21,12 @@ impl<'a, T: Borrow<Package>> From<&'a T> for CrateName {
1721 }
1822}
1923
24+ impl CrateName {
25+ pub fn new ( name : impl Into < String > ) -> Self {
26+ Self ( name. into ( ) )
27+ }
28+ }
29+
2030impl Display for CrateName {
2131 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
2232 write ! ( f, "{}" , self . 0 )
@@ -25,6 +35,7 @@ impl Display for CrateName {
2535
2636/// A feature name
2737#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
38+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
2839pub struct FeatureName ( Cow < ' static , str > ) ;
2940
3041impl FeatureName {
@@ -46,6 +57,7 @@ impl Display for FeatureName {
4657}
4758
4859#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
60+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
4961pub enum FeatureEffect {
5062 /// I.e. `foo=["feature"]` is represented as `EnableFeature("feature")`
5163 EnableFeature ( FeatureName ) ,
@@ -80,6 +92,7 @@ impl FeatureEffect {
8092}
8193
8294#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
95+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
8396pub struct Feature {
8497 pub name : FeatureName ,
8598 pub effects : Vec < FeatureEffect > ,
@@ -167,33 +180,42 @@ impl Feature {
167180
168181/// Describes a dependency relationship
169182#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
170- pub enum Dependency {
183+ pub enum DependencyKind {
171184 Optional ( CrateName ) ,
172185 NonOptional ( CrateName ) ,
173186}
174187
175- impl Dependency {
188+ impl DependencyKind {
176189 pub fn crate_name ( & self ) -> & CrateName {
177190 match self {
178- Dependency :: Optional ( name) => name,
179- Dependency :: NonOptional ( name) => name,
191+ DependencyKind :: Optional ( name) => name,
192+ DependencyKind :: NonOptional ( name) => name,
180193 }
181194 }
182195
183196 pub fn is_optional ( & self ) -> bool {
184- matches ! ( self , Dependency :: Optional ( _) )
197+ matches ! ( self , DependencyKind :: Optional ( _) )
185198 }
186199}
187200
188201#[ derive( Clone , Debug ) ]
202+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
203+ pub struct CrateDependency {
204+ pub name : CrateName ,
205+ pub version : VersionReq ,
206+ }
207+
208+ #[ derive( Clone , Debug ) ]
209+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
189210pub struct Crate {
190211 pub name : CrateName ,
191212 pub features : Vec < Feature > ,
192- pub dependencies : Vec < CrateName > ,
193- pub optional_dependencies : Vec < CrateName > ,
213+ pub dependencies : Vec < CrateDependency > ,
214+ pub optional_dependencies : Vec < CrateDependency > ,
194215 pub version : Version ,
195216 pub in_workspace : Option < bool > ,
196217 pub active_features : Option < HashSet < FeatureName > > ,
218+ pub active_dependency_features : Option < HashMap < CrateName , Vec < FeatureName > > > ,
197219 pub is_enabled : Option < bool > ,
198220}
199221
@@ -203,27 +225,27 @@ struct DependencyIter<'a> {
203225}
204226
205227impl < ' a > Iterator for DependencyIter < ' a > {
206- type Item = Dependency ;
228+ type Item = DependencyKind ;
207229
208230 fn next ( & mut self ) -> Option < Self :: Item > {
209231 if self . index < self . krate . dependencies . len ( ) {
210232 let dep = & self . krate . dependencies [ self . index ] ;
211233 self . index += 1 ;
212- Some ( Dependency :: NonOptional ( dep. clone ( ) ) )
234+ Some ( DependencyKind :: NonOptional ( dep. name . clone ( ) ) )
213235 } else if self . index
214236 < self . krate . dependencies . len ( ) + self . krate . optional_dependencies . len ( )
215237 {
216238 let opt_dep =
217239 & self . krate . optional_dependencies [ self . index - self . krate . dependencies . len ( ) ] ;
218240 self . index += 1 ;
219- Some ( Dependency :: Optional ( opt_dep. clone ( ) ) )
241+ Some ( DependencyKind :: Optional ( opt_dep. name . clone ( ) ) )
220242 } else {
221243 None
222244 }
223245 }
224246}
225247impl Crate {
226- pub fn dependencies ( & self ) -> impl Iterator < Item = Dependency > {
248+ pub fn dependencies ( & self ) -> impl Iterator < Item = DependencyKind > {
227249 DependencyIter {
228250 krate : self ,
229251 index : 0 ,
@@ -318,12 +340,19 @@ impl From<Package> for Crate {
318340 . dependencies
319341 . iter ( )
320342 . filter ( |d| d. kind == cargo_metadata:: DependencyKind :: Normal ) // dev dependencies can introduce weird cycles, and we don't care about them anyway
321- . map ( |f| ( f. name . clone ( ) , f. optional , f. uses_default_features ) )
322- . partition_map ( |( name, opt, enable_default) | {
343+ . map ( |f| {
344+ (
345+ f. name . clone ( ) ,
346+ f. optional ,
347+ f. uses_default_features ,
348+ f. req . clone ( ) ,
349+ )
350+ } )
351+ . partition_map ( |( name, opt, enable_default, req) | {
323352 if opt {
324- Either :: Left ( ( CrateName ( name) , enable_default) )
353+ Either :: Left ( ( CrateName ( name) , enable_default, req ) )
325354 } else {
326- Either :: Right ( ( CrateName ( name) , enable_default) )
355+ Either :: Right ( ( CrateName ( name) , enable_default, req ) )
327356 }
328357 } ) ;
329358
@@ -334,7 +363,8 @@ impl From<Package> for Crate {
334363 . collect :: < Vec < _ > > ( ) ;
335364
336365 // for each dependency that enables default features, we add a feature named after the dependency that enables the "default" feature
337- for ( dep_name, enable_default) in dependencies. iter ( ) . chain ( optional_dependencies. iter ( ) ) {
366+ for ( dep_name, enable_default, _) in dependencies. iter ( ) . chain ( optional_dependencies. iter ( ) )
367+ {
338368 if * enable_default {
339369 features. push ( Feature :: new_enabling_default_for ( dep_name. clone ( ) ) ) ;
340370 }
@@ -343,17 +373,31 @@ impl From<Package> for Crate {
343373 Self {
344374 name : CrateName ( meta. name . clone ( ) ) ,
345375 features,
346- dependencies : dependencies. into_iter ( ) . map ( |( n, _) | n) . collect ( ) ,
347- optional_dependencies : optional_dependencies. into_iter ( ) . map ( |( n, _) | n) . collect ( ) ,
376+ dependencies : dependencies
377+ . into_iter ( )
378+ . map ( |( n, _, req) | CrateDependency {
379+ name : n,
380+ version : req,
381+ } )
382+ . collect ( ) ,
383+ optional_dependencies : optional_dependencies
384+ . into_iter ( )
385+ . map ( |( n, _, req) | CrateDependency {
386+ name : n,
387+ version : req,
388+ } )
389+ . collect ( ) ,
348390 version : meta. version ,
349391 in_workspace : Some ( true ) ,
350392 active_features : None ,
393+ active_dependency_features : None ,
351394 is_enabled : None ,
352395 }
353396 }
354397}
355398
356- #[ derive( Clone , Debug ) ]
399+ #[ derive( Clone , Debug , Default ) ]
400+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
357401pub struct Workspace {
358402 pub workspace_crates : Vec < Crate > ,
359403 pub other_crates : Vec < Crate > ,
@@ -482,6 +526,31 @@ impl From<&Metadata> for Workspace {
482526 }
483527 } ) ;
484528
529+ let existing_package_names = workspace_crates
530+ . iter ( )
531+ . map ( |c| c. name . clone ( ) )
532+ . collect :: < HashSet < _ > > ( ) ;
533+
534+ // also process dependency crates that are not part of the workspace
535+ for dep in meta. packages . iter ( ) {
536+ for dependency in dep. dependencies . iter ( ) {
537+ let dep_name = CrateName :: new ( & dependency. name ) ;
538+ if !existing_package_names. contains ( & dep_name) {
539+ other_crates. push ( Crate {
540+ name : dep_name,
541+ features : vec ! [ ] ,
542+ dependencies : vec ! [ ] ,
543+ optional_dependencies : vec ! [ ] ,
544+ version : Version :: new ( 0 , 0 , 0 ) ,
545+ in_workspace : Some ( false ) ,
546+ active_features : None ,
547+ active_dependency_features : None ,
548+ is_enabled : None ,
549+ } ) ;
550+ }
551+ }
552+ }
553+
485554 for krate in workspace_crates. iter_mut ( ) {
486555 krate. in_workspace = Some ( true ) ;
487556 }
@@ -562,6 +631,7 @@ mod tests {
562631 in_workspace : Some ( true ) ,
563632 active_features : None ,
564633 is_enabled : None ,
634+ active_dependency_features : None ,
565635 } ;
566636
567637 krate. compute_active_features ( & HashSet :: from ( [ FeatureName ( "default" . into ( ) ) ] ) , true ) ;
@@ -599,6 +669,7 @@ mod tests {
599669 in_workspace: Some ( true ) ,
600670 active_features: None ,
601671 is_enabled: None ,
672+ active_dependency_features: None ,
602673 } ,
603674 Crate {
604675 name: CrateName ( "crate_b" . into( ) ) ,
@@ -609,6 +680,7 @@ mod tests {
609680 in_workspace: Some ( true ) ,
610681 active_features: None ,
611682 is_enabled: None ,
683+ active_dependency_features: None ,
612684 } ,
613685 ] ,
614686 other_crates : vec ! [ Crate {
@@ -620,6 +692,7 @@ mod tests {
620692 in_workspace: Some ( false ) ,
621693 active_features: None ,
622694 is_enabled: None ,
695+ active_dependency_features: None ,
623696 } ] ,
624697 root : None ,
625698 } ;
0 commit comments