Skip to content

Commit 2f8bf34

Browse files
authored
Rollup merge of #106440 - jyn514:tidy, r=the8472
Ignore files in .gitignore in tidy - Switch from `walkdir` to `ignore`. This required various changes to make `skip` thread-safe. - Ignore `build` anywhere in the source tree, not just at the top-level. We support this in bootstrap, we should support it in tidy too. As a nice side benefit, this also makes tidy a bit faster. Before: ``` ; hyperfine -i '"/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/home/gh-jyn514/rust2" "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "/home/gh-jyn514/rust2/build" "32"' Benchmark 1: "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/home/gh-jyn514/rust2" "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "/home/gh-jyn514/rust2/build" "32" Time (mean ± σ): 1.080 s ± 0.008 s [User: 2.616 s, System: 3.243 s] Range (min … max): 1.069 s … 1.099 s 10 runs ``` After: ``` ; hyperfine '"/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/home/gh-jyn514/rust2" "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "/home/gh-jyn514/rust2/build" "32"' Benchmark 1: "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/home/gh-jyn514/rust2" "/home/gh-jyn514/rust2/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "/home/gh-jyn514/rust2/build" "32" Time (mean ± σ): 705.0 ms ± 1.4 ms [User: 3179.1 ms, System: 1517.5 ms] Range (min … max): 702.3 ms … 706.9 ms 10 runs ``` r? `@the8472`
2 parents 0d439f8 + 98334f6 commit 2f8bf34

File tree

16 files changed

+91
-108
lines changed

16 files changed

+91
-108
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ no_llvm_build
4141
/inst/
4242
/llvm/
4343
/mingw-build/
44-
/build/
44+
build/
4545
/build-rust-analyzer/
4646
/dist/
4747
/unicode-downloads

