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.
--- 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 {