4 // |
4 // |
5 // This software may be used and distributed according to the terms of the |
5 // This software may be used and distributed according to the terms of the |
6 // GNU General Public License version 2 or any later version. |
6 // GNU General Public License version 2 or any later version. |
7 |
7 |
8 use crate::{ |
8 use crate::{ |
9 cindex, |
|
10 conversion::{rev_pyiter_collect, rev_pyiter_collect_or_else}, |
9 conversion::{rev_pyiter_collect, rev_pyiter_collect_or_else}, |
11 utils::{node_from_py_bytes, node_from_py_object}, |
10 utils::{node_from_py_bytes, node_from_py_object}, |
12 PyRevision, |
11 PyRevision, |
13 }; |
12 }; |
14 use cpython::{ |
13 use cpython::{ |
85 self.inner.node(rev) |
84 self.inner.node(rev) |
86 } |
85 } |
87 } |
86 } |
88 |
87 |
89 py_class!(pub class MixedIndex |py| { |
88 py_class!(pub class MixedIndex |py| { |
90 data cindex: RefCell<cindex::Index>; |
|
91 @shared data index: hg::index::Index; |
89 @shared data index: hg::index::Index; |
92 data nt: RefCell<Option<CoreNodeTree>>; |
90 data nt: RefCell<Option<CoreNodeTree>>; |
93 data docket: RefCell<Option<PyObject>>; |
91 data docket: RefCell<Option<PyObject>>; |
94 // Holds a reference to the mmap'ed persistent nodemap data |
92 // Holds a reference to the mmap'ed persistent nodemap data |
95 data nodemap_mmap: RefCell<Option<PyBuffer>>; |
93 data nodemap_mmap: RefCell<Option<PyBuffer>>; |
96 // Holds a reference to the mmap'ed persistent index data |
94 // Holds a reference to the mmap'ed persistent index data |
97 data index_mmap: RefCell<Option<PyBuffer>>; |
95 data index_mmap: RefCell<Option<PyBuffer>>; |
98 |
96 |
99 def __new__( |
97 def __new__( |
100 _cls, |
98 _cls, |
101 cindex: PyObject, |
|
102 data: PyObject, |
99 data: PyObject, |
103 default_header: u32, |
100 default_header: u32, |
104 ) -> PyResult<MixedIndex> { |
101 ) -> PyResult<MixedIndex> { |
105 Self::new(py, cindex, data, default_header) |
102 Self::new(py, data, default_header) |
106 } |
103 } |
107 |
104 |
108 /// Compatibility layer used for Python consumers needing access to the C index |
105 /// Compatibility layer used for Python consumers needing access to the C index |
109 /// |
106 /// |
110 /// Only use case so far is `scmutil.shortesthexnodeidprefix`, |
107 /// Only use case so far is `scmutil.shortesthexnodeidprefix`, |
111 /// that may need to build a custom `nodetree`, based on a specified revset. |
108 /// that may need to build a custom `nodetree`, based on a specified revset. |
112 /// With a Rust implementation of the nodemap, we will be able to get rid of |
109 /// With a Rust implementation of the nodemap, we will be able to get rid of |
113 /// this, by exposing our own standalone nodemap class, |
110 /// this, by exposing our own standalone nodemap class, |
114 /// ready to accept `MixedIndex`. |
111 /// ready to accept `Index`. |
115 def get_cindex(&self) -> PyResult<PyObject> { |
112 /* def get_cindex(&self) -> PyResult<PyObject> { |
116 Ok(self.cindex(py).borrow().inner().clone_ref(py)) |
113 Ok(self.cindex(py).borrow().inner().clone_ref(py)) |
117 } |
114 } |
118 |
115 */ |
119 // Index API involving nodemap, as defined in mercurial/pure/parsers.py |
116 // Index API involving nodemap, as defined in mercurial/pure/parsers.py |
120 |
117 |
121 /// Return Revision if found, raises a bare `error.RevlogError` |
118 /// Return Revision if found, raises a bare `error.RevlogError` |
122 /// in case of ambiguity, same as C version does |
119 /// in case of ambiguity, same as C version does |
123 def get_rev(&self, node: PyBytes) -> PyResult<Option<PyRevision>> { |
120 def get_rev(&self, node: PyBytes) -> PyResult<Option<PyRevision>> { |
600 }) |
597 }) |
601 } |
598 } |
602 } |
599 } |
603 |
600 |
604 impl MixedIndex { |
601 impl MixedIndex { |
605 fn new( |
602 fn new(py: Python, data: PyObject, header: u32) -> PyResult<MixedIndex> { |
606 py: Python, |
|
607 cindex: PyObject, |
|
608 data: PyObject, |
|
609 header: u32, |
|
610 ) -> PyResult<MixedIndex> { |
|
611 // Safety: we keep the buffer around inside the class as `index_mmap` |
603 // Safety: we keep the buffer around inside the class as `index_mmap` |
612 let (buf, bytes) = unsafe { mmap_keeparound(py, data)? }; |
604 let (buf, bytes) = unsafe { mmap_keeparound(py, data)? }; |
613 |
605 |
614 Self::create_instance( |
606 Self::create_instance( |
615 py, |
607 py, |
616 RefCell::new(cindex::Index::new(py, cindex)?), |
|
617 hg::index::Index::new( |
608 hg::index::Index::new( |
618 bytes, |
609 bytes, |
619 IndexHeader::parse(&header.to_be_bytes()) |
610 IndexHeader::parse(&header.to_be_bytes()) |
620 .expect("default header is broken") |
611 .expect("default header is broken") |
621 .unwrap(), |
612 .unwrap(), |
662 let mut nt = CoreNodeTree::load_bytes(readonly, 0); |
653 let mut nt = CoreNodeTree::load_bytes(readonly, 0); |
663 self.fill_nodemap(py, &mut nt)?; |
654 self.fill_nodemap(py, &mut nt)?; |
664 self.nt(py).borrow_mut().replace(nt); |
655 self.nt(py).borrow_mut().replace(nt); |
665 } |
656 } |
666 Ok(self.nt(py)) |
657 Ok(self.nt(py)) |
667 } |
|
668 |
|
669 pub fn clone_cindex(&self, py: Python) -> cindex::Index { |
|
670 self.cindex(py).borrow().clone_ref(py) |
|
671 } |
658 } |
672 |
659 |
673 /// Returns the full nodemap bytes to be written as-is to disk |
660 /// Returns the full nodemap bytes to be written as-is to disk |
674 fn inner_nodemap_data_all(&self, py: Python) -> PyResult<PyBytes> { |
661 fn inner_nodemap_data_all(&self, py: Python) -> PyResult<PyBytes> { |
675 let nodemap = self.get_nodetree(py)?.borrow_mut().take().unwrap(); |
662 let nodemap = self.get_nodetree(py)?.borrow_mut().take().unwrap(); |