##// END OF EJS Templates
rust-matchers: add functions to get roots, dirs and parents from patterns...
Raphaël Gomès -
r45007:d4e8cfcd default
parent child Browse files
Show More
@@ -10,8 +10,10 b''
10 #[cfg(feature = "with-re2")]
10 #[cfg(feature = "with-re2")]
11 use crate::re2::Re2;
11 use crate::re2::Re2;
12 use crate::{
12 use crate::{
13 filepatterns::PatternResult, utils::hg_path::HgPath, DirsMultiset,
13 filepatterns::PatternResult,
14 DirstateMapError, PatternError,
14 utils::hg_path::{HgPath, HgPathBuf},
15 DirsMultiset, DirstateMapError, IgnorePattern, PatternError,
16 PatternSyntax,
15 };
17 };
16 use std::collections::HashSet;
18 use std::collections::HashSet;
17 use std::iter::FromIterator;
19 use std::iter::FromIterator;
@@ -240,10 +242,156 b' fn re_matcher(_: &[u8]) -> PatternResult'
240 Err(PatternError::Re2NotInstalled)
242 Err(PatternError::Re2NotInstalled)
241 }
243 }
242
244
245 /// Returns roots and directories corresponding to each pattern.
246 ///
247 /// This calculates the roots and directories exactly matching the patterns and
248 /// returns a tuple of (roots, dirs). It does not return other directories
249 /// which may also need to be considered, like the parent directories.
250 fn roots_and_dirs(
251 ignore_patterns: &[IgnorePattern],
252 ) -> (Vec<HgPathBuf>, Vec<HgPathBuf>) {
253 let mut roots = Vec::new();
254 let mut dirs = Vec::new();
255
256 for ignore_pattern in ignore_patterns {
257 let IgnorePattern {
258 syntax, pattern, ..
259 } = ignore_pattern;
260 match syntax {
261 PatternSyntax::RootGlob | PatternSyntax::Glob => {
262 let mut root = vec![];
263
264 for p in pattern.split(|c| *c == b'/') {
265 if p.iter().any(|c| match *c {
266 b'[' | b'{' | b'*' | b'?' => true,
267 _ => false,
268 }) {
269 break;
270 }
271 root.push(HgPathBuf::from_bytes(p));
272 }
273 let buf =
274 root.iter().fold(HgPathBuf::new(), |acc, r| acc.join(r));
275 roots.push(buf);
276 }
277 PatternSyntax::Path | PatternSyntax::RelPath => {
278 let pat = HgPath::new(if pattern == b"." {
279 &[] as &[u8]
280 } else {
281 pattern
282 });
283 roots.push(pat.to_owned());
284 }
285 PatternSyntax::RootFiles => {
286 let pat = if pattern == b"." {
287 &[] as &[u8]
288 } else {
289 pattern
290 };
291 dirs.push(HgPathBuf::from_bytes(pat));
292 }
293 _ => {
294 roots.push(HgPathBuf::new());
295 }
296 }
297 }
298 (roots, dirs)
299 }
300
301 /// Paths extracted from patterns
302 #[derive(Debug, PartialEq)]
303 struct RootsDirsAndParents {
304 /// Directories to match recursively
305 pub roots: HashSet<HgPathBuf>,
306 /// Directories to match non-recursively
307 pub dirs: HashSet<HgPathBuf>,
308 /// Implicitly required directories to go to items in either roots or dirs
309 pub parents: HashSet<HgPathBuf>,
310 }
311
312 /// Extract roots, dirs and parents from patterns.
313 fn roots_dirs_and_parents(
314 ignore_patterns: &[IgnorePattern],
315 ) -> PatternResult<RootsDirsAndParents> {
316 let (roots, dirs) = roots_and_dirs(ignore_patterns);
317
318 let mut parents = HashSet::new();
319
320 parents.extend(
321 DirsMultiset::from_manifest(&dirs)
322 .map_err(|e| match e {
323 DirstateMapError::InvalidPath(e) => e,
324 _ => unreachable!(),
325 })?
326 .iter()
327 .map(|k| k.to_owned()),
328 );
329 parents.extend(
330 DirsMultiset::from_manifest(&roots)
331 .map_err(|e| match e {
332 DirstateMapError::InvalidPath(e) => e,
333 _ => unreachable!(),
334 })?
335 .iter()
336 .map(|k| k.to_owned()),
337 );
338
339 Ok(RootsDirsAndParents {
340 roots: HashSet::from_iter(roots),
341 dirs: HashSet::from_iter(dirs),
342 parents,
343 })
344 }
345
243 #[cfg(test)]
346 #[cfg(test)]
244 mod tests {
347 mod tests {
245 use super::*;
348 use super::*;
246 use pretty_assertions::assert_eq;
349 use pretty_assertions::assert_eq;
350 use std::path::Path;
351
352 #[test]
353 fn test_roots_and_dirs() {
354 let pats = vec![
355 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
356 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
357 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
358 ];
359 let (roots, dirs) = roots_and_dirs(&pats);
360
361 assert_eq!(
362 roots,
363 vec!(
364 HgPathBuf::from_bytes(b"g/h"),
365 HgPathBuf::from_bytes(b"g/h"),
366 HgPathBuf::new()
367 ),
368 );
369 assert_eq!(dirs, vec!());
370 }
371
372 #[test]
373 fn test_roots_dirs_and_parents() {
374 let pats = vec![
375 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
376 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
377 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
378 ];
379
380 let mut roots = HashSet::new();
381 roots.insert(HgPathBuf::from_bytes(b"g/h"));
382 roots.insert(HgPathBuf::new());
383
384 let dirs = HashSet::new();
385
386 let mut parents = HashSet::new();
387 parents.insert(HgPathBuf::new());
388 parents.insert(HgPathBuf::from_bytes(b"g"));
389
390 assert_eq!(
391 roots_dirs_and_parents(&pats).unwrap(),
392 RootsDirsAndParents {roots, dirs, parents}
393 );
394 }
247
395
248 #[test]
396 #[test]
249 fn test_filematcher_visit_children_set() {
397 fn test_filematcher_visit_children_set() {
General Comments 0
You need to be logged in to leave comments. Login now