@@ -4,6 +4,8 @@ use std::path::{Path, PathBuf};
4
4
use std:: slice;
5
5
6
6
use glob:: glob;
7
+ use ignore:: Match ;
8
+ use ignore:: gitignore:: { Gitignore , GitignoreBuilder } ;
7
9
use url:: Url ;
8
10
9
11
use core:: { Package , VirtualManifest , EitherManifest , SourceId } ;
@@ -74,7 +76,7 @@ pub enum WorkspaceConfig {
74
76
/// optionally specified as well.
75
77
Root {
76
78
members : Option < Vec < String > > ,
77
- exclude : Vec < String > ,
79
+ exclude : Gitignore ,
78
80
} ,
79
81
80
82
/// Indicates that `[workspace]` was present and the `root` field is the
@@ -340,13 +342,12 @@ impl<'cfg> Workspace<'cfg> {
340
342
341
343
let mut expanded_list = Vec :: new ( ) ;
342
344
for path in list {
343
- let pathbuf = root. join ( path) ;
344
- let expanded_paths = expand_member_path ( & pathbuf) ?;
345
+ let expanded_paths = expand_member_path ( root, & path) ?;
345
346
346
347
// If glob does not find any valid paths, then put the original
347
348
// path in the expanded list to maintain backwards compatibility.
348
349
if expanded_paths. is_empty ( ) {
349
- expanded_list. push ( pathbuf ) ;
350
+ expanded_list. push ( root . join ( path . as_str ( ) ) ) ;
350
351
} else {
351
352
expanded_list. extend ( expanded_paths) ;
352
353
}
@@ -562,11 +563,13 @@ impl<'cfg> Workspace<'cfg> {
562
563
}
563
564
}
564
565
565
- fn expand_member_path ( path : & Path ) -> CargoResult < Vec < PathBuf > > {
566
- let path = match path. to_str ( ) {
566
+ fn expand_member_path ( root : & Path , pattern : & str ) -> CargoResult < Vec < PathBuf > > {
567
+ let root = root. join ( pattern) ;
568
+ let path = match root. to_str ( ) {
567
569
Some ( p) => p,
568
570
None => return Ok ( Vec :: new ( ) ) ,
569
571
} ;
572
+ // TODO: need to switch away from `glob` to `ignore` here.
570
573
let res = glob ( path) . chain_err ( || {
571
574
format ! ( "could not parse pattern `{}`" , & path)
572
575
} ) ?;
@@ -578,25 +581,39 @@ fn expand_member_path(path: &Path) -> CargoResult<Vec<PathBuf>> {
578
581
}
579
582
580
583
fn is_excluded ( members : & Option < Vec < String > > ,
581
- exclude : & [ String ] ,
584
+ exclude : & Gitignore ,
582
585
root_path : & Path ,
583
586
manifest_path : & Path ) -> bool {
584
- let excluded = exclude. iter ( ) . any ( |ex| {
585
- manifest_path. starts_with ( root_path. join ( ex) )
586
- } ) ;
587
+ let exclude_match = exclude. matched_path_or_any_parents ( manifest_path, false ) ;
587
588
588
589
let explicit_member = match * members {
589
590
Some ( ref members) => {
590
- members. iter ( ) . any ( |mem| {
591
- manifest_path. starts_with ( root_path. join ( mem ) )
592
- } )
591
+ members. iter ( )
592
+ . filter ( |p| manifest_path. starts_with ( root_path. join ( p ) ) )
593
+ . max_by_key ( |p| p . len ( ) )
593
594
}
594
- None => false ,
595
+ None => None ,
595
596
} ;
596
597
597
- !explicit_member && excluded
598
- }
598
+ match explicit_member {
599
+ // This `manifest_path` is explicitly included by `path` here, and
600
+ // `path` is the longest specification for whether to include this,
601
+ // taking the highest precedence. This is still excluded, however, if
602
+ // there's any `exclude` path which is longer
603
+ Some ( path) => {
604
+ match exclude_match {
605
+ Match :: Ignore ( glob) => {
606
+ glob. original ( ) . len ( ) > path. as_str ( ) . len ( )
607
+ }
608
+ _ => false , // not ignored
609
+ }
610
+ }
599
611
612
+ // This `manifest_path` isn't explicitly included, so see if we're
613
+ // explicitly excluded by any rules
614
+ None => exclude_match. is_ignore ( ) ,
615
+ }
616
+ }
600
617
601
618
impl < ' cfg > Packages < ' cfg > {
602
619
fn get ( & self , manifest_path : & Path ) -> & MaybePackage {
@@ -656,3 +673,20 @@ impl MaybePackage {
656
673
}
657
674
}
658
675
}
676
+
677
+ impl WorkspaceConfig {
678
+ pub fn root ( root : & Path ,
679
+ members : Option < Vec < String > > ,
680
+ excludes : Option < Vec < String > > )
681
+ -> CargoResult < WorkspaceConfig >
682
+ {
683
+ let mut builder = GitignoreBuilder :: new ( root) ;
684
+ for exclude in excludes. unwrap_or ( Vec :: new ( ) ) {
685
+ builder. add_line ( None , & exclude) ?;
686
+ }
687
+ Ok ( WorkspaceConfig :: Root {
688
+ members : members,
689
+ exclude : builder. build ( ) ?,
690
+ } )
691
+ }
692
+ }
0 commit comments