match: make `was_tampered_with` work recursively
authorArseniy Alekseyev <aalekseyev@janestreet.com>
Fri, 26 Apr 2024 18:53:02 +0100
changeset 51625 aa23b19e6da4
parent 51624 e32f23f15623
child 51626 865efc020c33
match: make `was_tampered_with` work recursively This is useful if we are to use it outside of Rust, when deciding whether or not to do some fast-path operation with a given matcher.
mercurial/match.py
rust/hg-cpython/src/dirstate/status.rs
--- a/mercurial/match.py	Fri Apr 26 19:43:42 2024 +0100
+++ b/mercurial/match.py	Fri Apr 26 18:53:02 2024 +0100
@@ -399,11 +399,14 @@
         if badfn is not None:
             self.bad = badfn
 
-    def was_tampered_with(self):
+    def was_tampered_with_nonrec(self):
         # [_was_tampered_with] is used to track if when extensions changed the matcher
         # behavior (crazy stuff!), so we disable the rust fast path.
         return self._was_tampered_with
 
+    def was_tampered_with(self):
+        return self.was_tampered_with_nonrec()
+
     def __call__(self, fn):
         return self.matchfn(fn)
 
@@ -891,6 +894,13 @@
         self.bad = m1.bad
         self.traversedir = m1.traversedir
 
+    def was_tampered_with(self):
+        return (
+            self.was_tampered_with_nonrec()
+            or self._m1.was_tampered_with()
+            or self._m2.was_tampered_with()
+        )
+
     def matchfn(self, f):
         return self._m1(f) and not self._m2(f)
 
@@ -974,6 +984,13 @@
         self.bad = m1.bad
         self.traversedir = m1.traversedir
 
+    def was_tampered_with(self):
+        return (
+            self.was_tampered_with_nonrec()
+            or self._m1.was_tampered_with()
+            or self._m2.was_tampered_with()
+        )
+
     @propertycache
     def _files(self):
         if self.isexact():
@@ -1071,6 +1088,11 @@
         if matcher.prefix():
             self._always = any(f == path for f in matcher._files)
 
+    def was_tampered_with(self):
+        return (
+            self.was_tampered_with_nonrec() or self._matcher.was_tampered_with()
+        )
+
     def bad(self, f, msg):
         self._matcher.bad(self._path + b"/" + f, msg)
 
@@ -1205,6 +1227,11 @@
         self.traversedir = m1.traversedir
         self._matchers = matchers
 
+    def was_tampered_with(self):
+        return self.was_tampered_with_nonrec() or any(
+            map(lambda m: m.was_tampered_with(), self._matchers)
+        )
+
     def matchfn(self, f):
         for match in self._matchers:
             if match(f):
--- a/rust/hg-cpython/src/dirstate/status.rs	Fri Apr 26 19:43:42 2024 +0100
+++ b/rust/hg-cpython/src/dirstate/status.rs	Fri Apr 26 18:53:02 2024 +0100
@@ -182,7 +182,7 @@
     matcher: PyObject,
 ) -> PyResult<Box<dyn Matcher + Sync>> {
     let tampered = matcher
-        .call_method(py, "was_tampered_with", PyTuple::empty(py), None)?
+        .call_method(py, "was_tampered_with_nonrec", PyTuple::empty(py), None)?
         .extract::<PyBool>(py)?
         .is_true();
     if tampered {