@@ -7,7 +7,7 @@ use std::fmt::Debug;
77use std:: fs;
88use std:: hash:: Hash ;
99use std:: ops:: Deref ;
10- use std:: path:: { Path , PathBuf } ;
10+ use std:: path:: { Component , Path , PathBuf } ;
1111use std:: process:: Command ;
1212use std:: time:: { Duration , Instant } ;
1313
@@ -105,6 +105,44 @@ struct StepDescription {
105105 should_run : fn ( ShouldRun < ' _ > ) -> ShouldRun < ' _ > ,
106106 make_run : fn ( RunConfig < ' _ > ) ,
107107 name : & ' static str ,
108+ kind : Kind ,
109+ }
110+
111+ #[ derive( Clone , PartialOrd , Ord , PartialEq , Eq ) ]
112+ pub struct TaskPath {
113+ pub path : PathBuf ,
114+ pub kind : Option < Kind > ,
115+ }
116+
117+ impl TaskPath {
118+ pub fn parse ( path : impl Into < PathBuf > ) -> TaskPath {
119+ let mut kind = None ;
120+ let mut path = path. into ( ) ;
121+
122+ let mut components = path. components ( ) ;
123+ if let Some ( Component :: Normal ( os_str) ) = components. next ( ) {
124+ if let Some ( str) = os_str. to_str ( ) {
125+ if let Some ( ( found_kind, found_prefix) ) = str. split_once ( "::" ) {
126+ if found_kind. is_empty ( ) {
127+ panic ! ( "empty kind in task path {}" , path. display( ) ) ;
128+ }
129+ kind = Some ( Kind :: parse ( found_kind) ) ;
130+ path = Path :: new ( found_prefix) . join ( components. as_path ( ) ) ;
131+ }
132+ }
133+ }
134+
135+ TaskPath { path, kind }
136+ }
137+ }
138+
139+ impl Debug for TaskPath {
140+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
141+ if let Some ( kind) = & self . kind {
142+ write ! ( f, "{}::" , kind. as_str( ) ) ?;
143+ }
144+ write ! ( f, "{}" , self . path. display( ) )
145+ }
108146}
109147
110148/// Collection of paths used to match a task rule.
@@ -115,50 +153,61 @@ pub enum PathSet {
115153 /// These are generally matched as a path suffix. For example, a
116154 /// command-line value of `libstd` will match if `src/libstd` is in the
117155 /// set.
118- Set ( BTreeSet < PathBuf > ) ,
156+ Set ( BTreeSet < TaskPath > ) ,
119157 /// A "suite" of paths.
120158 ///
121159 /// These can match as a path suffix (like `Set`), or as a prefix. For
122160 /// example, a command-line value of `src/test/ui/abi/variadic-ffi.rs`
123161 /// will match `src/test/ui`. A command-line value of `ui` would also
124162 /// match `src/test/ui`.
125- Suite ( PathBuf ) ,
163+ Suite ( TaskPath ) ,
126164}
127165
128166impl PathSet {
129167 fn empty ( ) -> PathSet {
130168 PathSet :: Set ( BTreeSet :: new ( ) )
131169 }
132170
133- fn one < P : Into < PathBuf > > ( path : P ) -> PathSet {
171+ fn one < P : Into < PathBuf > > ( path : P , kind : Kind ) -> PathSet {
134172 let mut set = BTreeSet :: new ( ) ;
135- set. insert ( path. into ( ) ) ;
173+ set. insert ( TaskPath { path : path . into ( ) , kind : Some ( kind . into ( ) ) } ) ;
136174 PathSet :: Set ( set)
137175 }
138176
139- fn has ( & self , needle : & Path ) -> bool {
177+ fn has ( & self , needle : & Path , module : Option < Kind > ) -> bool {
178+ let check = |p : & TaskPath | {
179+ if let ( Some ( p_kind) , Some ( kind) ) = ( & p. kind , module) {
180+ p. path . ends_with ( needle) && * p_kind == kind
181+ } else {
182+ p. path . ends_with ( needle)
183+ }
184+ } ;
185+
140186 match self {
141- PathSet :: Set ( set) => set. iter ( ) . any ( |p| p . ends_with ( needle ) ) ,
142- PathSet :: Suite ( suite) => suite . ends_with ( needle ) ,
187+ PathSet :: Set ( set) => set. iter ( ) . any ( check ) ,
188+ PathSet :: Suite ( suite) => check ( suite ) ,
143189 }
144190 }
145191
146192 fn path ( & self , builder : & Builder < ' _ > ) -> PathBuf {
147193 match self {
148- PathSet :: Set ( set) => set. iter ( ) . next ( ) . unwrap_or ( & builder. build . src ) . to_path_buf ( ) ,
149- PathSet :: Suite ( path) => PathBuf :: from ( path) ,
194+ PathSet :: Set ( set) => {
195+ set. iter ( ) . next ( ) . map ( |p| & p. path ) . unwrap_or ( & builder. build . src ) . clone ( )
196+ }
197+ PathSet :: Suite ( path) => path. path . clone ( ) ,
150198 }
151199 }
152200}
153201
154202impl StepDescription {
155- fn from < S : Step > ( ) -> StepDescription {
203+ fn from < S : Step > ( kind : Kind ) -> StepDescription {
156204 StepDescription {
157205 default : S :: DEFAULT ,
158206 only_hosts : S :: ONLY_HOSTS ,
159207 should_run : S :: should_run,
160208 make_run : S :: make_run,
161209 name : std:: any:: type_name :: < S > ( ) ,
210+ kind,
162211 }
163212 }
164213
@@ -177,7 +226,7 @@ impl StepDescription {
177226 }
178227
179228 fn is_excluded ( & self , builder : & Builder < ' _ > , pathset : & PathSet ) -> bool {
180- if builder. config . exclude . iter ( ) . any ( |e| pathset. has ( e ) ) {
229+ if builder. config . exclude . iter ( ) . any ( |e| pathset. has ( & e . path , e . kind ) ) {
181230 eprintln ! ( "Skipping {:?} because it is excluded" , pathset) ;
182231 return true ;
183232 }
@@ -192,8 +241,10 @@ impl StepDescription {
192241 }
193242
194243 fn run ( v : & [ StepDescription ] , builder : & Builder < ' _ > , paths : & [ PathBuf ] ) {
195- let should_runs =
196- v. iter ( ) . map ( |desc| ( desc. should_run ) ( ShouldRun :: new ( builder) ) ) . collect :: < Vec < _ > > ( ) ;
244+ let should_runs = v
245+ . iter ( )
246+ . map ( |desc| ( desc. should_run ) ( ShouldRun :: new ( builder, desc. kind ) ) )
247+ . collect :: < Vec < _ > > ( ) ;
197248
198249 // sanity checks on rules
199250 for ( desc, should_run) in v. iter ( ) . zip ( & should_runs) {
@@ -226,7 +277,7 @@ impl StepDescription {
226277 if let Some ( suite) = should_run. is_suite_path ( path) {
227278 attempted_run = true ;
228279 desc. maybe_run ( builder, suite) ;
229- } else if let Some ( pathset) = should_run. pathset_for_path ( path) {
280+ } else if let Some ( pathset) = should_run. pathset_for_path ( path, desc . kind ) {
230281 attempted_run = true ;
231282 desc. maybe_run ( builder, pathset) ;
232283 }
@@ -246,6 +297,8 @@ enum ReallyDefault<'a> {
246297
247298pub struct ShouldRun < ' a > {
248299 pub builder : & ' a Builder < ' a > ,
300+ kind : Kind ,
301+
249302 // use a BTreeSet to maintain sort order
250303 paths : BTreeSet < PathSet > ,
251304
@@ -255,9 +308,10 @@ pub struct ShouldRun<'a> {
255308}
256309
257310impl < ' a > ShouldRun < ' a > {
258- fn new ( builder : & ' a Builder < ' _ > ) -> ShouldRun < ' a > {
311+ fn new ( builder : & ' a Builder < ' _ > , kind : Kind ) -> ShouldRun < ' a > {
259312 ShouldRun {
260313 builder,
314+ kind,
261315 paths : BTreeSet :: new ( ) ,
262316 is_really_default : ReallyDefault :: Bool ( true ) , // by default no additional conditions
263317 }
@@ -293,7 +347,7 @@ impl<'a> ShouldRun<'a> {
293347 let mut set = BTreeSet :: new ( ) ;
294348 for krate in self . builder . in_tree_crates ( name, None ) {
295349 let path = krate. local_path ( self . builder ) ;
296- set. insert ( path) ;
350+ set. insert ( TaskPath { path, kind : Some ( self . kind ) } ) ;
297351 }
298352 self . paths . insert ( PathSet :: Set ( set) ) ;
299353 self
@@ -306,7 +360,7 @@ impl<'a> ShouldRun<'a> {
306360 pub fn krate ( mut self , name : & str ) -> Self {
307361 for krate in self . builder . in_tree_crates ( name, None ) {
308362 let path = krate. local_path ( self . builder ) ;
309- self . paths . insert ( PathSet :: one ( path) ) ;
363+ self . paths . insert ( PathSet :: one ( path, self . kind ) ) ;
310364 }
311365 self
312366 }
@@ -318,19 +372,25 @@ impl<'a> ShouldRun<'a> {
318372
319373 // multiple aliases for the same job
320374 pub fn paths ( mut self , paths : & [ & str ] ) -> Self {
321- self . paths . insert ( PathSet :: Set ( paths. iter ( ) . map ( PathBuf :: from) . collect ( ) ) ) ;
375+ self . paths . insert ( PathSet :: Set (
376+ paths
377+ . iter ( )
378+ . map ( |p| TaskPath { path : p. into ( ) , kind : Some ( self . kind . into ( ) ) } )
379+ . collect ( ) ,
380+ ) ) ;
322381 self
323382 }
324383
325384 pub fn is_suite_path ( & self , path : & Path ) -> Option < & PathSet > {
326385 self . paths . iter ( ) . find ( |pathset| match pathset {
327- PathSet :: Suite ( p) => path. starts_with ( p ) ,
386+ PathSet :: Suite ( p) => path. starts_with ( & p . path ) ,
328387 PathSet :: Set ( _) => false ,
329388 } )
330389 }
331390
332391 pub fn suite_path ( mut self , suite : & str ) -> Self {
333- self . paths . insert ( PathSet :: Suite ( PathBuf :: from ( suite) ) ) ;
392+ self . paths
393+ . insert ( PathSet :: Suite ( TaskPath { path : suite. into ( ) , kind : Some ( self . kind . into ( ) ) } ) ) ;
334394 self
335395 }
336396
@@ -340,12 +400,12 @@ impl<'a> ShouldRun<'a> {
340400 self
341401 }
342402
343- fn pathset_for_path ( & self , path : & Path ) -> Option < & PathSet > {
344- self . paths . iter ( ) . find ( |pathset| pathset. has ( path) )
403+ fn pathset_for_path ( & self , path : & Path , kind : Kind ) -> Option < & PathSet > {
404+ self . paths . iter ( ) . find ( |pathset| pathset. has ( path, Some ( kind ) ) )
345405 }
346406}
347407
348- #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
408+ #[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Debug ) ]
349409pub enum Kind {
350410 Build ,
351411 Check ,
@@ -359,11 +419,44 @@ pub enum Kind {
359419 Run ,
360420}
361421
422+ impl Kind {
423+ fn parse ( string : & str ) -> Kind {
424+ match string {
425+ "build" => Kind :: Build ,
426+ "check" => Kind :: Check ,
427+ "clippy" => Kind :: Clippy ,
428+ "fix" => Kind :: Fix ,
429+ "test" => Kind :: Test ,
430+ "bench" => Kind :: Bench ,
431+ "dist" => Kind :: Dist ,
432+ "doc" => Kind :: Doc ,
433+ "install" => Kind :: Install ,
434+ "run" => Kind :: Run ,
435+ other => panic ! ( "unknown kind: {}" , other) ,
436+ }
437+ }
438+
439+ fn as_str ( & self ) -> & ' static str {
440+ match self {
441+ Kind :: Build => "build" ,
442+ Kind :: Check => "check" ,
443+ Kind :: Clippy => "clippy" ,
444+ Kind :: Fix => "fix" ,
445+ Kind :: Test => "test" ,
446+ Kind :: Bench => "bench" ,
447+ Kind :: Dist => "dist" ,
448+ Kind :: Doc => "doc" ,
449+ Kind :: Install => "install" ,
450+ Kind :: Run => "run" ,
451+ }
452+ }
453+ }
454+
362455impl < ' a > Builder < ' a > {
363456 fn get_step_descriptions ( kind : Kind ) -> Vec < StepDescription > {
364457 macro_rules! describe {
365458 ( $( $rule: ty) ,+ $( , ) ?) => { {
366- vec![ $( StepDescription :: from:: <$rule>( ) ) ,+]
459+ vec![ $( StepDescription :: from:: <$rule>( kind ) ) ,+]
367460 } } ;
368461 }
369462 match kind {
@@ -540,8 +633,11 @@ impl<'a> Builder<'a> {
540633
541634 let builder = Self :: new_internal ( build, kind, vec ! [ ] ) ;
542635 let builder = & builder;
543- let mut should_run = ShouldRun :: new ( builder) ;
636+ // The "build" kind here is just a placeholder, it will be replaced with something else in
637+ // the following statement.
638+ let mut should_run = ShouldRun :: new ( builder, Kind :: Build ) ;
544639 for desc in Builder :: get_step_descriptions ( builder. kind ) {
640+ should_run. kind = desc. kind ;
545641 should_run = ( desc. should_run ) ( should_run) ;
546642 }
547643 let mut help = String :: from ( "Available paths:\n " ) ;
@@ -552,11 +648,11 @@ impl<'a> Builder<'a> {
552648 match pathset {
553649 PathSet :: Set ( set) => {
554650 for path in set {
555- add_path ( & path) ;
651+ add_path ( & path. path ) ;
556652 }
557653 }
558654 PathSet :: Suite ( path) => {
559- add_path ( & path. join ( "..." ) ) ;
655+ add_path ( & path. path . join ( "..." ) ) ;
560656 }
561657 }
562658 }
@@ -1626,9 +1722,10 @@ impl<'a> Builder<'a> {
16261722 pub ( crate ) fn ensure_if_default < T , S : Step < Output = Option < T > > > (
16271723 & ' a self ,
16281724 step : S ,
1725+ kind : Kind ,
16291726 ) -> S :: Output {
1630- let desc = StepDescription :: from :: < S > ( ) ;
1631- let should_run = ( desc. should_run ) ( ShouldRun :: new ( self ) ) ;
1727+ let desc = StepDescription :: from :: < S > ( kind ) ;
1728+ let should_run = ( desc. should_run ) ( ShouldRun :: new ( self , desc . kind ) ) ;
16321729
16331730 // Avoid running steps contained in --exclude
16341731 for pathset in & should_run. paths {
@@ -1642,13 +1739,16 @@ impl<'a> Builder<'a> {
16421739 }
16431740
16441741 /// Checks if any of the "should_run" paths is in the `Builder` paths.
1645- pub ( crate ) fn was_invoked_explicitly < S : Step > ( & ' a self ) -> bool {
1646- let desc = StepDescription :: from :: < S > ( ) ;
1647- let should_run = ( desc. should_run ) ( ShouldRun :: new ( self ) ) ;
1742+ pub ( crate ) fn was_invoked_explicitly < S : Step > ( & ' a self , kind : Kind ) -> bool {
1743+ let desc = StepDescription :: from :: < S > ( kind ) ;
1744+ let should_run = ( desc. should_run ) ( ShouldRun :: new ( self , desc . kind ) ) ;
16481745
16491746 for path in & self . paths {
1650- if should_run. paths . iter ( ) . any ( |s| s. has ( path) )
1651- && !desc. is_excluded ( self , & PathSet :: Suite ( path. clone ( ) ) )
1747+ if should_run. paths . iter ( ) . any ( |s| s. has ( path, Some ( desc. kind ) ) )
1748+ && !desc. is_excluded (
1749+ self ,
1750+ & PathSet :: Suite ( TaskPath { path : path. clone ( ) , kind : Some ( desc. kind . into ( ) ) } ) ,
1751+ )
16521752 {
16531753 return true ;
16541754 }
0 commit comments