##// END OF EJS Templates
rust-discovery: moving most of hg-cpython methods to regular code blocks...
Georges Racinet -
r52135:2e2832e0 default
parent child Browse files
Show More
@@ -1,173 +1,234 b''
1 1 // discovery.rs
2 2 //
3 3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
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 //! Bindings for the `hg::discovery` module provided by the
9 9 //! `hg-core` crate. From Python, this will be seen as `rustext.discovery`
10 10 //!
11 11 //! # Classes visible from Python:
12 12 //! - [`PartialDiscovery`] is the Rust implementation of
13 13 //! `mercurial.setdiscovery.partialdiscovery`.
14 14
15 15 use crate::PyRevision;
16 16 use crate::{
17 17 cindex::Index, conversion::rev_pyiter_collect, exceptions::GraphError,
18 18 };
19 19 use cpython::{
20 20 ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple,
21 21 Python, PythonObject, ToPyObject,
22 22 };
23 23 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
24 24 use hg::Revision;
25 25 use std::collections::HashSet;
26 26
27 27 use std::cell::RefCell;
28 28
29 29 use crate::revlog::pyindex_to_graph;
30 30
31 31 py_class!(pub class PartialDiscovery |py| {
32 32 data inner: RefCell<Box<CorePartialDiscovery<Index>>>;
33 33 data index: RefCell<Index>;
34 34
35 35 // `_respectsize` is currently only here to replicate the Python API and
36 36 // will be used in future patches inside methods that are yet to be
37 37 // implemented.
38 38 def __new__(
39 39 _cls,
40 40 repo: PyObject,
41 41 targetheads: PyObject,
42 42 respectsize: bool,
43 43 randomize: bool = true
44 44 ) -> PyResult<PartialDiscovery> {
45 let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
46 let index = pyindex_to_graph(py, index)?;
47 let target_heads = rev_pyiter_collect(py, &targetheads, &index)?;
48 Self::create_instance(
49 py,
50 RefCell::new(Box::new(CorePartialDiscovery::new(
51 index.clone_ref(py),
52 target_heads,
53 respectsize,
54 randomize,
55 ))),
56 RefCell::new(index),
57 )
45 Self::inner_new(py, repo, targetheads, respectsize, randomize)
58 46 }
59 47
60 48 def addcommons(&self, commons: PyObject) -> PyResult<PyObject> {
61 let index = self.index(py).borrow();
62 let commons_vec: Vec<_> = rev_pyiter_collect(py, &commons, &*index)?;
63 let mut inner = self.inner(py).borrow_mut();
64 inner.add_common_revisions(commons_vec)
65 .map_err(|e| GraphError::pynew(py, e))?;
66 Ok(py.None())
67 }
49 self.inner_addcommons(py, commons)
50 }
68 51
69 52 def addmissings(&self, missings: PyObject) -> PyResult<PyObject> {
70 let index = self.index(py).borrow();
71 let missings_vec: Vec<_> = rev_pyiter_collect(py, &missings, &*index)?;
72 let mut inner = self.inner(py).borrow_mut();
73 inner.add_missing_revisions(missings_vec)
74 .map_err(|e| GraphError::pynew(py, e))?;
75 Ok(py.None())
53 self.inner_addmissings(py, missings)
76 54 }
77 55
78 56 def addinfo(&self, sample: PyObject) -> PyResult<PyObject> {
79 let mut missing: Vec<Revision> = Vec::new();
80 let mut common: Vec<Revision> = Vec::new();
81 for info in sample.iter(py)? { // info is a pair (Revision, bool)
82 let mut revknown = info?.iter(py)?;
83 let rev: PyRevision = revknown.next().unwrap()?.extract(py)?;
84 // This is fine since we're just using revisions as integers
85 // for the purposes of discovery
86 let rev = Revision(rev.0);
87 let known: bool = revknown.next().unwrap()?.extract(py)?;
88 if known {
89 common.push(rev);
90 } else {
91 missing.push(rev);
92 }
93 }
94 let mut inner = self.inner(py).borrow_mut();
95 inner.add_common_revisions(common)
96 .map_err(|e| GraphError::pynew(py, e))?;
97 inner.add_missing_revisions(missing)
98 .map_err(|e| GraphError::pynew(py, e))?;
99 Ok(py.None())
57 self.inner_addinfo(py, sample)
100 58 }
101 59
102 60 def hasinfo(&self) -> PyResult<bool> {
103 61 Ok(self.inner(py).borrow().has_info())
104 62 }
105 63
106 64 def iscomplete(&self) -> PyResult<bool> {
107 65 Ok(self.inner(py).borrow().is_complete())
108 66 }
109 67
110 68 def stats(&self) -> PyResult<PyDict> {
111 69 let stats = self.inner(py).borrow().stats();
112 70 let as_dict: PyDict = PyDict::new(py);
113 71 as_dict.set_item(py, "undecided",
114 72 stats.undecided.map(
115 73 |l| l.to_py_object(py).into_object())
116 74 .unwrap_or_else(|| py.None()))?;
117 75 Ok(as_dict)
118 76 }
119 77
120 78 def commonheads(&self) -> PyResult<HashSet<PyRevision>> {
121 79 let res = self.inner(py).borrow().common_heads()
122 80 .map_err(|e| GraphError::pynew(py, e))?;
123 81 Ok(res.into_iter().map(Into::into).collect())
124 82 }
125 83
126 def takefullsample(&self, _headrevs: PyObject,
84 def takefullsample(&self, headrevs: PyObject,
127 85 size: usize) -> PyResult<PyObject> {
86 self.inner_takefullsample(py, headrevs, size)
87 }
88
89 def takequicksample(&self, headrevs: PyObject,
90 size: usize) -> PyResult<PyObject> {
91 self.inner_takequicksample(py, headrevs, size)
92 }
93
94 });
95
96 impl PartialDiscovery {
97 fn inner_new(
98 py: Python,
99 repo: PyObject,
100 targetheads: PyObject,
101 respectsize: bool,
102 randomize: bool,
103 ) -> PyResult<Self> {
104 let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
105 let index = pyindex_to_graph(py, index)?;
106 let target_heads = rev_pyiter_collect(py, &targetheads, &index)?;
107 Self::create_instance(
108 py,
109 RefCell::new(Box::new(CorePartialDiscovery::new(
110 index.clone_ref(py),
111 target_heads,
112 respectsize,
113 randomize,
114 ))),
115 RefCell::new(index),
116 )
117 }
118
119 fn inner_addinfo(
120 &self,
121 py: Python,
122 sample: PyObject,
123 ) -> PyResult<PyObject> {
124 let mut missing: Vec<Revision> = Vec::new();
125 let mut common: Vec<Revision> = Vec::new();
126 for info in sample.iter(py)? {
127 // info is a pair (Revision, bool)
128 let mut revknown = info?.iter(py)?;
129 let rev: PyRevision = revknown.next().unwrap()?.extract(py)?;
130 // This is fine since we're just using revisions as integers
131 // for the purposes of discovery
132 let rev = Revision(rev.0);
133 let known: bool = revknown.next().unwrap()?.extract(py)?;
134 if known {
135 common.push(rev);
136 } else {
137 missing.push(rev);
138 }
139 }
128 140 let mut inner = self.inner(py).borrow_mut();
129 let sample = inner.take_full_sample(size)
141 inner
142 .add_common_revisions(common)
143 .map_err(|e| GraphError::pynew(py, e))?;
144 inner
145 .add_missing_revisions(missing)
146 .map_err(|e| GraphError::pynew(py, e))?;
147 Ok(py.None())
148 }
149
150 fn inner_addcommons(
151 &self,
152 py: Python,
153 commons: PyObject,
154 ) -> PyResult<PyObject> {
155 let index = self.index(py).borrow();
156 let commons_vec: Vec<_> = rev_pyiter_collect(py, &commons, &*index)?;
157 let mut inner = self.inner(py).borrow_mut();
158 inner
159 .add_common_revisions(commons_vec)
160 .map_err(|e| GraphError::pynew(py, e))?;
161 Ok(py.None())
162 }
163
164 fn inner_addmissings(
165 &self,
166 py: Python,
167 missings: PyObject,
168 ) -> PyResult<PyObject> {
169 let index = self.index(py).borrow();
170 let missings_vec: Vec<_> = rev_pyiter_collect(py, &missings, &*index)?;
171 let mut inner = self.inner(py).borrow_mut();
172 inner
173 .add_missing_revisions(missings_vec)
174 .map_err(|e| GraphError::pynew(py, e))?;
175 Ok(py.None())
176 }
177
178 fn inner_takefullsample(
179 &self,
180 py: Python,
181 _headrevs: PyObject,
182 size: usize,
183 ) -> PyResult<PyObject> {
184 let mut inner = self.inner(py).borrow_mut();
185 let sample = inner
186 .take_full_sample(size)
130 187 .map_err(|e| GraphError::pynew(py, e))?;
131 188 let as_vec: Vec<PyObject> = sample
132 189 .iter()
133 190 .map(|rev| PyRevision(rev.0).to_py_object(py).into_object())
134 191 .collect();
135 192 Ok(PyTuple::new(py, as_vec.as_slice()).into_object())
136 193 }
137 194
138 def takequicksample(&self, headrevs: PyObject,
139 size: usize) -> PyResult<PyObject> {
195 fn inner_takequicksample(
196 &self,
197 py: Python,
198 headrevs: PyObject,
199 size: usize,
200 ) -> PyResult<PyObject> {
140 201 let index = self.index(py).borrow();
141 202 let mut inner = self.inner(py).borrow_mut();
142 203 let revsvec: Vec<_> = rev_pyiter_collect(py, &headrevs, &*index)?;
143 let sample = inner.take_quick_sample(revsvec, size)
204 let sample = inner
205 .take_quick_sample(revsvec, size)
144 206 .map_err(|e| GraphError::pynew(py, e))?;
145 207 let as_vec: Vec<PyObject> = sample
146 208 .iter()
147 209 .map(|rev| PyRevision(rev.0).to_py_object(py).into_object())
148 210 .collect();
149 211 Ok(PyTuple::new(py, as_vec.as_slice()).into_object())
150 212 }
151
152 });
213 }
153 214
154 215 /// Create the module, with __package__ given from parent
155 216 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
156 217 let dotted_name = &format!("{}.discovery", package);
157 218 let m = PyModule::new(py, dotted_name)?;
158 219 m.add(py, "__package__", package)?;
159 220 m.add(
160 221 py,
161 222 "__doc__",
162 223 "Discovery of common node sets - Rust implementation",
163 224 )?;
164 225 m.add_class::<PartialDiscovery>(py)?;
165 226
166 227 let sys = PyModule::import(py, "sys")?;
167 228 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
168 229 sys_modules.set_item(py, dotted_name, &m)?;
169 230 // Example C code (see pyexpat.c and import.c) will "give away the
170 231 // reference", but we won't because it will be consumed once the
171 232 // Rust PyObject is dropped.
172 233 Ok(m)
173 234 }
General Comments 0
You need to be logged in to leave comments. Login now