comparison rust/hg-cpython/src/revlog.rs @ 51220:c817d9f626d3

rust-index: add support for `computephasesmapsets` Exposition in `hg-cpython` done in the regular `impl` block to enjoy rustfmt and clearer compilartion errors.
author Raphaël Gomès <rgomes@octobus.net>
date Mon, 30 Oct 2023 11:54:42 +0100
parents 8cb31833b486
children fc05dd74e907
comparison
equal deleted inserted replaced
51219:8cb31833b486 51220:c817d9f626d3
18 PyModule, PyObject, PyResult, PySet, PyString, PyTuple, Python, 18 PyModule, PyObject, PyResult, PySet, PyString, PyTuple, Python,
19 PythonObject, ToPyObject, 19 PythonObject, ToPyObject,
20 }; 20 };
21 use hg::{ 21 use hg::{
22 errors::HgError, 22 errors::HgError,
23 index::{IndexHeader, RevisionDataParams, SnapshotsCache}, 23 index::{IndexHeader, Phase, RevisionDataParams, SnapshotsCache},
24 nodemap::{Block, NodeMapError, NodeTree}, 24 nodemap::{Block, NodeMapError, NodeTree},
25 revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex}, 25 revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex},
26 BaseRevision, Revision, UncheckedRevision, NULL_REVISION, 26 BaseRevision, Revision, UncheckedRevision, NULL_REVISION,
27 }; 27 };
28 use std::cell::RefCell; 28 use std::{cell::RefCell, collections::HashMap};
29 29
30 /// Return a Struct implementing the Graph trait 30 /// Return a Struct implementing the Graph trait
31 pub(crate) fn pyindex_to_graph( 31 pub(crate) fn pyindex_to_graph(
32 py: Python, 32 py: Python,
33 index: PyObject, 33 index: PyObject,
239 Ok(rust_res) 239 Ok(rust_res)
240 } 240 }
241 241
242 /// compute phases 242 /// compute phases
243 def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> { 243 def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
244 self.call_cindex(py, "computephasesmapsets", args, kw) 244 let py_roots = args.get_item(py, 0).extract::<PyDict>(py)?;
245 let rust_res = self.inner_computephasesmapsets(py, py_roots)?;
246
247 let c_res = self.call_cindex(py, "computephasesmapsets", args, kw)?;
248 assert_py_eq(py, "computephasesmapsets", &rust_res, &c_res)?;
249 Ok(rust_res)
245 } 250 }
246 251
247 /// reachableroots 252 /// reachableroots
248 def reachableroots2(&self, *args, **kw) -> PyResult<PyObject> { 253 def reachableroots2(&self, *args, **kw) -> PyResult<PyObject> {
249 self.call_cindex(py, "reachableroots2", args, kw) 254 self.call_cindex(py, "reachableroots2", args, kw)
827 .map(|r| PyRevision::from(*r).into_py_object(py).into_object()) 832 .map(|r| PyRevision::from(*r).into_py_object(py).into_object())
828 .collect(); 833 .collect();
829 Ok(PyList::new(py, &as_vec).into_object()) 834 Ok(PyList::new(py, &as_vec).into_object())
830 } 835 }
831 836
837 fn inner_computephasesmapsets(
838 &self,
839 py: Python,
840 py_roots: PyDict,
841 ) -> PyResult<PyObject> {
842 let index = &*self.index(py).borrow();
843 let opt = self.get_nodetree(py)?.borrow();
844 let nt = opt.as_ref().unwrap();
845 let roots: Result<HashMap<Phase, Vec<Revision>>, PyErr> = py_roots
846 .items_list(py)
847 .iter(py)
848 .map(|r| {
849 let phase = r.get_item(py, 0)?;
850 let nodes = r.get_item(py, 1)?;
851 // Transform the nodes from Python to revs here since we
852 // have access to the nodemap
853 let revs: Result<_, _> = nodes
854 .iter(py)?
855 .map(|node| match node?.extract::<PyBytes>(py) {
856 Ok(py_bytes) => {
857 let node = node_from_py_bytes(py, &py_bytes)?;
858 nt.find_bin(index, node.into())
859 .map_err(|e| nodemap_error(py, e))?
860 .ok_or_else(|| revlog_error(py))
861 }
862 Err(e) => Err(e),
863 })
864 .collect();
865 let phase = Phase::try_from(phase.extract::<usize>(py)?)
866 .map_err(|_| revlog_error(py));
867 Ok((phase?, revs?))
868 })
869 .collect();
870 let (len, phase_maps) = index
871 .compute_phases_map_sets(roots?)
872 .map_err(|e| graph_error(py, e))?;
873
874 // Ugly hack, but temporary
875 const IDX_TO_PHASE_NUM: [usize; 4] = [1, 2, 32, 96];
876 let py_phase_maps = PyDict::new(py);
877 for (idx, roots) in phase_maps.iter().enumerate() {
878 let phase_num = IDX_TO_PHASE_NUM[idx].into_py_object(py);
879 // OPTIM too bad we have to collect here. At least, we could
880 // reuse the same Vec and allocate it with capacity at
881 // max(len(phase_maps)
882 let roots_vec: Vec<PyInt> = roots
883 .iter()
884 .map(|r| PyRevision::from(*r).into_py_object(py))
885 .collect();
886 py_phase_maps.set_item(
887 py,
888 phase_num,
889 PySet::new(py, roots_vec)?,
890 )?;
891 }
892 Ok(PyTuple::new(
893 py,
894 &[
895 len.into_py_object(py).into_object(),
896 py_phase_maps.into_object(),
897 ],
898 )
899 .into_object())
900 }
901
832 fn inner_slicechunktodensity( 902 fn inner_slicechunktodensity(
833 &self, 903 &self,
834 py: Python, 904 py: Python,
835 revs: PyObject, 905 revs: PyObject,
836 target_density: f64, 906 target_density: f64,