Comments
Patch
@@ -10,7 +10,7 @@
#[cfg(feature = "with-re2")]
use crate::re2::Re2;
use crate::{
- filepatterns::PatternResult,
+ filepatterns::{build_single_regex, PatternResult},
utils::hg_path::{HgPath, HgPathBuf},
DirsMultiset, DirstateMapError, IgnorePattern, PatternError,
PatternSyntax,
@@ -244,6 +244,57 @@
Err(PatternError::Re2NotInstalled)
}
+/// Returns a function that matches an `HgPath` against the regex formed by
+/// the given patterns.
+fn build_regex_match<'a>(
+ ignore_patterns: &'a [&'a IgnorePattern],
+) -> PatternResult<(Vec<u8>, Box<dyn Fn(&HgPath) -> bool + Sync>)> {
+ let mut all_groups = vec![];
+ let regexps: Result<Vec<_>, PatternError> = ignore_patterns
+ .into_iter()
+ .map(|k| build_single_regex(*k))
+ .collect();
+ let regexps = regexps?;
+ let full_regex = regexps.join(&b'|');
+
+ let mut start_index = 0;
+ let mut group_size = 0;
+
+ for (index, re) in regexps.iter().enumerate() {
+ let piece_size = re.len();
+ if piece_size > MAX_RE_SIZE {
+ return Err(PatternError::TooLong(piece_size));
+ }
+ if (group_size + piece_size) > MAX_RE_SIZE {
+ let group = ®exps[start_index..index];
+ all_groups.push(group.join(&b'|'));
+ start_index = index;
+ group_size = 0
+ }
+ group_size += piece_size + 1;
+ }
+
+ let func = if start_index == 0 {
+ let matcher = re_matcher(&full_regex)?;
+ Box::new(move |filename: &HgPath| matcher(filename))
+ as Box<dyn Fn(&HgPath) -> bool + Sync>
+ } else {
+ let group = ®exps[start_index..];
+ all_groups.push(group.join(&b'|'));
+
+ let all_matchers: PatternResult<Vec<_>> =
+ all_groups.iter().map(|group| re_matcher(group)).collect();
+ let all_matchers = all_matchers?;
+
+ let ret = Box::new(move |filename: &HgPath| {
+ all_matchers.iter().any(|f| f(filename))
+ });
+ ret as Box<dyn Fn(&HgPath) -> bool + Sync>
+ };
+
+ Ok((full_regex, func))
+}
+
/// Returns roots and directories corresponding to each pattern.
///
/// This calculates the roots and directories exactly matching the patterns and