|
1 | 1 | use std::any::{type_name, Any};
|
2 | 2 | use std::cell::{Cell, RefCell};
|
3 |
| -use std::collections::BTreeSet; |
| 3 | +use std::collections::{BTreeSet, HashMap}; |
4 | 4 | use std::env;
|
5 | 5 | use std::ffi::{OsStr, OsString};
|
6 | 6 | use std::fmt::{Debug, Write};
|
@@ -265,23 +265,9 @@ impl PathSet {
|
265 | 265 | }
|
266 | 266 | }
|
267 | 267 |
|
268 |
| - /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the |
269 |
| - /// matched needles. |
270 |
| - /// |
271 |
| - /// This is used for `StepDescription::krate`, which passes all matching crates at once to |
272 |
| - /// `Step::make_run`, rather than calling it many times with a single crate. |
273 |
| - /// See `tests.rs` for examples. |
274 |
| - fn intersection_removing_matches(&self, needles: &mut Vec<PathBuf>, module: Kind) -> PathSet { |
275 |
| - let mut check = |p| { |
276 |
| - for (i, n) in needles.iter().enumerate() { |
277 |
| - let matched = Self::check(p, n, module); |
278 |
| - if matched { |
279 |
| - needles.remove(i); |
280 |
| - return true; |
281 |
| - } |
282 |
| - } |
283 |
| - false |
284 |
| - }; |
| 268 | + /// Return all `TaskPath`s in `Self` that contain the `path`. |
| 269 | + fn intersection_pathset(&self, path: &Path, module: Kind) -> PathSet { |
| 270 | + let check = |p| Self::check(p, path, module); |
285 | 271 | match self {
|
286 | 272 | PathSet::Set(set) => PathSet::Set(set.iter().filter(|&p| check(p)).cloned().collect()),
|
287 | 273 | PathSet::Suite(suite) => {
|
@@ -473,14 +459,39 @@ impl StepDescription {
|
473 | 459 | return;
|
474 | 460 | }
|
475 | 461 |
|
476 |
| - // Handle all PathSets. |
477 |
| - for (desc, should_run) in v.iter().zip(&should_runs) { |
478 |
| - let pathsets = should_run.pathset_for_paths_removing_matches(&mut paths, desc.kind); |
479 |
| - if !pathsets.is_empty() { |
480 |
| - desc.maybe_run(builder, pathsets); |
| 462 | + // Special type that helps bootstrap to: |
| 463 | + // 1. keep the given CLI order on step execution |
| 464 | + // 2. keep all matching crates so we can pass them to `Step::make_run` at once, |
| 465 | + // rather than calling it many times with a single crate. |
| 466 | + let mut steps_to_run: HashMap<PathBuf, (&StepDescription, Vec<PathSet>)> = HashMap::new(); |
| 467 | + |
| 468 | + // Handle all PathSets |
| 469 | + for path in &paths { |
| 470 | + for (desc, should_run) in v.iter().zip(&should_runs) { |
| 471 | + let pathsets = should_run.resolve_pathsets(path, desc.kind); |
| 472 | + if !pathsets.is_empty() { |
| 473 | + steps_to_run |
| 474 | + .entry(path.clone()) |
| 475 | + .or_insert_with(|| (desc, Vec::new())) |
| 476 | + .1 |
| 477 | + .extend(pathsets); |
| 478 | + } |
481 | 479 | }
|
482 | 480 | }
|
483 | 481 |
|
| 482 | + // Start given steps and remove them from `paths`. |
| 483 | + paths.retain(|path| { |
| 484 | + if let Some((desc, pathsets)) = steps_to_run.remove(path) { |
| 485 | + desc.maybe_run(builder, pathsets); |
| 486 | + |
| 487 | + false |
| 488 | + } else { |
| 489 | + true |
| 490 | + } |
| 491 | + }); |
| 492 | + |
| 493 | + assert!(steps_to_run.is_empty(), "Some steps did not executed."); |
| 494 | + |
484 | 495 | if !paths.is_empty() {
|
485 | 496 | eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths,);
|
486 | 497 | eprintln!(
|
@@ -632,23 +643,18 @@ impl<'a> ShouldRun<'a> {
|
632 | 643 | self
|
633 | 644 | }
|
634 | 645 |
|
635 |
| - /// Given a set of requested paths, return the subset which match the Step for this `ShouldRun`, |
636 |
| - /// removing the matches from `paths`. |
| 646 | + /// Return the subset from given `path` and `kind` which match the `Step` for this `ShouldRun`. |
637 | 647 | ///
|
638 | 648 | /// NOTE: this returns multiple PathSets to allow for the possibility of multiple units of work
|
639 | 649 | /// within the same step. For example, `test::Crate` allows testing multiple crates in the same
|
640 | 650 | /// cargo invocation, which are put into separate sets because they aren't aliases.
|
641 | 651 | ///
|
642 | 652 | /// The reason we return PathSet instead of PathBuf is to allow for aliases that mean the same thing
|
643 | 653 | /// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?)
|
644 |
| - fn pathset_for_paths_removing_matches( |
645 |
| - &self, |
646 |
| - paths: &mut Vec<PathBuf>, |
647 |
| - kind: Kind, |
648 |
| - ) -> Vec<PathSet> { |
| 654 | + fn resolve_pathsets(&self, path: &Path, kind: Kind) -> Vec<PathSet> { |
649 | 655 | let mut sets = vec![];
|
650 | 656 | for pathset in &self.paths {
|
651 |
| - let subset = pathset.intersection_removing_matches(paths, kind); |
| 657 | + let subset = pathset.intersection_pathset(path, kind); |
652 | 658 | if subset != PathSet::empty() {
|
653 | 659 | sets.push(subset);
|
654 | 660 | }
|
|
0 commit comments