@@ -75,16 +75,24 @@ enum MaybePackage {
75
75
pub enum WorkspaceConfig {
76
76
/// Indicates that `[workspace]` was present and the members were
77
77
/// optionally specified as well.
78
- Root {
79
- members : Option < Vec < String > > ,
80
- exclude : Vec < String > ,
81
- } ,
78
+ Root ( WorkspaceRootConfig ) ,
82
79
83
80
/// Indicates that `[workspace]` was present and the `root` field is the
84
81
/// optional value of `package.workspace`, if present.
85
82
Member { root : Option < String > } ,
86
83
}
87
84
85
+ /// Intermediate configuration of a workspace root in a manifest.
86
+ ///
87
+ /// Knows the Workspace Root path, as well as `members` and `exclude` lists of path patterns, which
88
+ /// together tell if some path is recognized as a member by this root or not.
89
+ #[ derive( Debug , Clone ) ]
90
+ pub struct WorkspaceRootConfig {
91
+ root_dir : PathBuf ,
92
+ members : Option < Vec < String > > ,
93
+ exclude : Vec < String > ,
94
+ }
95
+
88
96
/// An iterator over the member packages of a workspace, returned by
89
97
/// `Workspace::members`
90
98
pub struct Members < ' a , ' cfg : ' a > {
@@ -202,7 +210,7 @@ impl<'cfg> Workspace<'cfg> {
202
210
let root = self . root_manifest . as_ref ( ) . unwrap_or ( & self . current_manifest ) ;
203
211
match * self . packages . get ( root) {
204
212
MaybePackage :: Package ( ref p) => p. manifest ( ) . profiles ( ) ,
205
- MaybePackage :: Virtual ( ref m ) => m . profiles ( ) ,
213
+ MaybePackage :: Virtual ( ref vm ) => vm . profiles ( ) ,
206
214
}
207
215
}
208
216
@@ -233,7 +241,7 @@ impl<'cfg> Workspace<'cfg> {
233
241
} ;
234
242
match * self . packages . get ( path) {
235
243
MaybePackage :: Package ( ref p) => p. manifest ( ) . replace ( ) ,
236
- MaybePackage :: Virtual ( ref v ) => v . replace ( ) ,
244
+ MaybePackage :: Virtual ( ref vm ) => vm . replace ( ) ,
237
245
}
238
246
}
239
247
@@ -247,7 +255,7 @@ impl<'cfg> Workspace<'cfg> {
247
255
} ;
248
256
match * self . packages . get ( path) {
249
257
MaybePackage :: Package ( ref p) => p. manifest ( ) . patch ( ) ,
250
- MaybePackage :: Virtual ( ref v ) => v . patch ( ) ,
258
+ MaybePackage :: Virtual ( ref vm ) => vm . patch ( ) ,
251
259
}
252
260
}
253
261
@@ -289,7 +297,7 @@ impl<'cfg> Workspace<'cfg> {
289
297
{
290
298
let current = self . packages . load ( manifest_path) ?;
291
299
match * current. workspace_config ( ) {
292
- WorkspaceConfig :: Root { .. } => {
300
+ WorkspaceConfig :: Root ( _ ) => {
293
301
debug ! ( "find_root - is root {}" , manifest_path. display( ) ) ;
294
302
return Ok ( Some ( manifest_path. to_path_buf ( ) ) )
295
303
}
@@ -301,20 +309,20 @@ impl<'cfg> Workspace<'cfg> {
301
309
}
302
310
303
311
for path in paths:: ancestors ( manifest_path) . skip ( 2 ) {
304
- let manifest = path. join ( "Cargo.toml" ) ;
305
- debug ! ( "find_root - trying {}" , manifest . display( ) ) ;
306
- if manifest . exists ( ) {
307
- match * self . packages . load ( & manifest ) ?. workspace_config ( ) {
308
- WorkspaceConfig :: Root { ref exclude , ref members } => {
312
+ let ances_manifest_path = path. join ( "Cargo.toml" ) ;
313
+ debug ! ( "find_root - trying {}" , ances_manifest_path . display( ) ) ;
314
+ if ances_manifest_path . exists ( ) {
315
+ match * self . packages . load ( & ances_manifest_path ) ?. workspace_config ( ) {
316
+ WorkspaceConfig :: Root ( ref ances_root_config ) => {
309
317
debug ! ( "find_root - found a root checking exclusion" ) ;
310
- if !is_excluded ( members , exclude , path , manifest_path) {
318
+ if !ances_root_config . is_excluded ( & manifest_path) {
311
319
debug ! ( "find_root - found!" ) ;
312
- return Ok ( Some ( manifest ) )
320
+ return Ok ( Some ( ances_manifest_path ) )
313
321
}
314
322
}
315
323
WorkspaceConfig :: Member { root : Some ( ref path_to_root) } => {
316
324
debug ! ( "find_root - found pointer" ) ;
317
- return Ok ( Some ( read_root_pointer ( & manifest , path_to_root) ?) )
325
+ return Ok ( Some ( read_root_pointer ( & ances_manifest_path , path_to_root) ?) )
318
326
}
319
327
WorkspaceConfig :: Member { .. } => { }
320
328
}
@@ -332,47 +340,29 @@ impl<'cfg> Workspace<'cfg> {
332
340
/// will transitively follow all `path` dependencies looking for members of
333
341
/// the workspace.
334
342
fn find_members ( & mut self ) -> CargoResult < ( ) > {
335
- let root_manifest = match self . root_manifest {
343
+ let root_manifest_path = match self . root_manifest {
336
344
Some ( ref path) => path. clone ( ) ,
337
345
None => {
338
346
debug ! ( "find_members - only me as a member" ) ;
339
347
self . members . push ( self . current_manifest . clone ( ) ) ;
340
348
return Ok ( ( ) )
341
349
}
342
350
} ;
343
- let members = {
344
- let root = self . packages . load ( & root_manifest) ?;
345
- match * root. workspace_config ( ) {
346
- WorkspaceConfig :: Root { ref members, .. } => members. clone ( ) ,
351
+
352
+ let members_paths = {
353
+ let root_package = self . packages . load ( & root_manifest_path) ?;
354
+ match * root_package. workspace_config ( ) {
355
+ WorkspaceConfig :: Root ( ref root_config) => root_config. members_paths ( ) ?,
347
356
_ => bail ! ( "root of a workspace inferred but wasn't a root: {}" ,
348
- root_manifest . display( ) ) ,
357
+ root_manifest_path . display( ) ) ,
349
358
}
350
359
} ;
351
360
352
- if let Some ( list) = members {
353
- let root = root_manifest. parent ( ) . unwrap ( ) ;
354
-
355
- let mut expanded_list = Vec :: new ( ) ;
356
- for path in list {
357
- let pathbuf = root. join ( path) ;
358
- let expanded_paths = expand_member_path ( & pathbuf) ?;
359
-
360
- // If glob does not find any valid paths, then put the original
361
- // path in the expanded list to maintain backwards compatibility.
362
- if expanded_paths. is_empty ( ) {
363
- expanded_list. push ( pathbuf) ;
364
- } else {
365
- expanded_list. extend ( expanded_paths) ;
366
- }
367
- }
368
-
369
- for path in expanded_list {
370
- let manifest_path = path. join ( "Cargo.toml" ) ;
371
- self . find_path_deps ( & manifest_path, & root_manifest, false ) ?;
372
- }
361
+ for path in members_paths {
362
+ self . find_path_deps ( & path. join ( "Cargo.toml" ) , & root_manifest_path, false ) ?;
373
363
}
374
364
375
- self . find_path_deps ( & root_manifest , & root_manifest , false )
365
+ self . find_path_deps ( & root_manifest_path , & root_manifest_path , false )
376
366
}
377
367
378
368
fn find_path_deps ( & mut self ,
@@ -391,10 +381,9 @@ impl<'cfg> Workspace<'cfg> {
391
381
return Ok ( ( ) )
392
382
}
393
383
394
- let root = root_manifest. parent ( ) . unwrap ( ) ;
395
384
match * self . packages . load ( root_manifest) ?. workspace_config ( ) {
396
- WorkspaceConfig :: Root { ref members , ref exclude } => {
397
- if is_excluded ( members , exclude , root , & manifest_path) {
385
+ WorkspaceConfig :: Root ( ref root_config ) => {
386
+ if root_config . is_excluded ( & manifest_path) {
398
387
return Ok ( ( ) )
399
388
}
400
389
}
@@ -439,7 +428,7 @@ impl<'cfg> Workspace<'cfg> {
439
428
for member in self . members . iter ( ) {
440
429
let package = self . packages . get ( member) ;
441
430
match * package. workspace_config ( ) {
442
- WorkspaceConfig :: Root { .. } => {
431
+ WorkspaceConfig :: Root ( _ ) => {
443
432
roots. push ( member. parent ( ) . unwrap ( ) . to_path_buf ( ) ) ;
444
433
}
445
434
WorkspaceConfig :: Member { .. } => { }
@@ -505,6 +494,8 @@ impl<'cfg> Workspace<'cfg> {
505
494
let current_dir = self . current_manifest . parent ( ) . unwrap ( ) ;
506
495
let root_pkg = self . packages . get ( root) ;
507
496
497
+ // FIXME: Make this more generic by using a relative path resolver between member and
498
+ // root.
508
499
let members_msg = match current_dir. strip_prefix ( root_dir) {
509
500
Ok ( rel) => {
510
501
format ! ( "this may be fixable by adding `{}` to the \
@@ -522,11 +513,11 @@ impl<'cfg> Workspace<'cfg> {
522
513
let extra = match * root_pkg {
523
514
MaybePackage :: Virtual ( _) => members_msg,
524
515
MaybePackage :: Package ( ref p) => {
525
- let members = match * p. manifest ( ) . workspace_config ( ) {
526
- WorkspaceConfig :: Root { ref members , .. } => members ,
516
+ let has_members_list = match * p. manifest ( ) . workspace_config ( ) {
517
+ WorkspaceConfig :: Root ( ref root_config ) => root_config . has_members_list ( ) ,
527
518
WorkspaceConfig :: Member { .. } => unreachable ! ( ) ,
528
519
} ;
529
- if members . is_none ( ) {
520
+ if !has_members_list {
530
521
format ! ( "this may be fixable by ensuring that this \
531
522
crate is depended on by the workspace \
532
523
root: {}", root. display( ) )
@@ -576,41 +567,6 @@ impl<'cfg> Workspace<'cfg> {
576
567
}
577
568
}
578
569
579
- fn expand_member_path ( path : & Path ) -> CargoResult < Vec < PathBuf > > {
580
- let path = match path. to_str ( ) {
581
- Some ( p) => p,
582
- None => return Ok ( Vec :: new ( ) ) ,
583
- } ;
584
- let res = glob ( path) . chain_err ( || {
585
- format ! ( "could not parse pattern `{}`" , & path)
586
- } ) ?;
587
- res. map ( |p| {
588
- p. chain_err ( || {
589
- format ! ( "unable to match path to pattern `{}`" , & path)
590
- } )
591
- } ) . collect ( )
592
- }
593
-
594
- fn is_excluded ( members : & Option < Vec < String > > ,
595
- exclude : & [ String ] ,
596
- root_path : & Path ,
597
- manifest_path : & Path ) -> bool {
598
- let excluded = exclude. iter ( ) . any ( |ex| {
599
- manifest_path. starts_with ( root_path. join ( ex) )
600
- } ) ;
601
-
602
- let explicit_member = match * members {
603
- Some ( ref members) => {
604
- members. iter ( ) . any ( |mem| {
605
- manifest_path. starts_with ( root_path. join ( mem) )
606
- } )
607
- }
608
- None => false ,
609
- } ;
610
-
611
- !explicit_member && excluded
612
- }
613
-
614
570
615
571
impl < ' cfg > Packages < ' cfg > {
616
572
fn get ( & self , manifest_path : & Path ) -> & MaybePackage {
@@ -627,11 +583,10 @@ impl<'cfg> Packages<'cfg> {
627
583
read_manifest ( manifest_path, & source_id, self . config ) ?;
628
584
Ok ( v. insert ( match manifest {
629
585
EitherManifest :: Real ( manifest) => {
630
- MaybePackage :: Package ( Package :: new ( manifest,
631
- manifest_path) )
586
+ MaybePackage :: Package ( Package :: new ( manifest, manifest_path) )
632
587
}
633
- EitherManifest :: Virtual ( v ) => {
634
- MaybePackage :: Virtual ( v )
588
+ EitherManifest :: Virtual ( vm ) => {
589
+ MaybePackage :: Virtual ( vm )
635
590
}
636
591
} ) )
637
592
}
@@ -665,8 +620,83 @@ impl<'a, 'cfg> Iterator for Members<'a, 'cfg> {
665
620
impl MaybePackage {
666
621
fn workspace_config ( & self ) -> & WorkspaceConfig {
667
622
match * self {
668
- MaybePackage :: Virtual ( ref v ) => v . workspace_config ( ) ,
669
- MaybePackage :: Package ( ref v ) => v . manifest ( ) . workspace_config ( ) ,
623
+ MaybePackage :: Package ( ref p ) => p . manifest ( ) . workspace_config ( ) ,
624
+ MaybePackage :: Virtual ( ref vm ) => vm . workspace_config ( ) ,
670
625
}
671
626
}
672
627
}
628
+
629
+ impl WorkspaceRootConfig {
630
+ /// Create a new Intermediate Workspace Root configuration.
631
+ pub fn new (
632
+ root_dir : & Path ,
633
+ members : & Option < Vec < String > > ,
634
+ exclude : & Option < Vec < String > > ,
635
+ ) -> WorkspaceRootConfig {
636
+ WorkspaceRootConfig {
637
+ root_dir : root_dir. to_path_buf ( ) ,
638
+ members : members. clone ( ) ,
639
+ exclude : exclude. clone ( ) . unwrap_or_default ( ) ,
640
+ }
641
+ }
642
+
643
+ /// Checks the path against the `excluded` list.
644
+ ///
645
+ /// This method does NOT consider the `members` list.
646
+ fn is_excluded ( & self , manifest_path : & Path ) -> bool {
647
+ let excluded = self . exclude . iter ( ) . any ( |ex| {
648
+ manifest_path. starts_with ( self . root_dir . join ( ex) )
649
+ } ) ;
650
+
651
+ let explicit_member = match self . members {
652
+ Some ( ref members) => {
653
+ members. iter ( ) . any ( |mem| {
654
+ manifest_path. starts_with ( self . root_dir . join ( mem) )
655
+ } )
656
+ }
657
+ None => false ,
658
+ } ;
659
+
660
+ !explicit_member && excluded
661
+ }
662
+
663
+ fn has_members_list ( & self ) -> bool {
664
+ self . members . is_some ( )
665
+ }
666
+
667
+ fn members_paths ( & self ) -> CargoResult < Vec < PathBuf > > {
668
+ let mut expanded_list = Vec :: new ( ) ;
669
+
670
+ if let Some ( globs) = self . members . clone ( ) {
671
+ for glob in globs {
672
+ let pathbuf = self . root_dir . join ( glob) ;
673
+ let expanded_paths = Self :: expand_member_path ( & pathbuf) ?;
674
+
675
+ // If glob does not find any valid paths, then put the original
676
+ // path in the expanded list to maintain backwards compatibility.
677
+ if expanded_paths. is_empty ( ) {
678
+ expanded_list. push ( pathbuf) ;
679
+ } else {
680
+ expanded_list. extend ( expanded_paths) ;
681
+ }
682
+ }
683
+ }
684
+
685
+ Ok ( expanded_list)
686
+ }
687
+
688
+ fn expand_member_path ( path : & Path ) -> CargoResult < Vec < PathBuf > > {
689
+ let path = match path. to_str ( ) {
690
+ Some ( p) => p,
691
+ None => return Ok ( Vec :: new ( ) ) ,
692
+ } ;
693
+ let res = glob ( path) . chain_err ( || {
694
+ format ! ( "could not parse pattern `{}`" , & path)
695
+ } ) ?;
696
+ res. map ( |p| {
697
+ p. chain_err ( || {
698
+ format ! ( "unable to match path to pattern `{}`" , & path)
699
+ } )
700
+ } ) . collect ( )
701
+ }
702
+ }
0 commit comments