Show More
@@ -271,7 +271,7 b' pub fn normalize_path_bytes(bytes: &[u8]' | |||||
271 | /// that don't need to be transformed into a regex. |
|
271 | /// that don't need to be transformed into a regex. | |
272 | pub fn build_single_regex( |
|
272 | pub fn build_single_regex( | |
273 | entry: &IgnorePattern, |
|
273 | entry: &IgnorePattern, | |
274 | ) -> Result<Vec<u8>, PatternError> { |
|
274 | ) -> Result<Option<Vec<u8>>, PatternError> { | |
275 | let IgnorePattern { |
|
275 | let IgnorePattern { | |
276 | pattern, syntax, .. |
|
276 | pattern, syntax, .. | |
277 | } = entry; |
|
277 | } = entry; | |
@@ -288,16 +288,11 b' pub fn build_single_regex(' | |||||
288 | if *syntax == PatternSyntax::RootGlob |
|
288 | if *syntax == PatternSyntax::RootGlob | |
289 | && !pattern.iter().any(|b| GLOB_SPECIAL_CHARACTERS.contains(b)) |
|
289 | && !pattern.iter().any(|b| GLOB_SPECIAL_CHARACTERS.contains(b)) | |
290 | { |
|
290 | { | |
291 | // The `regex` crate adds `.*` to the start and end of expressions |
|
291 | Ok(None) | |
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) |
|
|||
297 | } else { |
|
292 | } else { | |
298 | let mut entry = entry.clone(); |
|
293 | let mut entry = entry.clone(); | |
299 | entry.pattern = pattern; |
|
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 | Path::new("") |
|
623 | Path::new("") | |
629 | )) |
|
624 | )) | |
630 | .unwrap(), |
|
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 | Path::new("") |
|
636 | Path::new("") | |
642 | )) |
|
637 | )) | |
643 | .unwrap(), |
|
638 | .unwrap(), | |
644 | br"^\.(?:/|$)".to_vec(), |
|
639 | None, | |
645 | ); |
|
640 | ); | |
646 | assert_eq!( |
|
641 | assert_eq!( | |
647 | build_single_regex(&IgnorePattern::new( |
|
642 | build_single_regex(&IgnorePattern::new( | |
@@ -650,7 +645,7 b' mod tests {' | |||||
650 | Path::new("") |
|
645 | Path::new("") | |
651 | )) |
|
646 | )) | |
652 | .unwrap(), |
|
647 | .unwrap(), | |
653 | br"^whatever(?:/|$)".to_vec(), |
|
648 | None, | |
654 | ); |
|
649 | ); | |
655 | assert_eq!( |
|
650 | assert_eq!( | |
656 | build_single_regex(&IgnorePattern::new( |
|
651 | build_single_regex(&IgnorePattern::new( | |
@@ -659,7 +654,7 b' mod tests {' | |||||
659 | Path::new("") |
|
654 | Path::new("") | |
660 | )) |
|
655 | )) | |
661 | .unwrap(), |
|
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 | PatternSyntax, |
|
24 | PatternSyntax, | |
25 | }; |
|
25 | }; | |
26 |
|
26 | |||
|
27 | use crate::filepatterns::normalize_path_bytes; | |||
27 | use std::borrow::ToOwned; |
|
28 | use std::borrow::ToOwned; | |
28 | use std::collections::HashSet; |
|
29 | use std::collections::HashSet; | |
29 | use std::fmt::{Display, Error, Formatter}; |
|
30 | use std::fmt::{Display, Error, Formatter}; | |
@@ -373,15 +374,32 b' fn re_matcher(' | |||||
373 | fn build_regex_match<'a>( |
|
374 | fn build_regex_match<'a>( | |
374 | ignore_patterns: &'a [&'a IgnorePattern], |
|
375 | ignore_patterns: &'a [&'a IgnorePattern], | |
375 | ) -> PatternResult<(Vec<u8>, Box<dyn Fn(&HgPath) -> bool + Sync>)> { |
|
376 | ) -> PatternResult<(Vec<u8>, Box<dyn Fn(&HgPath) -> bool + Sync>)> { | |
376 | let regexps: Result<Vec<_>, PatternError> = ignore_patterns |
|
377 | let mut regexps = vec![]; | |
377 | .into_iter() |
|
378 | let mut exact_set = HashSet::new(); | |
378 | .map(|k| build_single_regex(*k)) |
|
379 | ||
379 | .collect(); |
|
380 | for pattern in ignore_patterns { | |
380 | let regexps = regexps?; |
|
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 | let full_regex = regexps.join(&b'|'); |
|
389 | let full_regex = regexps.join(&b'|'); | |
382 |
|
390 | |||
383 | let matcher = re_matcher(&full_regex)?; |
|
391 | // An empty pattern would cause the regex engine to incorrectly match the | |
384 | let func = Box::new(move |filename: &HgPath| matcher(filename)); |
|
392 | // (empty) root directory | |
|
393 | let func = if !(regexps.is_empty()) { | |||
|
394 | let matcher = re_matcher(&full_regex)?; | |||
|
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 | Ok((full_regex, func)) |
|
404 | Ok((full_regex, func)) | |
387 | } |
|
405 | } |
General Comments 0
You need to be logged in to leave comments.
Login now