matchers: support patternmatcher in rust
authorArseniy Alekseyev <aalekseyev@janestreet.com>
Fri, 05 Apr 2024 17:57:26 +0100
changeset 51603 a2afa35641c9
parent 51602 68929cf3c0c6
child 51604 32ba01b5669d
matchers: support patternmatcher in rust
mercurial/match.py
rust/hg-cpython/src/dirstate/status.rs
--- a/mercurial/match.py	Tue Apr 09 11:12:24 2024 +0100
+++ b/mercurial/match.py	Fri Apr 05 17:57:26 2024 +0100
@@ -644,6 +644,11 @@
         super(patternmatcher, self).__init__(badfn)
         kindpats.sort()
 
+        if rustmod is not None:
+            # We need to pass the patterns to Rust because they can contain
+            # patterns from the user interface
+            self._kindpats = kindpats
+
         roots, dirs, parents = _rootsdirsandparents(kindpats)
         self._files = _explicitfiles(kindpats)
         self._dirs_explicit = set(dirs)
--- a/rust/hg-cpython/src/dirstate/status.rs	Tue Apr 09 11:12:24 2024 +0100
+++ b/rust/hg-cpython/src/dirstate/status.rs	Fri Apr 05 17:57:26 2024 +0100
@@ -17,7 +17,7 @@
 use hg::dirstate::status::StatusPath;
 use hg::matchers::{
     DifferenceMatcher, IntersectionMatcher, Matcher, NeverMatcher,
-    UnionMatcher,
+    PatternMatcher, UnionMatcher,
 };
 use hg::{
     matchers::{AlwaysMatcher, FileMatcher, IncludeMatcher},
@@ -253,6 +253,38 @@
 
             Ok(Box::new(DifferenceMatcher::new(m1, m2)))
         }
+        "patternmatcher" => {
+            let ignore_patterns = matcher
+                .getattr(py, "_kindpats")?
+                .iter(py)?
+                .map(|k| {
+                    let k = k?;
+                    let syntax = parse_pattern_syntax(
+                        &[
+                            k.get_item(py, 0)?
+                                .extract::<PyBytes>(py)?
+                                .data(py),
+                            &b":"[..],
+                        ]
+                        .concat(),
+                    )
+                    .map_err(|e| {
+                        handle_fallback(py, StatusError::Pattern(e))
+                    })?;
+                    let pattern = k.get_item(py, 1)?.extract::<PyBytes>(py)?;
+                    let pattern = pattern.data(py);
+                    let source = k.get_item(py, 2)?.extract::<PyBytes>(py)?;
+                    let source = get_path_from_bytes(source.data(py));
+                    let new = IgnorePattern::new(syntax, pattern, source);
+                    Ok(new)
+                })
+                .collect::<PyResult<Vec<_>>>()?;
+
+            let matcher = PatternMatcher::new(ignore_patterns)
+                .map_err(|e| handle_fallback(py, e.into()))?;
+
+            Ok(Box::new(matcher))
+        }
         e => Err(PyErr::new::<FallbackError, _>(
             py,
             format!("Unsupported matcher {}", e),