Skip to content

Commit b10d744

Browse files
committed
Allow shortcuts to directories to be used for ./x.py fmt
Fixes #107944. Maximum recursive search depth is 3 and only accepts shortcuts for directories (single component paths, such as `./x.py fmt std`). If there are no shortcut candidates but single componenet path(s) are given, it falls back to the previous behavior to panic with unable to find directory. If there are multiple shortcut candidates for a given single component path, the shortcut candidates are considered ambiguous, are then ignored, and the single component path is accepted as-is. After this change, `./x.py fmt std` no longer panics and formats `library/std` instead.
1 parent b7089e0 commit b10d744

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

src/bootstrap/format.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,46 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
193193
let (tx, rx): (SyncSender<PathBuf>, _) = std::sync::mpsc::sync_channel(128);
194194
let walker = match paths.get(0) {
195195
Some(first) => {
196-
let mut walker = WalkBuilder::new(first);
196+
let find_shortcut_candidates = |p: &PathBuf| {
197+
let mut candidates = Vec::new();
198+
for candidate in WalkBuilder::new(src.clone()).max_depth(Some(3)).build() {
199+
if let Ok(entry) = candidate {
200+
if let Some(dir_name) = p.file_name() {
201+
if entry.path().is_dir() && entry.file_name() == dir_name {
202+
candidates.push(entry.into_path());
203+
}
204+
}
205+
}
206+
}
207+
candidates
208+
};
209+
210+
// Only try to look for shortcut candidates for single component paths like
211+
// `std` and not for e.g. relative paths like `../library/std`.
212+
let should_look_for_shortcut_dir = |p: &PathBuf| p.components().count() == 1;
213+
214+
let mut walker = if should_look_for_shortcut_dir(first) {
215+
if let [single_candidate] = &find_shortcut_candidates(first)[..] {
216+
WalkBuilder::new(single_candidate)
217+
} else {
218+
WalkBuilder::new(first)
219+
}
220+
} else {
221+
WalkBuilder::new(first)
222+
};
223+
197224
for path in &paths[1..] {
198-
walker.add(path);
225+
if should_look_for_shortcut_dir(path) {
226+
if let [single_candidate] = &find_shortcut_candidates(path)[..] {
227+
walker.add(single_candidate);
228+
} else {
229+
walker.add(path);
230+
}
231+
} else {
232+
walker.add(path);
233+
}
199234
}
235+
200236
walker
201237
}
202238
None => WalkBuilder::new(src.clone()),

0 commit comments

Comments
 (0)