1use std::ffi::OsStr;
2use std::fs::File;
3use std::io::Read;
4use std::path::Path;
5
6use ignore::DirEntry;
7
8pub fn filter_dirs(path: &Path) -> bool {
10 let skip = [
12 "tidy-test-file",
13 "compiler/rustc_codegen_cranelift",
14 "compiler/rustc_codegen_gcc",
15 "src/llvm-project",
16 "library/backtrace",
17 "library/compiler-builtins",
18 "library/portable-simd",
19 "library/stdarch",
20 "src/tools/cargo",
21 "src/tools/clippy",
22 "src/tools/libcxx-version",
23 "src/tools/miri",
24 "src/tools/rust-analyzer",
25 "src/tools/rustc-perf",
26 "src/tools/rustfmt",
27 "src/tools/enzyme",
28 "src/doc/book",
29 "src/doc/edition-guide",
30 "src/doc/embedded-book",
31 "src/doc/nomicon",
32 "src/doc/rust-by-example",
33 "src/doc/rustc-dev-guide",
34 "src/doc/reference",
35 "src/gcc",
36 "src/bootstrap/target",
37 "vendor",
38 ];
39 skip.iter().any(|p| path.ends_with(p))
40}
41
42pub fn filter_not_rust(path: &Path) -> bool {
44 path.extension() != Some(OsStr::new("rs")) && !path.is_dir()
45}
46
47pub fn walk(
48 path: &Path,
49 skip: impl Send + Sync + 'static + Fn(&Path, bool) -> bool,
50 f: &mut dyn FnMut(&DirEntry, &str),
51) {
52 walk_many(&[path], skip, f);
53}
54
55pub fn walk_many(
56 paths: &[&Path],
57 skip: impl Send + Sync + 'static + Fn(&Path, bool) -> bool,
58 f: &mut dyn FnMut(&DirEntry, &str),
59) {
60 let mut contents = Vec::new();
61 walk_no_read(paths, skip, &mut |entry| {
62 contents.clear();
63 let mut file = t!(File::open(entry.path()), entry.path());
64 t!(file.read_to_end(&mut contents), entry.path());
65 let contents_str = match std::str::from_utf8(&contents) {
66 Ok(s) => s,
67 Err(_) => return, };
69 f(&entry, &contents_str);
70 });
71}
72
73pub(crate) fn walk_no_read(
74 paths: &[&Path],
75 skip: impl Send + Sync + 'static + Fn(&Path, bool) -> bool,
76 f: &mut dyn FnMut(&DirEntry),
77) {
78 let mut walker = ignore::WalkBuilder::new(paths[0]);
79 for path in &paths[1..] {
80 walker.add(path);
81 }
82 let walker = walker.filter_entry(move |e| {
83 !skip(e.path(), e.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
84 });
85 for entry in walker.build().flatten() {
86 if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) {
87 continue;
88 }
89 f(&entry);
90 }
91}
92
93pub(crate) fn walk_dir(
95 path: &Path,
96 skip: impl Send + Sync + 'static + Fn(&Path) -> bool,
97 f: &mut dyn FnMut(&DirEntry),
98) {
99 let mut walker = ignore::WalkBuilder::new(path);
100 let walker = walker.filter_entry(move |e| !skip(e.path()));
101 for entry in walker.build().flatten() {
102 if entry.path().is_dir() {
103 f(&entry);
104 }
105 }
106}