Mercurial > hg
changeset 44297:cf1f8660e568
rust-dirstatemap: add `NonNormalEntries` class
This fix introduces the same encapsulation as the `copymap`. There is no easy
way of doing this any better for now.
`hg up -r null && time HGRCPATH= HGMODULEPOLICY=rust+c hg up tip` on Mozilla
Central, (not super recent, but it doesn't matter):
Before: 7:44,08 total
After: 1:03,23 total
Pretty brutal regression!
Differential Revision: https://phab.mercurial-scm.org/D8049
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 10 Feb 2020 21:54:12 +0100 |
parents | 5830efce522b |
children | 0e8b28fb751b |
files | mercurial/dirstate.py rust/hg-cpython/src/dirstate.rs rust/hg-cpython/src/dirstate/dirstate_map.rs rust/hg-cpython/src/dirstate/non_normal_entries.rs |
diffstat | 4 files changed, 128 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/dirstate.py Sun Feb 09 16:18:26 2020 -0500 +++ b/mercurial/dirstate.py Mon Feb 10 21:54:12 2020 +0100 @@ -1846,12 +1846,12 @@ @property def nonnormalset(self): - nonnorm, otherparents = self._rustmap.nonnormalentries() + nonnorm = self._rustmap.non_normal_entries() return nonnorm @propertycache def otherparentset(self): - nonnorm, otherparents = self._rustmap.nonnormalentries() + otherparents = self._rustmap.other_parent_entries() return otherparents @propertycache
--- a/rust/hg-cpython/src/dirstate.rs Sun Feb 09 16:18:26 2020 -0500 +++ b/rust/hg-cpython/src/dirstate.rs Mon Feb 10 21:54:12 2020 +0100 @@ -12,6 +12,7 @@ mod copymap; mod dirs_multiset; mod dirstate_map; +mod non_normal_entries; mod status; use crate::dirstate::{ dirs_multiset::Dirs, dirstate_map::DirstateMap, status::status_wrapper,
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs Sun Feb 09 16:18:26 2020 -0500 +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs Mon Feb 10 21:54:12 2020 +0100 @@ -13,12 +13,14 @@ use std::time::Duration; use cpython::{ - exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyObject, - PyResult, PyTuple, Python, PythonObject, ToPyObject, UnsafePyLeaked, + exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList, + PyObject, PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject, + UnsafePyLeaked, }; use crate::{ dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, + dirstate::non_normal_entries::NonNormalEntries, dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, }; use hg::{ @@ -164,32 +166,86 @@ Ok(py.None()) } - // TODO share the reference - def nonnormalentries(&self) -> PyResult<PyObject> { - let (non_normal, other_parent) = - self.inner(py).borrow().non_normal_other_parent_entries(); + def other_parent_entries(&self) -> PyResult<PyObject> { + let mut inner_shared = self.inner(py).borrow_mut(); + let (_, other_parent) = + inner_shared.get_non_normal_other_parent_entries(); let locals = PyDict::new(py); locals.set_item( py, - "non_normal", - non_normal - .iter() - .map(|v| PyBytes::new(py, v.as_ref())) - .collect::<Vec<PyBytes>>() - .to_py_object(py), - )?; - locals.set_item( - py, "other_parent", - other_parent + other_parent.as_ref() + .unwrap() .iter() .map(|v| PyBytes::new(py, v.as_ref())) .collect::<Vec<PyBytes>>() .to_py_object(py), )?; - py.eval("set(non_normal), set(other_parent)", None, Some(&locals)) + py.eval("set(other_parent)", None, Some(&locals)) + } + + def non_normal_entries(&self) -> PyResult<NonNormalEntries> { + NonNormalEntries::from_inner(py, self.clone_ref(py)) + } + + def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> { + let key = key.extract::<PyBytes>(py)?; + Ok(self + .inner(py) + .borrow_mut() + .get_non_normal_other_parent_entries().0 + .as_ref() + .unwrap() + .contains(HgPath::new(key.data(py)))) + } + + def non_normal_entries_display(&self) -> PyResult<PyString> { + Ok( + PyString::new( + py, + &format!( + "NonNormalEntries: {:?}", + self + .inner(py) + .borrow_mut() + .get_non_normal_other_parent_entries().0 + .as_ref() + .unwrap().iter().map(|o| o)) + ) + ) + } + + def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> { + let key = key.extract::<PyBytes>(py)?; + self + .inner(py) + .borrow_mut() + .non_normal_entries_remove(HgPath::new(key.data(py))); + Ok(py.None()) + } + + def non_normal_entries_union(&self, other: PyObject) -> PyResult<PyList> { + let other: PyResult<_> = other.iter(py)? + .map(|f| { + Ok(HgPathBuf::from_bytes( + f?.extract::<PyBytes>(py)?.data(py), + )) + }) + .collect(); + + let res = self + .inner(py) + .borrow_mut() + .non_normal_entries_union(other?); + + let ret = PyList::new(py, &[]); + for filename in res.iter() { + let as_pystring = PyBytes::new(py, filename.as_bytes()); + ret.append(py, as_pystring.into_object()); + } + Ok(ret) } def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-cpython/src/dirstate/non_normal_entries.rs Mon Feb 10 21:54:12 2020 +0100 @@ -0,0 +1,52 @@ +// non_normal_other_parent_entries.rs +// +// Copyright 2020 Raphaël Gomès <rgomes@octobus.net> +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +use cpython::{ + exc::NotImplementedError, CompareOp, ObjectProtocol, PyErr, PyList, + PyObject, PyResult, PyString, Python, PythonObject, ToPyObject, +}; + +use crate::dirstate::DirstateMap; + +py_class!(pub class NonNormalEntries |py| { + data dmap: DirstateMap; + + def __contains__(&self, key: PyObject) -> PyResult<bool> { + self.dmap(py).non_normal_entries_contains(py, key) + } + def remove(&self, key: PyObject) -> PyResult<PyObject> { + self.dmap(py).non_normal_entries_remove(py, key) + } + def union(&self, other: PyObject) -> PyResult<PyList> { + self.dmap(py).non_normal_entries_union(py, other) + } + def __richcmp__(&self, other: PyObject, op: CompareOp) -> PyResult<bool> { + match op { + CompareOp::Eq => self.is_equal_to(py, other), + CompareOp::Ne => Ok(!self.is_equal_to(py, other)?), + _ => Err(PyErr::new::<NotImplementedError, _>(py, "")) + } + } + def __repr__(&self) -> PyResult<PyString> { + self.dmap(py).non_normal_entries_display(py) + } +}); + +impl NonNormalEntries { + pub fn from_inner(py: Python, dm: DirstateMap) -> PyResult<Self> { + Self::create_instance(py, dm) + } + + fn is_equal_to(&self, py: Python, other: PyObject) -> PyResult<bool> { + for item in other.iter(py)? { + if !self.dmap(py).non_normal_entries_contains(py, item?)? { + return Ok(false); + } + } + Ok(true) + } +}