##// END OF EJS Templates
rust-matchers: implement `visit_children_set` for `FileMatcher`...
Raphaël Gomès -
r44828:54d185eb default
parent child Browse files
Show More
@@ -10,7 +10,9 b''
10 use crate::{utils::hg_path::HgPath, DirsMultiset, DirstateMapError};
10 use crate::{utils::hg_path::HgPath, DirsMultiset, DirstateMapError};
11 use std::collections::HashSet;
11 use std::collections::HashSet;
12 use std::iter::FromIterator;
12 use std::iter::FromIterator;
13 use std::ops::Deref;
13
14
15 #[derive(Debug, PartialEq)]
14 pub enum VisitChildrenSet<'a> {
16 pub enum VisitChildrenSet<'a> {
15 /// Don't visit anything
17 /// Don't visit anything
16 Empty,
18 Empty,
@@ -163,12 +165,48 b" impl<'a> Matcher for FileMatcher<'a> {"
163 }
165 }
164 fn visit_children_set(
166 fn visit_children_set(
165 &self,
167 &self,
166 _directory: impl AsRef<HgPath>,
168 directory: impl AsRef<HgPath>,
167 ) -> VisitChildrenSet {
169 ) -> VisitChildrenSet {
168 // TODO implement once we have `status.traverse`
170 if self.files.is_empty() || !self.dirs.contains(&directory) {
169 // This is useless until unknown files are taken into account
171 return VisitChildrenSet::Empty;
170 // Which will not need to happen before the `IncludeMatcher`.
172 }
171 unimplemented!()
173 let dirs_as_set = self.dirs.iter().map(|k| k.deref()).collect();
174
175 let mut candidates: HashSet<&HgPath> =
176 self.files.union(&dirs_as_set).map(|k| *k).collect();
177 candidates.remove(HgPath::new(b""));
178
179 if !directory.as_ref().is_empty() {
180 let directory = [directory.as_ref().as_bytes(), b"/"].concat();
181 candidates = candidates
182 .iter()
183 .filter_map(|c| {
184 if c.as_bytes().starts_with(&directory) {
185 Some(HgPath::new(&c.as_bytes()[directory.len()..]))
186 } else {
187 None
188 }
189 })
190 .collect();
191 }
192
193 // `self.dirs` includes all of the directories, recursively, so if
194 // we're attempting to match 'foo/bar/baz.txt', it'll have '', 'foo',
195 // 'foo/bar' in it. Thus we can safely ignore a candidate that has a
196 // '/' in it, indicating it's for a subdir-of-a-subdir; the immediate
197 // subdir will be in there without a slash.
198 VisitChildrenSet::Set(
199 candidates
200 .iter()
201 .filter_map(|c| {
202 if c.bytes().all(|b| *b != b'/') {
203 Some(*c)
204 } else {
205 None
206 }
207 })
208 .collect(),
209 )
172 }
210 }
173 fn matches_everything(&self) -> bool {
211 fn matches_everything(&self) -> bool {
174 false
212 false
@@ -177,3 +215,107 b" impl<'a> Matcher for FileMatcher<'a> {"
177 true
215 true
178 }
216 }
179 }
217 }
218 #[cfg(test)]
219 mod tests {
220 use super::*;
221 use pretty_assertions::assert_eq;
222
223 #[test]
224 fn test_filematcher_visit_children_set() {
225 // Visitchildrenset
226 let files = vec![HgPath::new(b"dir/subdir/foo.txt")];
227 let matcher = FileMatcher::new(&files).unwrap();
228
229 let mut set = HashSet::new();
230 set.insert(HgPath::new(b"dir"));
231 assert_eq!(
232 matcher.visit_children_set(HgPath::new(b"")),
233 VisitChildrenSet::Set(set)
234 );
235
236 let mut set = HashSet::new();
237 set.insert(HgPath::new(b"subdir"));
238 assert_eq!(
239 matcher.visit_children_set(HgPath::new(b"dir")),
240 VisitChildrenSet::Set(set)
241 );
242
243 let mut set = HashSet::new();
244 set.insert(HgPath::new(b"foo.txt"));
245 assert_eq!(
246 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
247 VisitChildrenSet::Set(set)
248 );
249
250 assert_eq!(
251 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
252 VisitChildrenSet::Empty
253 );
254 assert_eq!(
255 matcher.visit_children_set(HgPath::new(b"dir/subdir/foo.txt")),
256 VisitChildrenSet::Empty
257 );
258 assert_eq!(
259 matcher.visit_children_set(HgPath::new(b"folder")),
260 VisitChildrenSet::Empty
261 );
262 }
263
264 #[test]
265 fn test_filematcher_visit_children_set_files_and_dirs() {
266 let files = vec![
267 HgPath::new(b"rootfile.txt"),
268 HgPath::new(b"a/file1.txt"),
269 HgPath::new(b"a/b/file2.txt"),
270 // No file in a/b/c
271 HgPath::new(b"a/b/c/d/file4.txt"),
272 ];
273 let matcher = FileMatcher::new(&files).unwrap();
274
275 let mut set = HashSet::new();
276 set.insert(HgPath::new(b"a"));
277 set.insert(HgPath::new(b"rootfile.txt"));
278 assert_eq!(
279 matcher.visit_children_set(HgPath::new(b"")),
280 VisitChildrenSet::Set(set)
281 );
282
283 let mut set = HashSet::new();
284 set.insert(HgPath::new(b"b"));
285 set.insert(HgPath::new(b"file1.txt"));
286 assert_eq!(
287 matcher.visit_children_set(HgPath::new(b"a")),
288 VisitChildrenSet::Set(set)
289 );
290
291 let mut set = HashSet::new();
292 set.insert(HgPath::new(b"c"));
293 set.insert(HgPath::new(b"file2.txt"));
294 assert_eq!(
295 matcher.visit_children_set(HgPath::new(b"a/b")),
296 VisitChildrenSet::Set(set)
297 );
298
299 let mut set = HashSet::new();
300 set.insert(HgPath::new(b"d"));
301 assert_eq!(
302 matcher.visit_children_set(HgPath::new(b"a/b/c")),
303 VisitChildrenSet::Set(set)
304 );
305 let mut set = HashSet::new();
306 set.insert(HgPath::new(b"file4.txt"));
307 assert_eq!(
308 matcher.visit_children_set(HgPath::new(b"a/b/c/d")),
309 VisitChildrenSet::Set(set)
310 );
311
312 assert_eq!(
313 matcher.visit_children_set(HgPath::new(b"a/b/c/d/e")),
314 VisitChildrenSet::Empty
315 );
316 assert_eq!(
317 matcher.visit_children_set(HgPath::new(b"folder")),
318 VisitChildrenSet::Empty
319 );
320 }
321 }
General Comments 0
You need to be logged in to leave comments. Login now