src/tools/replace-version-placeholder/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn main() {
1010
let version_str = version_str.trim();
1111
walk::walk(
1212
&root_path,
13-
&mut |path| {
13+
|path| {
1414
walk::filter_dirs(path)
1515
// We exempt these as they require the placeholder
1616
// for their operation

src/tools/tidy/src/alphabetical.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn check_section<'a>(
9595
}
9696

9797
pub fn check(path: &Path, bad: &mut bool) {
98-
walk(path, &mut filter_dirs, &mut |entry, contents| {
98+
walk(path, filter_dirs, &mut |entry, contents| {
9999
let file = &entry.path().display();
100100

101101
let mut lines = contents.lines().enumerate().peekable();

src/tools/tidy/src/bins.rs

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -101,54 +101,38 @@ mod os_impl {
101101

102102
const ALLOWED: &[&str] = &["configure", "x"];
103103

104-
walk_no_read(
105-
path,
106-
&mut |path| {
107-
filter_dirs(path)
108-
|| path.ends_with("src/etc")
109-
// This is a list of directories that we almost certainly
110-
// don't need to walk. A future PR will likely want to
111-
// remove these in favor of crate::walk_no_read using git
112-
// ls-files to discover the paths we should check, which
113-
// would naturally ignore all of these directories. It's
114-
// also likely faster than walking the directory tree
115-
// directly (since git is just reading from a couple files
116-
// to produce the results).
117-
|| path.ends_with("target")
118-
|| path.ends_with("build")
119-
|| path.ends_with(".git")
120-
},
121-
&mut |entry| {
122-
let file = entry.path();
123-
let extension = file.extension();
124-
let scripts = ["py", "sh", "ps1"];
125-
if scripts.into_iter().any(|e| extension == Some(OsStr::new(e))) {
126-
return;
127-
}
104+
// FIXME: we don't need to look at all binaries, only files that have been modified in this branch
105+
// (e.g. using `git ls-files`).
106+
walk_no_read(path, |path| filter_dirs(path) || path.ends_with("src/etc"), &mut |entry| {
107+
let file = entry.path();
108+
let extension = file.extension();
109+
let scripts = ["py", "sh", "ps1"];
110+
if scripts.into_iter().any(|e| extension == Some(OsStr::new(e))) {
111+
return;
112+
}
128113

129-
if t!(is_executable(&file), file) {
130-
let rel_path = file.strip_prefix(path).unwrap();
131-
let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
114+
if t!(is_executable(&file), file) {
115+
let rel_path = file.strip_prefix(path).unwrap();
116+
let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
132117

133-
if ALLOWED.contains(&git_friendly_path.as_str()) {
134-
return;
135-
}
118+
if ALLOWED.contains(&git_friendly_path.as_str()) {
119+
return;
120+
}
136121

137-
let output = Command::new("git")
138-
.arg("ls-files")
139-
.arg(&git_friendly_path)
140-
.current_dir(path)
141-
.stderr(Stdio::null())
142-
.output()
143-
.unwrap_or_else(|e| {
144-
panic!("could not run git ls-files: {e}");
145-
});
146-
let path_bytes = rel_path.as_os_str().as_bytes();
147-
if output.status.success() && output.stdout.starts_with(path_bytes) {
148-
tidy_error!(bad, "binary checked into source: {}", file.display());
149-
}
122+
let output = Command::new("git")
123+
.arg("ls-files")
124+
.arg(&git_friendly_path)
125+
.current_dir(path)
126+
.stderr(Stdio::null())
127+
.output()
128+
.unwrap_or_else(|e| {
129+
panic!("could not run git ls-files: {e}");
130+
});
131+
let path_bytes = rel_path.as_os_str().as_bytes();
132+
if output.status.success() && output.stdout.starts_with(path_bytes) {
133+
tidy_error!(bad, "binary checked into source: {}", file.display());
150134
}
151-
},
152-
)
135+
}
136+
})
153137
}
154138
}

src/tools/tidy/src/debug_artifacts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::path::Path;
66
const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
77

88
pub fn check(test_dir: &Path, bad: &mut bool) {
9-
walk(test_dir, &mut filter_dirs, &mut |entry, contents| {
9+
walk(test_dir, filter_dirs, &mut |entry, contents| {
1010
let filename = entry.path();
1111
let is_rust = filename.extension().map_or(false, |ext| ext == "rs");
1212
if !is_rust {

src/tools/tidy/src/edition.rs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,20 @@ fn is_edition_2021(mut line: &str) -> bool {
99
}
1010

1111
pub fn check(path: &Path, bad: &mut bool) {
12-
walk(
13-
path,
14-
&mut |path| {
15-
filter_dirs(path)
16-
|| (path.ends_with("tests") && path.join("COMPILER_TESTS.md").exists())
17-
},
18-
&mut |entry, contents| {
19-
let file = entry.path();
20-
let filename = file.file_name().unwrap();
21-
if filename != "Cargo.toml" {
22-
return;
23-
}
12+
walk(path, |path| filter_dirs(path), &mut |entry, contents| {
13+
let file = entry.path();
14+
let filename = file.file_name().unwrap();
15+
if filename != "Cargo.toml" {
16+
return;
17+
}
2418

25-
let is_2021 = contents.lines().any(is_edition_2021);
26-
if !is_2021 {
27-
tidy_error!(
28-
bad,
29-
"{} doesn't have `edition = \"2021\"` on a separate line",
30-
file.display()
31-
);
32-
}
33-
},
34-
);
19+
let is_2021 = contents.lines().any(is_edition_2021);
20+
if !is_2021 {
21+
tidy_error!(
22+
bad,
23+
"{} doesn't have `edition = \"2021\"` on a separate line",
24+
file.display()
25+
);
26+
}
27+
});
3528
}

src/tools/tidy/src/error_codes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ fn check_error_codes_docs(
127127

128128
let mut no_longer_emitted_codes = Vec::new();
129129

130-
walk(&docs_path, &mut |_| false, &mut |entry, contents| {
130+
walk(&docs_path, |_| false, &mut |entry, contents| {
131131
let path = entry.path();
132132

133133
// Error if the file isn't markdown.
@@ -319,7 +319,7 @@ fn check_error_codes_used(
319319

320320
let mut found_codes = Vec::new();
321321

322-
walk_many(search_paths, &mut filter_dirs, &mut |entry, contents| {
322+
walk_many(search_paths, filter_dirs, &mut |entry, contents| {
323323
let path = entry.path();
324324

325325
// Return early if we aren't looking at a source file.

src/tools/tidy/src/features.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ pub fn check(
101101
&tests_path.join("rustdoc-ui"),
102102
&tests_path.join("rustdoc"),
103103
],
104-
&mut filter_dirs,
104+
filter_dirs,
105105
&mut |entry, contents| {
106106
let file = entry.path();
107107
let filename = file.file_name().unwrap().to_string_lossy();
@@ -477,11 +477,11 @@ fn get_and_check_lib_features(
477477

478478
fn map_lib_features(
479479
base_src_path: &Path,
480-
mf: &mut dyn FnMut(Result<(&str, Feature), &str>, &Path, usize),
480+
mf: &mut (dyn Send + Sync + FnMut(Result<(&str, Feature), &str>, &Path, usize)),
481481
) {
482482
walk(
483483
base_src_path,
484-
&mut |path| filter_dirs(path) || path.ends_with("tests"),
484+
|path| filter_dirs(path) || path.ends_with("tests"),
485485
&mut |entry, contents| {
486486
let file = entry.path();
487487
let filename = file.file_name().unwrap().to_string_lossy();

src/tools/tidy/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ fn main() {
9191

9292
// Checks that need to be done for both the compiler and std libraries.
9393
check!(unit_tests, &src_path);
94-
check!(unit_tests, &tests_path);
9594
check!(unit_tests, &compiler_path);
9695
check!(unit_tests, &library_path);
9796

@@ -107,7 +106,6 @@ fn main() {
107106
check!(edition, &src_path);
108107
check!(edition, &compiler_path);
109108
check!(edition, &library_path);
110-
check!(edition, &tests_path);
111109

112110
check!(alphabetical, &src_path);
113111
check!(alphabetical, &tests_path);

src/tools/tidy/src/pal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn check(path: &Path, bad: &mut bool) {
6868
// Sanity check that the complex parsing here works.
6969
let mut saw_target_arch = false;
7070
let mut saw_cfg_bang = false;
71-
walk(path, &mut filter_dirs, &mut |entry, contents| {
71+
walk(path, filter_dirs, &mut |entry, contents| {
7272
let file = entry.path();
7373
let filestr = file.to_string_lossy().replace("\\", "/");
7474
if !filestr.ends_with(".rs") {

src/tools/tidy/src/rustdoc_gui_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::path::Path;
55
pub fn check(path: &Path, bad: &mut bool) {
66
crate::walk::walk(
77
&path.join("rustdoc-gui"),
8-
&mut |p| {
8+
|p| {
99
// If there is no extension, it's very likely a folder and we want to go into it.
1010
p.extension().map(|e| e != "goml").unwrap_or(false)
1111
},

src/tools/tidy/src/style.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ pub fn check(path: &Path, bad: &mut bool) {
235235
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
236236
.collect();
237237
let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap();
238-
walk(path, &mut skip, &mut |entry, contents| {
238+
walk(path, skip, &mut |entry, contents| {
239239
let file = entry.path();
240240
let filename = file.file_name().unwrap().to_string_lossy();
241241
let extensions =

src/tools/tidy/src/target_specific_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct RevisionInfo<'a> {
3737
pub fn check(path: &Path, bad: &mut bool) {
3838
crate::walk::walk(
3939
path,
40-
&mut |path| path.extension().map(|p| p == "rs") == Some(false),
40+
|path| path.extension().map(|p| p == "rs") == Some(false),
4141
&mut |entry, content| {
4242
let file = entry.path().display();
4343
let mut header_map = BTreeMap::new();

src/tools/tidy/src/ui_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn check_entries(path: &Path, bad: &mut bool) {
5454
pub fn check(path: &Path, bad: &mut bool) {
5555
check_entries(&path, bad);
5656
for path in &[&path.join("ui"), &path.join("ui-fulldeps")] {
57-
crate::walk::walk_no_read(path, &mut |_| false, &mut |entry| {
57+
crate::walk::walk_no_read(path, |_| false, &mut |entry| {
5858
let file_path = entry.path();
5959
if let Some(ext) = file_path.extension() {
6060
if ext == "stderr" || ext == "stdout" {

src/tools/tidy/src/unit_tests.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ use crate::walk::{filter_dirs, walk};
1111
use std::path::Path;
1212

1313
pub fn check(root_path: &Path, bad: &mut bool) {
14-
let core = &root_path.join("core");
15-
let core_tests = &core.join("tests");
16-
let core_benches = &core.join("benches");
17-
let is_core = |path: &Path| {
18-
path.starts_with(core) && !(path.starts_with(core_tests) || path.starts_with(core_benches))
14+
let core = root_path.join("core");
15+
let core_copy = core.clone();
16+
let core_tests = core.join("tests");
17+
let core_benches = core.join("benches");
18+
let is_core = move |path: &Path| {
19+
path.starts_with(&core)
20+
&& !(path.starts_with(&core_tests) || path.starts_with(&core_benches))
1921
};
2022

21-
let mut skip = |path: &Path| {
23+
let skip = move |path: &Path| {
2224
let file_name = path.file_name().unwrap_or_default();
2325
if path.is_dir() {
2426
filter_dirs(path)
25-
|| path.ends_with("tests")
2627
|| path.ends_with("src/doc")
2728
|| (file_name == "tests" || file_name == "benches") && !is_core(path)
2829
} else {
@@ -35,9 +36,9 @@ pub fn check(root_path: &Path, bad: &mut bool) {
3536
}
3637
};
3738

38-
walk(root_path, &mut skip, &mut |entry, contents| {
39+
walk(root_path, skip, &mut |entry, contents| {
3940
let path = entry.path();
40-
let is_core = path.starts_with(core);
41+
let is_core = path.starts_with(&core_copy);
4142
for (i, line) in contents.lines().enumerate() {
4243
let line = line.trim();
4344
let is_test = || line.contains("#[test]") && !line.contains("`#[test]");

src/tools/tidy/src/walk.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::fs::File;
2-
use std::io::Read;
3-
use walkdir::{DirEntry, WalkDir};
1+
use ignore::DirEntry;
42

5-
use std::path::Path;
3+
use std::{fs::File, io::Read, path::Path};
64

5+
/// The default directory filter.
76
pub fn filter_dirs(path: &Path) -> bool {
87
let skip = [
98
"tidy-test-file",
@@ -36,34 +35,42 @@ pub fn filter_dirs(path: &Path) -> bool {
3635

3736
pub fn walk_many(
3837
paths: &[&Path],
39-
skip: &mut dyn FnMut(&Path) -> bool,
38+
skip: impl Clone + Send + Sync + 'static + Fn(&Path) -> bool,
4039
f: &mut dyn FnMut(&DirEntry, &str),
4140
) {
4241
for path in paths {
43-
walk(path, skip, f);
42+
walk(path, skip.clone(), f);
4443
}
4544
}
4645

47-
pub fn walk(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)) {
48-
let mut contents = String::new();
46+
pub fn walk(
47+
path: &Path,
48+
skip: impl Send + Sync + 'static + Fn(&Path) -> bool,
49+
f: &mut dyn FnMut(&DirEntry, &str),
50+
) {
51+
let mut contents = Vec::new();
4952
walk_no_read(path, skip, &mut |entry| {
5053
contents.clear();
51-
if t!(File::open(entry.path()), entry.path()).read_to_string(&mut contents).is_err() {
52-
contents.clear();
53-
}
54-
f(&entry, &contents);
54+
let mut file = t!(File::open(entry.path()), entry.path());
55+
t!(file.read_to_end(&mut contents), entry.path());
56+
let contents_str = match std::str::from_utf8(&contents) {
57+
Ok(s) => s,
58+
Err(_) => return, // skip this file
59+
};
60+
f(&entry, &contents_str);
5561
});
5662
}
5763

5864
pub(crate) fn walk_no_read(
5965
path: &Path,
60-
skip: &mut dyn FnMut(&Path) -> bool,
66+
skip: impl Send + Sync + 'static + Fn(&Path) -> bool,
6167
f: &mut dyn FnMut(&DirEntry),
6268
) {
63-
let walker = WalkDir::new(path).into_iter().filter_entry(|e| !skip(e.path()));
64-
for entry in walker {
69+
let mut walker = ignore::WalkBuilder::new(path);
70+
let walker = walker.filter_entry(move |e| !skip(e.path()));
71+
for entry in walker.build() {
6572
if let Ok(entry) = entry {
66-
if entry.file_type().is_dir() {
73+
if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) {
6774
continue;
6875
}
6976
f(&entry);

0 commit comments

Comments
 (0)