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