diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 3c4806a1311..19f40fab2c0 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -274,7 +274,7 @@ fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool { /// This is used for `StepDescription::krate`, which passes all matching crates at once to /// `Step::make_run`, rather than calling it many times with a single crate. /// See `tests.rs` for examples. - fn intersection_removing_matches(&self, needles: &mut Vec<&Path>, module: Kind) -> PathSet { + fn intersection_removing_matches(&self, needles: &mut Vec, module: Kind) -> PathSet { let mut check = |p| { for (i, n) in needles.iter().enumerate() { let matched = Self::check(p, n, module); @@ -346,7 +346,7 @@ pub fn assert_single_path(&self) -> &TaskPath { ), ]; -fn remap_paths(paths: &mut Vec<&Path>) { +fn remap_paths(paths: &mut Vec) { let mut remove = vec![]; let mut add = vec![]; for (i, path) in paths.iter().enumerate().filter_map(|(i, path)| path.to_str().map(|s| (i, s))) @@ -355,7 +355,7 @@ fn remap_paths(paths: &mut Vec<&Path>) { // Remove leading and trailing slashes so `tests/` and `tests` are equivalent if path.trim_matches(std::path::is_separator) == search { remove.push(i); - add.extend(replace.iter().map(Path::new)); + add.extend(replace.iter().map(PathBuf::from)); break; } } @@ -438,8 +438,25 @@ fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) { } } - // strip CurDir prefix if present - let mut paths: Vec<_> = paths.iter().map(|p| p.strip_prefix(".").unwrap_or(p)).collect(); + // Attempt to resolve paths to be relative to the builder source directory. + let mut paths: Vec = paths + .iter() + .map(|p| { + // If the path does not exist, it may represent the name of a Step, such as `tidy` in `x test tidy` + if !p.exists() { + return p.clone(); + } + + // Make the path absolute, strip the prefix, and convert to a PathBuf. + match std::path::absolute(p) { + Ok(p) => p.strip_prefix(&builder.src).unwrap_or(&p).to_path_buf(), + Err(e) => { + eprintln!("ERROR: {:?}", e); + panic!("Due to the above error, failed to resolve path: {:?}", p); + } + } + }) + .collect(); remap_paths(&mut paths); @@ -629,7 +646,7 @@ pub fn never(mut self) -> ShouldRun<'a> { /// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?) fn pathset_for_paths_removing_matches( &self, - paths: &mut Vec<&Path>, + paths: &mut Vec, kind: Kind, ) -> Vec { let mut sets = vec![]; diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 276fd0b11d6..aa119b8c699 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -122,11 +122,14 @@ fn test_intersection() { PathSet::Set(paths.into_iter().map(|p| TaskPath { path: p.into(), kind: None }).collect()) }; let library_set = set(&["library/core", "library/alloc", "library/std"]); - let mut command_paths = - vec![Path::new("library/core"), Path::new("library/alloc"), Path::new("library/stdarch")]; + let mut command_paths = vec![ + PathBuf::from("library/core"), + PathBuf::from("library/alloc"), + PathBuf::from("library/stdarch"), + ]; let subset = library_set.intersection_removing_matches(&mut command_paths, Kind::Build); assert_eq!(subset, set(&["library/core", "library/alloc"]),); - assert_eq!(command_paths, vec![Path::new("library/stdarch")]); + assert_eq!(command_paths, vec![PathBuf::from("library/stdarch")]); } #[test]