Skip to content

Commit 8a2c36e

Browse files
committed
support glob patterns
1 parent 215485c commit 8a2c36e

File tree

4 files changed

+48
-38
lines changed

4 files changed

+48
-38
lines changed

Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cpp-linter-lib/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ documentation.workspace = true
1010
[dependencies]
1111
chrono = "0.4.38"
1212
clap = "4.5.16"
13+
fast-glob = "0.4.0"
1314
futures = "0.3.30"
1415
git2 = "0.19.0"
1516
lenient_semver = "0.4.2"

cpp-linter-lib/src/common_fs/file_filter.rs

+39-38
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::{
33
path::{Path, PathBuf},
44
};
55

6+
use fast_glob::glob_match;
7+
68
use super::FileObj;
79

810
#[derive(Debug, Clone)]
@@ -76,35 +78,41 @@ impl FileFilter {
7678
}
7779
}
7880

79-
/// Describes if a specified `file_name` is contained within the given `set` of paths.
81+
/// Describes if a specified `file_name` is contained within the specified set of paths.
8082
///
81-
/// The `is_ignored` flag describes which list of paths is used as domains.
83+
/// The `is_ignored` flag describes which set of paths is used as domains.
8284
/// The specified `file_name` can be a direct or distant descendant of any paths in
83-
/// the list.
85+
/// the set.
8486
///
85-
/// Returns a [`Some`] value of the the path/pattern that matches the given `file_name`.
86-
/// If given `file_name` is not in the specified list, then [`None`] is returned.
87-
pub fn is_file_in_list(&self, file_name: &Path, is_ignored: bool) -> Option<String> {
87+
/// Returns a `true` value of the the path/pattern that matches the given `file_name`.
88+
/// If given `file_name` is not in the specified set, then `false` is returned.
89+
pub fn is_file_in_list(&self, file_name: &Path, is_ignored: bool) -> bool {
8890
let file_name = PathBuf::from(format!(
8991
"./{}",
9092
file_name
9193
.as_os_str()
9294
.to_string_lossy()
9395
.to_string()
9496
.replace("\\", "/")
97+
.trim_start_matches("./")
9598
));
9699
let set = if is_ignored {
97100
&self.ignored
98101
} else {
99102
&self.not_ignored
100103
};
101104
for pattern in set {
105+
let glob_matched =
106+
glob_match(pattern, file_name.to_string_lossy().to_string().as_str());
102107
let pat = PathBuf::from(&pattern);
103-
if (pat.is_file() && file_name == pat) || (pat.is_dir() && file_name.starts_with(pat)) {
104-
return Some(pattern.to_owned());
108+
if glob_matched
109+
|| (pat.is_file() && file_name == pat)
110+
|| (pat.is_dir() && file_name.starts_with(pat))
111+
{
112+
return true;
105113
}
106114
}
107-
None
115+
false
108116
}
109117

110118
/// A helper function that checks if `entry` satisfies the following conditions (in
@@ -130,7 +138,7 @@ impl FileFilter {
130138
if !is_ignored {
131139
let is_in_ignored = self.is_file_in_list(entry, true);
132140
let is_in_not_ignored = self.is_file_in_list(entry, false);
133-
if is_in_not_ignored.is_some() || is_in_ignored.is_none() {
141+
if is_in_not_ignored || !is_in_ignored {
134142
return true;
135143
}
136144
}
@@ -145,7 +153,7 @@ impl FileFilter {
145153
pub fn list_source_files(&self, root_path: &str) -> Vec<FileObj> {
146154
let mut files: Vec<FileObj> = Vec::new();
147155
let entries = fs::read_dir(root_path).expect("repo root-path should exist");
148-
for entry in entries.flatten() {
156+
for entry in entries.filter_map(|p| p.ok()) {
149157
let path = entry.path();
150158
if path.is_dir() {
151159
let mut is_hidden = false;
@@ -196,34 +204,31 @@ mod tests {
196204
#[test]
197205
fn ignore_src() {
198206
let file_filter = setup_ignore("src", vec![]);
199-
assert!(file_filter
200-
.is_file_in_list(&PathBuf::from("./src/lib.rs"), true)
201-
.is_some());
202-
assert!(file_filter
203-
.is_file_in_list(&PathBuf::from("./src/lib.rs"), false)
204-
.is_none());
207+
assert!(file_filter.is_file_in_list(&PathBuf::from("./src/lib.rs"), true));
208+
assert!(!file_filter.is_file_in_list(&PathBuf::from("./src/lib.rs"), false));
205209
}
206210

207211
#[test]
208212
fn ignore_root() {
209213
let file_filter = setup_ignore("!src/lib.rs|./", vec![]);
210-
assert!(file_filter
211-
.is_file_in_list(&PathBuf::from("./cargo.toml"), true)
212-
.is_some());
213-
assert!(file_filter
214-
.is_file_in_list(&PathBuf::from("./src/lib.rs"), false)
215-
.is_some());
214+
assert!(file_filter.is_file_in_list(&PathBuf::from("./Cargo.toml"), true));
215+
assert!(file_filter.is_file_in_list(&PathBuf::from("./src/lib.rs"), false));
216216
}
217217

218218
#[test]
219219
fn ignore_root_implicit() {
220220
let file_filter = setup_ignore("!src|", vec![]);
221-
assert!(file_filter
222-
.is_file_in_list(&PathBuf::from("./cargo.toml"), true)
223-
.is_some());
224-
assert!(file_filter
225-
.is_file_in_list(&PathBuf::from("./src/lib.rs"), false)
226-
.is_some());
221+
assert!(file_filter.is_file_in_list(&PathBuf::from("./Cargo.toml"), true));
222+
assert!(file_filter.is_file_in_list(&PathBuf::from("./src/lib.rs"), false));
223+
}
224+
225+
#[test]
226+
fn ignore_glob() {
227+
let file_filter = setup_ignore("!src/**/*", vec![]);
228+
assert!(file_filter.is_file_in_list(&PathBuf::from("./src/lib.rs"), false));
229+
assert!(
230+
file_filter.is_file_in_list(&PathBuf::from("./src/common_fs/file_filter.rs"), false)
231+
);
227232
}
228233

229234
#[test]
@@ -235,17 +240,13 @@ mod tests {
235240
// using Vec::contains() because these files don't actually exist in project files
236241
for ignored_submodule in ["./RF24", "./RF24Network", "./RF24Mesh"] {
237242
assert!(file_filter.ignored.contains(&ignored_submodule.to_string()));
238-
assert!(file_filter
239-
.is_file_in_list(
240-
&PathBuf::from(ignored_submodule.to_string() + "/some_src.cpp"),
241-
true
242-
)
243-
.is_none());
243+
assert!(!file_filter.is_file_in_list(
244+
&PathBuf::from(ignored_submodule.to_string() + "/some_src.cpp"),
245+
true
246+
));
244247
}
245248
assert!(file_filter.not_ignored.contains(&"./pybind11".to_string()));
246-
assert!(file_filter
247-
.is_file_in_list(&PathBuf::from("./pybind11/some_src.cpp"), false)
248-
.is_none());
249+
assert!(!file_filter.is_file_in_list(&PathBuf::from("./pybind11/some_src.cpp"), false));
249250
}
250251

251252
// *********************** tests for recursive path search
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This file is here for completeness when testig file filters.

0 commit comments

Comments
 (0)