@@ -7,7 +7,7 @@ use std::fmt::Debug;
7
7
use std::fs;
8
8
use std::hash::Hash;
9
9
use std::ops::Deref;
10
- use std::path::{Path, PathBuf};
10
+ use std::path::{Component, Path, PathBuf};
11
11
use std::process::Command;
12
12
use std::time::{Duration, Instant};
13
13
@@ -105,17 +105,43 @@ struct StepDescription {
105
105
should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>,
106
106
make_run: fn(RunConfig<'_>),
107
107
name: &'static str,
108
+ kind: Kind,
108
109
}
109
110
110
- #[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
111
+ #[derive(Clone, PartialOrd, Ord, PartialEq, Eq)]
111
112
pub struct TaskPath {
112
113
pub path: PathBuf,
113
- pub module : Option<String >,
114
+ pub kind : Option<Kind >,
114
115
}
115
116
116
117
impl TaskPath {
117
118
pub fn parse(path: impl Into<PathBuf>) -> TaskPath {
118
- TaskPath { path: path.into(), module: None }
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())
119
145
}
120
146
}
121
147
@@ -142,16 +168,24 @@ impl PathSet {
142
168
PathSet::Set(BTreeSet::new())
143
169
}
144
170
145
- fn one<P: Into<PathBuf>>(path: P) -> PathSet {
171
+ fn one<P: Into<PathBuf>>(path: P, kind: Kind ) -> PathSet {
146
172
let mut set = BTreeSet::new();
147
- set.insert(TaskPath::parse(path) );
173
+ set.insert(TaskPath { path: path.into(), kind: Some(kind.into()) } );
148
174
PathSet::Set(set)
149
175
}
150
176
151
- 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
+
152
186
match self {
153
- PathSet::Set(set) => set.iter().any(|p| p.path.ends_with(needle) ),
154
- PathSet::Suite(suite) => suite.path.ends_with(needle ),
187
+ PathSet::Set(set) => set.iter().any(check ),
188
+ PathSet::Suite(suite) => check(suite ),
155
189
}
156
190
}
157
191
@@ -166,13 +200,14 @@ impl PathSet {
166
200
}
167
201
168
202
impl StepDescription {
169
- fn from<S: Step>() -> StepDescription {
203
+ fn from<S: Step>(kind: Kind ) -> StepDescription {
170
204
StepDescription {
171
205
default: S::DEFAULT,
172
206
only_hosts: S::ONLY_HOSTS,
173
207
should_run: S::should_run,
174
208
make_run: S::make_run,
175
209
name: std::any::type_name::<S>(),
210
+ kind,
176
211
}
177
212
}
178
213
@@ -191,7 +226,7 @@ impl StepDescription {
191
226
}
192
227
193
228
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
194
- if builder.config.exclude.iter().any(|e| pathset.has(e )) {
229
+ if builder.config.exclude.iter().any(|e| pathset.has(&e.path, e.kind )) {
195
230
eprintln!("Skipping {:?} because it is excluded", pathset);
196
231
return true;
197
232
}
@@ -206,8 +241,10 @@ impl StepDescription {
206
241
}
207
242
208
243
fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
209
- let should_runs =
210
- 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<_>>();
211
248
212
249
// sanity checks on rules
213
250
for (desc, should_run) in v.iter().zip(&should_runs) {
@@ -240,7 +277,7 @@ impl StepDescription {
240
277
if let Some(suite) = should_run.is_suite_path(path) {
241
278
attempted_run = true;
242
279
desc.maybe_run(builder, suite);
243
- } 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 ) {
244
281
attempted_run = true;
245
282
desc.maybe_run(builder, pathset);
246
283
}
@@ -260,6 +297,8 @@ enum ReallyDefault<'a> {
260
297
261
298
pub struct ShouldRun<'a> {
262
299
pub builder: &'a Builder<'a>,
300
+ kind: Kind,
301
+
263
302
// use a BTreeSet to maintain sort order
264
303
paths: BTreeSet<PathSet>,
265
304
@@ -269,9 +308,10 @@ pub struct ShouldRun<'a> {
269
308
}
270
309
271
310
impl<'a> ShouldRun<'a> {
272
- fn new(builder: &'a Builder<'_>) -> ShouldRun<'a> {
311
+ fn new(builder: &'a Builder<'_>, kind: Kind ) -> ShouldRun<'a> {
273
312
ShouldRun {
274
313
builder,
314
+ kind,
275
315
paths: BTreeSet::new(),
276
316
is_really_default: ReallyDefault::Bool(true), // by default no additional conditions
277
317
}
@@ -307,7 +347,7 @@ impl<'a> ShouldRun<'a> {
307
347
let mut set = BTreeSet::new();
308
348
for krate in self.builder.in_tree_crates(name, None) {
309
349
let path = krate.local_path(self.builder);
310
- set.insert(TaskPath::parse(path) );
350
+ set.insert(TaskPath { path, kind: Some(self.kind) } );
311
351
}
312
352
self.paths.insert(PathSet::Set(set));
313
353
self
@@ -320,7 +360,7 @@ impl<'a> ShouldRun<'a> {
320
360
pub fn krate(mut self, name: &str) -> Self {
321
361
for krate in self.builder.in_tree_crates(name, None) {
322
362
let path = krate.local_path(self.builder);
323
- self.paths.insert(PathSet::one(path));
363
+ self.paths.insert(PathSet::one(path, self.kind ));
324
364
}
325
365
self
326
366
}
@@ -332,7 +372,12 @@ impl<'a> ShouldRun<'a> {
332
372
333
373
// multiple aliases for the same job
334
374
pub fn paths(mut self, paths: &[&str]) -> Self {
335
- self.paths.insert(PathSet::Set(paths.iter().map(|p| TaskPath::parse(p)).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
+ ));
336
381
self
337
382
}
338
383
@@ -344,7 +389,8 @@ impl<'a> ShouldRun<'a> {
344
389
}
345
390
346
391
pub fn suite_path(mut self, suite: &str) -> Self {
347
- self.paths.insert(PathSet::Suite(TaskPath::parse(suite)));
392
+ self.paths
393
+ .insert(PathSet::Suite(TaskPath { path: suite.into(), kind: Some(self.kind.into()) }));
348
394
self
349
395
}
350
396
@@ -354,12 +400,12 @@ impl<'a> ShouldRun<'a> {
354
400
self
355
401
}
356
402
357
- fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> {
358
- 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) ))
359
405
}
360
406
}
361
407
362
- #[derive(Copy, Clone, PartialEq, Eq, Debug)]
408
+ #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
363
409
pub enum Kind {
364
410
Build,
365
411
Check,
@@ -373,11 +419,44 @@ pub enum Kind {
373
419
Run,
374
420
}
375
421
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
+
376
455
impl<'a> Builder<'a> {
377
456
fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
378
457
macro_rules! describe {
379
458
($($rule:ty),+ $(,)?) => {{
380
- vec![$(StepDescription::from::<$rule>()),+]
459
+ vec![$(StepDescription::from::<$rule>(kind )),+]
381
460
}};
382
461
}
383
462
match kind {
@@ -554,8 +633,11 @@ impl<'a> Builder<'a> {
554
633
555
634
let builder = Self::new_internal(build, kind, vec![]);
556
635
let builder = &builder;
557
- 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);
558
639
for desc in Builder::get_step_descriptions(builder.kind) {
640
+ should_run.kind = desc.kind;
559
641
should_run = (desc.should_run)(should_run);
560
642
}
561
643
let mut help = String::from("Available paths:\n");
@@ -1640,9 +1722,10 @@ impl<'a> Builder<'a> {
1640
1722
pub(crate) fn ensure_if_default<T, S: Step<Output = Option<T>>>(
1641
1723
&'a self,
1642
1724
step: S,
1725
+ kind: Kind,
1643
1726
) -> S::Output {
1644
- let desc = StepDescription::from::<S>();
1645
- 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 ));
1646
1729
1647
1730
// Avoid running steps contained in --exclude
1648
1731
for pathset in &should_run.paths {
@@ -1656,13 +1739,16 @@ impl<'a> Builder<'a> {
1656
1739
}
1657
1740
1658
1741
/// Checks if any of the "should_run" paths is in the `Builder` paths.
1659
- pub(crate) fn was_invoked_explicitly<S: Step>(&'a self) -> bool {
1660
- let desc = StepDescription::from::<S>();
1661
- 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 ));
1662
1745
1663
1746
for path in &self.paths {
1664
- if should_run.paths.iter().any(|s| s.has(path))
1665
- && !desc.is_excluded(self, &PathSet::Suite(TaskPath::parse(path)))
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
+ )
1666
1752
{
1667
1753
return true;
1668
1754
}
0 commit comments