run_make_support/
path_helpers.rs1use std::path::{Path, PathBuf};
4
5use crate::env::env_var;
6use crate::rfs;
7
8#[must_use]
13pub fn cwd() -> PathBuf {
14 std::env::current_dir().unwrap()
15}
16
17pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
28 cwd().join(p.as_ref())
29}
30
31#[must_use]
33pub fn source_root() -> PathBuf {
34 env_var("SOURCE_ROOT").into()
35}
36
37#[must_use]
39pub fn build_root() -> PathBuf {
40 env_var("BUILD_ROOT").into()
41}
42
43#[track_caller]
46pub fn shallow_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
47 path: P,
48 filter: F,
49) -> Vec<PathBuf> {
50 let mut matching_files = Vec::new();
51 for entry in rfs::read_dir(path) {
52 let entry = entry.expect("failed to read directory entry.");
53 let path = entry.path();
54
55 if path.is_file() && filter(&path) {
56 matching_files.push(path);
57 }
58 }
59 matching_files
60}
61
62#[track_caller]
65pub fn recursive_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
66 path: P,
67 filter: F,
68) -> Vec<PathBuf> {
69 let mut matching_files = Vec::new();
70 let mut stack = vec![path.as_ref().to_path_buf()];
71 while let Some(dir) = stack.pop() {
72 for entry in rfs::read_dir(dir) {
73 let entry = entry.expect("failed to read directory entry.");
74 let path = entry.path();
75
76 if path.is_dir() {
77 stack.push(path);
78 } else if path.is_file() && filter(&path) {
79 matching_files.push(path);
80 }
81 }
82 }
83 matching_files
84}
85
86#[track_caller]
89pub fn shallow_find_directories<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
90 path: P,
91 filter: F,
92) -> Vec<PathBuf> {
93 let mut matching_files = Vec::new();
94 for entry in rfs::read_dir(path) {
95 let entry = entry.expect("failed to read directory entry.");
96 let path = entry.path();
97
98 if path.is_dir() && filter(&path) {
99 matching_files.push(path);
100 }
101 }
102 matching_files
103}
104
105pub fn not_contains<P: AsRef<Path>>(path: P, expected: &str) -> bool {
107 !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected))
108}
109
110pub fn filename_not_in_denylist<P: AsRef<Path>, V: AsRef<[String]>>(path: P, expected: V) -> bool {
112 let expected = expected.as_ref();
113 path.as_ref()
114 .file_name()
115 .is_some_and(|name| !expected.contains(&name.to_str().unwrap().to_owned()))
116}
117
118pub fn has_prefix<P: AsRef<Path>>(path: P, prefix: &str) -> bool {
120 path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().starts_with(prefix))
121}
122
123pub fn has_extension<P: AsRef<Path>>(path: P, extension: &str) -> bool {
125 path.as_ref().extension().is_some_and(|ext| ext == extension)
126}
127
128pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
130 path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().ends_with(suffix))
131}
132
133pub fn filename_contains<P: AsRef<Path>>(path: P, needle: &str) -> bool {
135 path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle))
136}
137
138pub fn read_dir_entries_recursive<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
140 fn read_dir_entries_recursive_inner<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, callback: &mut F) {
141 for entry in rfs::read_dir(dir) {
142 let path = entry.unwrap().path();
143 callback(&path);
144 if path.is_dir() {
145 read_dir_entries_recursive_inner(path, callback);
146 }
147 }
148 }
149
150 read_dir_entries_recursive_inner(dir, &mut callback);
151}