##// END OF EJS Templates
rust-filepatterns: match exact `rootglob`s with a `HashSet`, not in the regex...
Raphaël Gomès -
r45311:e0414fcd default
parent child Browse files
Show More
@@ -271,7 +271,7 b' pub fn normalize_path_bytes(bytes: &[u8]'
271 271 /// that don't need to be transformed into a regex.
272 272 pub fn build_single_regex(
273 273 entry: &IgnorePattern,
274 ) -> Result<Vec<u8>, PatternError> {
274 ) -> Result<Option<Vec<u8>>, PatternError> {
275 275 let IgnorePattern {
276 276 pattern, syntax, ..
277 277 } = entry;
@@ -288,16 +288,11 b' pub fn build_single_regex('
288 288 if *syntax == PatternSyntax::RootGlob
289 289 && !pattern.iter().any(|b| GLOB_SPECIAL_CHARACTERS.contains(b))
290 290 {
291 // The `regex` crate adds `.*` to the start and end of expressions
292 // if there are no anchors, so add the start anchor.
293 let mut escaped = vec![b'^'];
294 escaped.extend(escape_pattern(&pattern));
295 escaped.extend(GLOB_SUFFIX);
296 Ok(escaped)
291 Ok(None)
297 292 } else {
298 293 let mut entry = entry.clone();
299 294 entry.pattern = pattern;
300 Ok(_build_single_regex(&entry))
295 Ok(Some(_build_single_regex(&entry)))
301 296 }
302 297 }
303 298
@@ -628,7 +623,7 b' mod tests {'
628 623 Path::new("")
629 624 ))
630 625 .unwrap(),
631 br"(?:.*/)?rust/target(?:/|$)".to_vec(),
626 Some(br"(?:.*/)?rust/target(?:/|$)".to_vec()),
632 627 );
633 628 }
634 629
@@ -641,7 +636,7 b' mod tests {'
641 636 Path::new("")
642 637 ))
643 638 .unwrap(),
644 br"^\.(?:/|$)".to_vec(),
639 None,
645 640 );
646 641 assert_eq!(
647 642 build_single_regex(&IgnorePattern::new(
@@ -650,7 +645,7 b' mod tests {'
650 645 Path::new("")
651 646 ))
652 647 .unwrap(),
653 br"^whatever(?:/|$)".to_vec(),
648 None,
654 649 );
655 650 assert_eq!(
656 651 build_single_regex(&IgnorePattern::new(
@@ -659,7 +654,7 b' mod tests {'
659 654 Path::new("")
660 655 ))
661 656 .unwrap(),
662 br"^[^/]*\.o(?:/|$)".to_vec(),
657 Some(br"^[^/]*\.o(?:/|$)".to_vec()),
663 658 );
664 659 }
665 660 }
@@ -24,6 +24,7 b' use crate::{'
24 24 PatternSyntax,
25 25 };
26 26
27 use crate::filepatterns::normalize_path_bytes;
27 28 use std::borrow::ToOwned;
28 29 use std::collections::HashSet;
29 30 use std::fmt::{Display, Error, Formatter};
@@ -373,15 +374,32 b' fn re_matcher('
373 374 fn build_regex_match<'a>(
374 375 ignore_patterns: &'a [&'a IgnorePattern],
375 376 ) -> PatternResult<(Vec<u8>, Box<dyn Fn(&HgPath) -> bool + Sync>)> {
376 let regexps: Result<Vec<_>, PatternError> = ignore_patterns
377 .into_iter()
378 .map(|k| build_single_regex(*k))
379 .collect();
380 let regexps = regexps?;
377 let mut regexps = vec![];
378 let mut exact_set = HashSet::new();
379
380 for pattern in ignore_patterns {
381 if let Some(re) = build_single_regex(pattern)? {
382 regexps.push(re);
383 } else {
384 let exact = normalize_path_bytes(&pattern.pattern);
385 exact_set.insert(HgPathBuf::from_bytes(&exact));
386 }
387 }
388
381 389 let full_regex = regexps.join(&b'|');
382 390
391 // An empty pattern would cause the regex engine to incorrectly match the
392 // (empty) root directory
393 let func = if !(regexps.is_empty()) {
383 394 let matcher = re_matcher(&full_regex)?;
384 let func = Box::new(move |filename: &HgPath| matcher(filename));
395 let func = move |filename: &HgPath| {
396 exact_set.contains(filename) || matcher(filename)
397 };
398 Box::new(func) as Box<dyn Fn(&HgPath) -> bool + Sync>
399 } else {
400 let func = move |filename: &HgPath| exact_set.contains(filename);
401 Box::new(func) as Box<dyn Fn(&HgPath) -> bool + Sync>
402 };
385 403
386 404 Ok((full_regex, func))
387 405 }
General Comments 0
You need to be logged in to leave comments. Login now