# HG changeset patch # User Arseniy Alekseyev # Date 2024-04-09 10:12:24 # Node ID 68929cf3c0c67c05861943613afb087dfcaa0676 # Parent ea3343104f07904104fb280f0b9f1168c7214562 match: avoid rust fast path if the matcher was tampered with Otherwise the fast path does not respect the modifications made by the extension (concretely largefiles, but other extensions can start using that too) diff --git a/rust/hg-cpython/src/dirstate/status.rs b/rust/hg-cpython/src/dirstate/status.rs --- a/rust/hg-cpython/src/dirstate/status.rs +++ b/rust/hg-cpython/src/dirstate/status.rs @@ -11,7 +11,7 @@ use crate::{dirstate::DirstateMap, exceptions::FallbackError}; use cpython::{ - exc::ValueError, ObjectProtocol, PyBytes, PyErr, PyList, PyObject, + exc::ValueError, ObjectProtocol, PyBool, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple, Python, PythonObject, ToPyObject, }; use hg::dirstate::status::StatusPath; @@ -26,8 +26,8 @@ use hg::{ files::{get_bytes_from_path, get_path_from_bytes}, hg_path::{HgPath, HgPathBuf}, }, - BadMatch, DirstateStatus, IgnorePattern, PatternFileWarning, StatusError, - StatusOptions, + BadMatch, DirstateStatus, IgnorePattern, PatternError, PatternFileWarning, + StatusError, StatusOptions, }; use std::borrow::Borrow; @@ -158,6 +158,18 @@ fn extract_matcher( py: Python, matcher: PyObject, ) -> PyResult> { + let tampered = matcher + .call_method(py, "was_tampered_with", PyTuple::empty(py), None)? + .extract::(py)? + .is_true(); + if tampered { + return Err(handle_fallback( + py, + StatusError::Pattern(PatternError::UnsupportedSyntax( + "Pattern matcher was tampered with!".to_string(), + )), + )); + }; match matcher.get_type(py).name(py).borrow() { "alwaysmatcher" => Ok(Box::new(AlwaysMatcher)), "nevermatcher" => Ok(Box::new(NeverMatcher)),