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