Mercurial > hg
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, |