findutils/find/matchers/
name.rs1use super::glob::Pattern;
8use super::{Matcher, MatcherIO, WalkEntry};
9
10pub struct NameMatcher {
13 pattern: Pattern,
14}
15
16impl NameMatcher {
17 pub fn new(pattern_string: &str, caseless: bool) -> Self {
18 let pattern = Pattern::new(pattern_string, caseless);
19 Self { pattern }
20 }
21}
22
23impl Matcher for NameMatcher {
24 fn matches(&self, file_info: &WalkEntry, _: &mut MatcherIO) -> bool {
25 let name = file_info.file_name().to_string_lossy();
26
27 #[cfg(unix)]
28 if name.len() > 1 && name.chars().all(|x| x == '/') {
29 self.pattern.matches("/")
30 } else {
31 self.pattern.matches(&name)
32 }
33
34 #[cfg(windows)]
35 self.pattern.matches(&name)
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::find::matchers::tests::get_dir_entry_for;
43 use crate::find::tests::FakeDependencies;
44 use std::io::ErrorKind;
45
46 #[cfg(unix)]
47 use std::os::unix::fs::symlink;
48
49 #[cfg(windows)]
50 use std::os::windows::fs::symlink_file;
51
52 fn create_file_link() {
53 #[cfg(unix)]
54 if let Err(e) = symlink("abbbc", "test_data/links/link-f") {
55 assert!(
56 e.kind() == ErrorKind::AlreadyExists,
57 "Failed to create sym link: {e:?}"
58 );
59 }
60 #[cfg(windows)]
61 if let Err(e) = symlink_file("abbbc", "test_data/links/link-f") {
62 assert!(
63 e.kind() == ErrorKind::AlreadyExists,
64 "Failed to create sym link: {:?}",
65 e
66 );
67 }
68 }
69
70 #[test]
71 fn matching_with_wrong_case_returns_false() {
72 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
73 let matcher = NameMatcher::new("A*C", false);
74 let deps = FakeDependencies::new();
75 assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
76 }
77
78 #[test]
79 fn matching_with_right_case_returns_true() {
80 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
81 let matcher = NameMatcher::new("abb?c", false);
82 let deps = FakeDependencies::new();
83 assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
84 }
85
86 #[test]
87 fn not_matching_returns_false() {
88 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
89 let matcher = NameMatcher::new("shouldn't match", false);
90 let deps = FakeDependencies::new();
91 assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
92 }
93
94 #[test]
95 fn matches_against_link_file_name() {
96 create_file_link();
97
98 let link_f = get_dir_entry_for("test_data/links", "link-f");
99 let matcher = NameMatcher::new("link?f", false);
100 let deps = FakeDependencies::new();
101 assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
102 }
103
104 #[test]
105 fn caseless_matching_with_wrong_case_returns_true() {
106 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
107 let matcher = NameMatcher::new("A*C", true);
108 let deps = FakeDependencies::new();
109 assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
110 }
111
112 #[test]
113 fn caseless_matching_with_right_case_returns_true() {
114 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
115 let matcher = NameMatcher::new("abb?c", true);
116 let deps = FakeDependencies::new();
117 assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
118 }
119
120 #[test]
121 fn caseless_not_matching_returns_false() {
122 let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
123 let matcher = NameMatcher::new("shouldn't match", true);
124 let deps = FakeDependencies::new();
125 assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
126 }
127
128 #[test]
129 fn caseless_matches_against_link_file_name() {
130 create_file_link();
131
132 let link_f = get_dir_entry_for("test_data/links", "link-f");
133 let matcher = NameMatcher::new("linK?f", true);
134 let deps = FakeDependencies::new();
135 assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
136 }
137
138 #[test]
139 #[cfg(unix)]
140 fn slash_match_returns_true() {
141 let dir_to_match = get_dir_entry_for("///", "");
142 let matcher = NameMatcher::new("/", true);
143 let deps = FakeDependencies::new();
144 assert!(matcher.matches(&dir_to_match, &mut deps.new_matcher_io()));
145 }
146
147 #[test]
148 #[cfg(unix)]
149 fn only_one_slash() {
150 let dir_to_match = get_dir_entry_for("/", "");
151 let matcher = NameMatcher::new("/", false);
152 let deps = FakeDependencies::new();
153 assert!(matcher.matches(&dir_to_match, &mut deps.new_matcher_io()));
154 }
155}