25 }, |
25 }, |
26 nodemap::{Block, NodeMapError, NodeTree as CoreNodeTree}, |
26 nodemap::{Block, NodeMapError, NodeTree as CoreNodeTree}, |
27 revlog::{nodemap::NodeMap, Graph, NodePrefix, RevlogError, RevlogIndex}, |
27 revlog::{nodemap::NodeMap, Graph, NodePrefix, RevlogError, RevlogIndex}, |
28 BaseRevision, Node, Revision, UncheckedRevision, NULL_REVISION, |
28 BaseRevision, Node, Revision, UncheckedRevision, NULL_REVISION, |
29 }; |
29 }; |
30 use std::{cell::RefCell, collections::HashMap}; |
30 use std::{ |
|
31 cell::RefCell, |
|
32 collections::{HashMap, HashSet}, |
|
33 }; |
31 use vcsgraph::graph::Graph as VCSGraph; |
34 use vcsgraph::graph::Graph as VCSGraph; |
32 |
35 |
33 pub struct PySharedIndex { |
36 pub struct PySharedIndex { |
34 /// The underlying hg-core index |
37 /// The underlying hg-core index |
35 pub(crate) inner: &'static hg::index::Index, |
38 pub(crate) inner: &'static hg::index::Index, |
303 Ok(rust_res) |
306 Ok(rust_res) |
304 } |
307 } |
305 |
308 |
306 /// get head revisions |
309 /// get head revisions |
307 def headrevs(&self, *args, **_kw) -> PyResult<PyObject> { |
310 def headrevs(&self, *args, **_kw) -> PyResult<PyObject> { |
308 let filtered_revs = match &args.len(py) { |
311 let (filtered_revs, stop_rev) = match &args.len(py) { |
309 0 => Ok(py.None()), |
312 0 => Ok((py.None(), py.None())), |
310 1 => Ok(args.get_item(py, 0)), |
313 1 => Ok((args.get_item(py, 0), py.None())), |
|
314 2 => Ok((args.get_item(py, 0), args.get_item(py, 1))), |
311 _ => Err(PyErr::new::<cpython::exc::TypeError, _>(py, "too many arguments")), |
315 _ => Err(PyErr::new::<cpython::exc::TypeError, _>(py, "too many arguments")), |
312 }?; |
316 }?; |
313 self.inner_headrevs(py, &filtered_revs) |
317 self.inner_headrevs(py, &filtered_revs, &stop_rev) |
314 } |
318 } |
315 |
319 |
316 /// get head nodeids |
320 /// get head nodeids |
317 def head_node_ids(&self) -> PyResult<PyObject> { |
321 def head_node_ids(&self) -> PyResult<PyObject> { |
318 let rust_res = self.inner_head_node_ids(py)?; |
322 let rust_res = self.inner_head_node_ids(py)?; |
819 |
823 |
820 fn inner_headrevs( |
824 fn inner_headrevs( |
821 &self, |
825 &self, |
822 py: Python, |
826 py: Python, |
823 filtered_revs: &PyObject, |
827 filtered_revs: &PyObject, |
|
828 stop_rev: &PyObject, |
824 ) -> PyResult<PyObject> { |
829 ) -> PyResult<PyObject> { |
825 let index = &*self.index(py).borrow(); |
830 let index = &*self.index(py).borrow(); |
826 |
831 let stop_rev = match stop_rev.is_none(py) { |
827 let from_core = match filtered_revs.is_none(py) { |
|
828 true => index.head_revs_shortcut(), |
|
829 false => { |
832 false => { |
|
833 let rev = stop_rev.extract::<i32>(py)?; |
|
834 if 0 <= rev && rev < index.len() as BaseRevision { |
|
835 Some(Revision(rev)) |
|
836 } else { |
|
837 None |
|
838 } |
|
839 } |
|
840 true => None, |
|
841 }; |
|
842 let from_core = match (filtered_revs.is_none(py), stop_rev.is_none()) { |
|
843 (true, true) => index.head_revs_shortcut(), |
|
844 (true, false) => { |
|
845 index.head_revs_advanced(&HashSet::new(), stop_rev, false) |
|
846 } |
|
847 _ => { |
830 let filtered_revs = |
848 let filtered_revs = |
831 rev_pyiter_collect(py, filtered_revs, index)?; |
849 rev_pyiter_collect(py, filtered_revs, index)?; |
832 index.head_revs_filtered(&filtered_revs, true) |
850 index.head_revs_advanced( |
|
851 &filtered_revs, |
|
852 stop_rev, |
|
853 stop_rev.is_none(), |
|
854 ) |
833 } |
855 } |
834 }; |
856 }; |
835 |
857 |
836 if let Some(new_heads) = from_core.map_err(|e| graph_error(py, e))? { |
858 if stop_rev.is_some() { |
837 self.cache_new_heads_py_list(&new_heads, py); |
859 // we don't cache result for now |
838 } |
860 let new_heads = from_core |
839 |
861 .map_err(|e| graph_error(py, e))? |
840 Ok(self |
862 .expect("this case should not be cached yet"); |
841 .head_revs_py_list(py) |
863 |
842 .borrow() |
864 let as_vec: Vec<PyObject> = new_heads |
843 .as_ref() |
865 .iter() |
844 .expect("head revs should be cached") |
866 .map(|r| PyRevision::from(*r).into_py_object(py).into_object()) |
845 .clone_ref(py) |
867 .collect(); |
846 .into_object()) |
868 Ok(PyList::new(py, &as_vec).into_object()) |
|
869 } else { |
|
870 if let Some(new_heads) = |
|
871 from_core.map_err(|e| graph_error(py, e))? |
|
872 { |
|
873 self.cache_new_heads_py_list(&new_heads, py); |
|
874 } |
|
875 |
|
876 Ok(self |
|
877 .head_revs_py_list(py) |
|
878 .borrow() |
|
879 .as_ref() |
|
880 .expect("head revs should be cached") |
|
881 .clone_ref(py) |
|
882 .into_object()) |
|
883 } |
847 } |
884 } |
848 |
885 |
849 fn check_revision( |
886 fn check_revision( |
850 index: &hg::index::Index, |
887 index: &hg::index::Index, |
851 rev: UncheckedRevision, |
888 rev: UncheckedRevision, |