D7924: rust-matchers: add `build_regex_match` function

Alphare (Raphaël Gomès) phabricator at mercurial-scm.org
Fri Jan 17 10:42:36 UTC 2020


Alphare created this revision.
Herald added subscribers: mercurial-devel, kevincox, durin42.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This function will be used to help build the upcoming `IncludeMatcher`.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D7924

AFFECTED FILES
  rust/hg-core/src/matchers.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/matchers.rs b/rust/hg-core/src/matchers.rs
--- a/rust/hg-core/src/matchers.rs
+++ b/rust/hg-core/src/matchers.rs
@@ -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 = &regexps[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 = &regexps[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



To: Alphare, #hg-reviewers
Cc: durin42, kevincox, mercurial-devel


More information about the Mercurial-devel mailing list