##// END OF EJS Templates
rust-index: moved constructor in separate impl block...
Georges Racinet -
r44990:887d0f92 default
parent child Browse files
Show More
@@ -1,235 +1,241 b''
1 1 // revlog.rs
2 2 //
3 3 // Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 use crate::cindex;
9 9 use cpython::{
10 10 ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple,
11 11 Python, PythonObject, ToPyObject,
12 12 };
13 13 use hg::Revision;
14 14 use std::cell::RefCell;
15 15
16 16 /// Return a Struct implementing the Graph trait
17 17 pub(crate) fn pyindex_to_graph(
18 18 py: Python,
19 19 index: PyObject,
20 20 ) -> PyResult<cindex::Index> {
21 21 match index.extract::<MixedIndex>(py) {
22 22 Ok(midx) => Ok(midx.clone_cindex(py)),
23 23 Err(_) => cindex::Index::new(py, index),
24 24 }
25 25 }
26 26
27 27 py_class!(pub class MixedIndex |py| {
28 28 data cindex: RefCell<cindex::Index>;
29 29
30 30 def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> {
31 Self::create_instance(py, RefCell::new(
32 cindex::Index::new(py, cindex)?))
31 Self::new(py, cindex)
33 32 }
34 33
35 34 /// Compatibility layer used for Python consumers needing access to the C index
36 35 ///
37 36 /// Only use case so far is `scmutil.shortesthexnodeidprefix`,
38 37 /// that may need to build a custom `nodetree`, based on a specified revset.
39 38 /// With a Rust implementation of the nodemap, we will be able to get rid of
40 39 /// this, by exposing our own standalone nodemap class,
41 40 /// ready to accept `MixedIndex`.
42 41 def get_cindex(&self) -> PyResult<PyObject> {
43 42 Ok(self.cindex(py).borrow().inner().clone_ref(py))
44 43 }
45 44
46 45
47 46 // Reforwarded C index API
48 47
49 48 // index_methods (tp_methods). Same ordering as in revlog.c
50 49
51 50 /// return the gca set of the given revs
52 51 def ancestors(&self, *args, **kw) -> PyResult<PyObject> {
53 52 self.call_cindex(py, "ancestors", args, kw)
54 53 }
55 54
56 55 /// return the heads of the common ancestors of the given revs
57 56 def commonancestorsheads(&self, *args, **kw) -> PyResult<PyObject> {
58 57 self.call_cindex(py, "commonancestorsheads", args, kw)
59 58 }
60 59
61 60 /// clear the index caches
62 61 def clearcaches(&self, *args, **kw) -> PyResult<PyObject> {
63 62 self.call_cindex(py, "clearcaches", args, kw)
64 63 }
65 64
66 65 /// get an index entry
67 66 def get(&self, *args, **kw) -> PyResult<PyObject> {
68 67 self.call_cindex(py, "get", args, kw)
69 68 }
70 69
71 70 /// return `rev` associated with a node or None
72 71 def get_rev(&self, *args, **kw) -> PyResult<PyObject> {
73 72 self.call_cindex(py, "get_rev", args, kw)
74 73 }
75 74
76 75 /// return True if the node exist in the index
77 76 def has_node(&self, *args, **kw) -> PyResult<PyObject> {
78 77 self.call_cindex(py, "has_node", args, kw)
79 78 }
80 79
81 80 /// return `rev` associated with a node or raise RevlogError
82 81 def rev(&self, *args, **kw) -> PyResult<PyObject> {
83 82 self.call_cindex(py, "rev", args, kw)
84 83 }
85 84
86 85 /// compute phases
87 86 def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
88 87 self.call_cindex(py, "computephasesmapsets", args, kw)
89 88 }
90 89
91 90 /// reachableroots
92 91 def reachableroots2(&self, *args, **kw) -> PyResult<PyObject> {
93 92 self.call_cindex(py, "reachableroots2", args, kw)
94 93 }
95 94
96 95 /// get head revisions
97 96 def headrevs(&self, *args, **kw) -> PyResult<PyObject> {
98 97 self.call_cindex(py, "headrevs", args, kw)
99 98 }
100 99
101 100 /// get filtered head revisions
102 101 def headrevsfiltered(&self, *args, **kw) -> PyResult<PyObject> {
103 102 self.call_cindex(py, "headrevsfiltered", args, kw)
104 103 }
105 104
106 105 /// True if the object is a snapshot
107 106 def issnapshot(&self, *args, **kw) -> PyResult<PyObject> {
108 107 self.call_cindex(py, "issnapshot", args, kw)
109 108 }
110 109
111 110 /// Gather snapshot data in a cache dict
112 111 def findsnapshots(&self, *args, **kw) -> PyResult<PyObject> {
113 112 self.call_cindex(py, "findsnapshots", args, kw)
114 113 }
115 114
116 115 /// determine revisions with deltas to reconstruct fulltext
117 116 def deltachain(&self, *args, **kw) -> PyResult<PyObject> {
118 117 self.call_cindex(py, "deltachain", args, kw)
119 118 }
120 119
121 120 /// slice planned chunk read to reach a density threshold
122 121 def slicechunktodensity(&self, *args, **kw) -> PyResult<PyObject> {
123 122 self.call_cindex(py, "slicechunktodensity", args, kw)
124 123 }
125 124
126 125 /// append an index entry
127 126 def append(&self, *args, **kw) -> PyResult<PyObject> {
128 127 self.call_cindex(py, "append", args, kw)
129 128 }
130 129
131 130 /// match a potentially ambiguous node ID
132 131 def partialmatch(&self, *args, **kw) -> PyResult<PyObject> {
133 132 self.call_cindex(py, "partialmatch", args, kw)
134 133 }
135 134
136 135 /// find length of shortest hex nodeid of a binary ID
137 136 def shortest(&self, *args, **kw) -> PyResult<PyObject> {
138 137 self.call_cindex(py, "shortest", args, kw)
139 138 }
140 139
141 140 /// stats for the index
142 141 def stats(&self, *args, **kw) -> PyResult<PyObject> {
143 142 self.call_cindex(py, "stats", args, kw)
144 143 }
145 144
146 145 // index_sequence_methods and index_mapping_methods.
147 146 //
148 147 // Since we call back through the high level Python API,
149 148 // there's no point making a distinction between index_get
150 149 // and index_getitem.
151 150
152 151 def __len__(&self) -> PyResult<usize> {
153 152 self.cindex(py).borrow().inner().len(py)
154 153 }
155 154
156 155 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
157 156 // this conversion seems needless, but that's actually because
158 157 // `index_getitem` does not handle conversion from PyLong,
159 158 // which expressions such as [e for e in index] internally use.
160 159 // Note that we don't seem to have a direct way to call
161 160 // PySequence_GetItem (does the job), which would be better for
162 161 // for performance
163 162 let key = match key.extract::<Revision>(py) {
164 163 Ok(rev) => rev.to_py_object(py).into_object(),
165 164 Err(_) => key,
166 165 };
167 166 self.cindex(py).borrow().inner().get_item(py, key)
168 167 }
169 168
170 169 def __setitem__(&self, key: PyObject, value: PyObject) -> PyResult<()> {
171 170 self.cindex(py).borrow().inner().set_item(py, key, value)
172 171 }
173 172
174 173 def __delitem__(&self, key: PyObject) -> PyResult<()> {
175 174 self.cindex(py).borrow().inner().del_item(py, key)
176 175 }
177 176
178 177 def __contains__(&self, item: PyObject) -> PyResult<bool> {
179 178 // ObjectProtocol does not seem to provide contains(), so
180 179 // this is an equivalent implementation of the index_contains()
181 180 // defined in revlog.c
182 181 let cindex = self.cindex(py).borrow();
183 182 match item.extract::<Revision>(py) {
184 183 Ok(rev) => {
185 184 Ok(rev >= -1 && rev < cindex.inner().len(py)? as Revision)
186 185 }
187 186 Err(_) => {
188 187 cindex.inner().call_method(
189 188 py,
190 189 "has_node",
191 190 PyTuple::new(py, &[item]),
192 191 None)?
193 192 .extract(py)
194 193 }
195 194 }
196 195 }
197 196
198 197
199 198 });
200 199
201 200 impl MixedIndex {
201 fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> {
202 Self::create_instance(
203 py,
204 RefCell::new(cindex::Index::new(py, cindex)?),
205 )
206 }
207
202 208 /// forward a method call to the underlying C index
203 209 fn call_cindex(
204 210 &self,
205 211 py: Python,
206 212 name: &str,
207 213 args: &PyTuple,
208 214 kwargs: Option<&PyDict>,
209 215 ) -> PyResult<PyObject> {
210 216 self.cindex(py)
211 217 .borrow()
212 218 .inner()
213 219 .call_method(py, name, args, kwargs)
214 220 }
215 221
216 222 pub fn clone_cindex(&self, py: Python) -> cindex::Index {
217 223 self.cindex(py).borrow().clone_ref(py)
218 224 }
219 225 }
220 226
221 227 /// Create the module, with __package__ given from parent
222 228 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
223 229 let dotted_name = &format!("{}.revlog", package);
224 230 let m = PyModule::new(py, dotted_name)?;
225 231 m.add(py, "__package__", package)?;
226 232 m.add(py, "__doc__", "RevLog - Rust implementations")?;
227 233
228 234 m.add_class::<MixedIndex>(py)?;
229 235
230 236 let sys = PyModule::import(py, "sys")?;
231 237 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
232 238 sys_modules.set_item(py, dotted_name, &m)?;
233 239
234 240 Ok(m)
235 241 }
General Comments 0
You need to be logged in to leave comments. Login now