58 // |
58 // |
59 // It would be nice for UnsharedPyLeaked to provide this directly as a variant |
59 // It would be nice for UnsharedPyLeaked to provide this directly as a variant |
60 // of the `map` method with a signature such as: |
60 // of the `map` method with a signature such as: |
61 // |
61 // |
62 // ``` |
62 // ``` |
63 // unafe fn map_or_err(py: Python, |
63 // unsafe fn map_or_err(py: Python, |
64 // f: impl FnOnce(T) -> Result(U, E), |
64 // f: impl FnOnce(T) -> Result(U, E), |
65 // convert_err: impl FnOnce(Python, E) -> PyErr) |
65 // convert_err: impl FnOnce(Python, E) -> PyErr) |
66 // ``` |
66 // ``` |
67 // |
67 // |
68 // This would spare users of the `cpython` crate the additional `unsafe` deref |
68 // This would spare users of the `cpython` crate the additional `unsafe` deref |
69 // to inspect the error and return it outside `UnsafePyLeaked`, and the |
69 // to inspect the error and return it outside `UnsafePyLeaked`, and the |
70 // subsequent unwrapping that this function performs. |
70 // subsequent unwrapping that this function performs. |
72 py: Python, |
72 py: Python, |
73 leaked: UnsafePyLeaked<Result<T, E>>, |
73 leaked: UnsafePyLeaked<Result<T, E>>, |
74 convert_err: impl FnOnce(Python, E) -> PyErr, |
74 convert_err: impl FnOnce(Python, E) -> PyErr, |
75 ) -> PyResult<UnsafePyLeaked<T>> { |
75 ) -> PyResult<UnsafePyLeaked<T>> { |
76 // Result.inspect_err is unstable in Rust 1.61 |
76 // Result.inspect_err is unstable in Rust 1.61 |
|
77 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
77 if let Err(e) = *unsafe { leaked.try_borrow(py)? } { |
78 if let Err(e) = *unsafe { leaked.try_borrow(py)? } { |
78 return Err(convert_err(py, e)); |
79 return Err(convert_err(py, e)); |
79 } |
80 } |
|
81 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
80 Ok(unsafe { |
82 Ok(unsafe { |
81 leaked.map(py, |res| { |
83 leaked.map(py, |res| { |
82 res.expect("Error case should have already be treated") |
84 res.expect("Error case should have already be treated") |
83 }) |
85 }) |
84 }) |
86 }) |
87 py_class!(pub class AncestorsIterator |py| { |
89 py_class!(pub class AncestorsIterator |py| { |
88 data inner: RefCell<UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>>; |
90 data inner: RefCell<UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>>; |
89 |
91 |
90 def __next__(&self) -> PyResult<Option<PyRevision>> { |
92 def __next__(&self) -> PyResult<Option<PyRevision>> { |
91 let mut leaked = self.inner(py).borrow_mut(); |
93 let mut leaked = self.inner(py).borrow_mut(); |
|
94 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
92 let mut inner = unsafe { leaked.try_borrow_mut(py)? }; |
95 let mut inner = unsafe { leaked.try_borrow_mut(py)? }; |
93 match inner.next() { |
96 match inner.next() { |
94 Some(Err(e)) => Err(GraphError::pynew_from_vcsgraph(py, e)), |
97 Some(Err(e)) => Err(GraphError::pynew_from_vcsgraph(py, e)), |
95 None => Ok(None), |
98 None => Ok(None), |
96 Some(Ok(r)) => Ok(Some(PyRevision(r))), |
99 Some(Ok(r)) => Ok(Some(PyRevision(r))), |
97 } |
100 } |
98 } |
101 } |
99 |
102 |
100 def __contains__(&self, rev: PyRevision) -> PyResult<bool> { |
103 def __contains__(&self, rev: PyRevision) -> PyResult<bool> { |
101 let mut leaked = self.inner(py).borrow_mut(); |
104 let mut leaked = self.inner(py).borrow_mut(); |
|
105 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
102 let mut inner = unsafe { leaked.try_borrow_mut(py)? }; |
106 let mut inner = unsafe { leaked.try_borrow_mut(py)? }; |
103 inner.contains(rev.0) |
107 inner.contains(rev.0) |
104 .map_err(|e| GraphError::pynew_from_vcsgraph(py, e)) |
108 .map_err(|e| GraphError::pynew_from_vcsgraph(py, e)) |
105 } |
109 } |
106 |
110 |
134 initrevs: PyObject, |
138 initrevs: PyObject, |
135 stoprev: PyRevision, |
139 stoprev: PyRevision, |
136 inclusive: bool, |
140 inclusive: bool, |
137 ) -> PyResult<AncestorsIterator> { |
141 ) -> PyResult<AncestorsIterator> { |
138 let index = py_rust_index_to_graph(py, index)?; |
142 let index = py_rust_index_to_graph(py, index)?; |
|
143 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
139 let initvec: Vec<_> = { |
144 let initvec: Vec<_> = { |
140 let borrowed_idx = unsafe { index.try_borrow(py)? }; |
145 let borrowed_idx = unsafe { index.try_borrow(py)? }; |
141 rev_pyiter_collect(py, &initrevs, &*borrowed_idx)? |
146 rev_pyiter_collect(py, &initrevs, &*borrowed_idx)? |
142 }; |
147 }; |
|
148 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
143 let res_ait = unsafe { |
149 let res_ait = unsafe { |
144 index.map(py, |idx| { |
150 index.map(py, |idx| { |
145 VCGAncestorsIterator::new( |
151 VCGAncestorsIterator::new( |
146 idx, |
152 idx, |
147 initvec.into_iter().map(|r| r.0), |
153 initvec.into_iter().map(|r| r.0), |
165 data stoprev: PyRevision; |
171 data stoprev: PyRevision; |
166 data inclusive: bool; |
172 data inclusive: bool; |
167 |
173 |
168 def __contains__(&self, rev: PyRevision) -> PyResult<bool> { |
174 def __contains__(&self, rev: PyRevision) -> PyResult<bool> { |
169 let leaked = self.inner(py).borrow(); |
175 let leaked = self.inner(py).borrow(); |
|
176 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
170 let inner: &RefCell<VCGLazyAncestors<PySharedIndex>> = |
177 let inner: &RefCell<VCGLazyAncestors<PySharedIndex>> = |
171 &*unsafe { leaked.try_borrow(py)? }; |
178 &*unsafe { leaked.try_borrow(py)? }; |
172 let inner_mut: &mut VCGLazyAncestors<PySharedIndex> = |
179 let inner_mut: &mut VCGLazyAncestors<PySharedIndex> = |
173 &mut *inner.borrow_mut(); |
180 &mut *inner.borrow_mut(); |
174 inner_mut.contains(rev.0) |
181 inner_mut.contains(rev.0) |
198 inclusive: bool |
206 inclusive: bool |
199 ) -> PyResult<Self> { |
207 ) -> PyResult<Self> { |
200 let cloned_index = index.clone_ref(py); |
208 let cloned_index = index.clone_ref(py); |
201 let index = py_rust_index_to_graph(py, index)?; |
209 let index = py_rust_index_to_graph(py, index)?; |
202 let initvec: Vec<_> = { |
210 let initvec: Vec<_> = { |
|
211 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
203 let borrowed_idx = unsafe {index.try_borrow(py)?}; |
212 let borrowed_idx = unsafe {index.try_borrow(py)?}; |
204 rev_pyiter_collect(py, &initrevs, &*borrowed_idx)? |
213 rev_pyiter_collect(py, &initrevs, &*borrowed_idx)? |
205 }; |
214 }; |
206 |
215 |
|
216 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
207 let res_lazy = |
217 let res_lazy = |
208 unsafe { index.map(py, |idx| VCGLazyAncestors::new( |
218 unsafe { index.map(py, |idx| VCGLazyAncestors::new( |
209 idx, |
219 idx, |
210 initvec.into_iter().map(|r| r.0), |
220 initvec.into_iter().map(|r| r.0), |
211 stoprev.0, |
221 stoprev.0, |
212 inclusive |
222 inclusive |
213 ))}; |
223 ))}; |
214 let lazy = pyleaked_or_map_err(py, res_lazy, |
224 let lazy = pyleaked_or_map_err(py, res_lazy, |
215 GraphError::pynew_from_vcsgraph)?; |
225 GraphError::pynew_from_vcsgraph)?; |
|
226 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
216 let lazy_cell = unsafe { lazy.map(py, RefCell::new)}; |
227 let lazy_cell = unsafe { lazy.map(py, RefCell::new)}; |
217 let res = Self::create_instance( |
228 let res = Self::create_instance( |
218 py, RefCell::new(lazy_cell), |
229 py, RefCell::new(lazy_cell), |
219 cloned_index, initrevs, stoprev, inclusive)?; |
230 cloned_index, initrevs, stoprev, inclusive)?; |
220 Ok(res) |
231 Ok(res) |
234 bases: PyObject |
245 bases: PyObject |
235 ) |
246 ) |
236 -> PyResult<MissingAncestors> { |
247 -> PyResult<MissingAncestors> { |
237 let cloned_index = index.clone_ref(py); |
248 let cloned_index = index.clone_ref(py); |
238 let inner_index = py_rust_index_to_graph(py, index)?; |
249 let inner_index = py_rust_index_to_graph(py, index)?; |
|
250 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
239 let bases_vec: Vec<_> = { |
251 let bases_vec: Vec<_> = { |
240 let borrowed_idx = unsafe { inner_index.try_borrow(py)? }; |
252 let borrowed_idx = unsafe { inner_index.try_borrow(py)? }; |
241 rev_pyiter_collect(py, &bases, &*borrowed_idx)? |
253 rev_pyiter_collect(py, &bases, &*borrowed_idx)? |
242 }; |
254 }; |
243 |
255 |
|
256 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
244 let inner = unsafe { |
257 let inner = unsafe { |
245 inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec)) |
258 inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec)) |
246 }; |
259 }; |
247 MissingAncestors::create_instance( |
260 MissingAncestors::create_instance( |
248 py, |
261 py, |
251 ) |
264 ) |
252 } |
265 } |
253 |
266 |
254 def hasbases(&self) -> PyResult<bool> { |
267 def hasbases(&self) -> PyResult<bool> { |
255 let leaked = self.inner(py).borrow(); |
268 let leaked = self.inner(py).borrow(); |
|
269 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
256 let inner: &CoreMissing<PySharedIndex> = |
270 let inner: &CoreMissing<PySharedIndex> = |
257 &*unsafe { leaked.try_borrow(py)? }; |
271 &*unsafe { leaked.try_borrow(py)? }; |
258 Ok(inner.has_bases()) |
272 Ok(inner.has_bases()) |
259 } |
273 } |
260 |
274 |
261 def addbases(&self, bases: PyObject) -> PyResult<PyObject> { |
275 def addbases(&self, bases: PyObject) -> PyResult<PyObject> { |
262 let bases_vec: Vec<_> = { |
276 let bases_vec: Vec<_> = { |
263 let leaked = py_rust_index_to_graph(py, |
277 let leaked = py_rust_index_to_graph(py, |
264 self.index(py).clone_ref(py))?; |
278 self.index(py).clone_ref(py))?; |
|
279 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
265 let index = &*unsafe { leaked.try_borrow(py)? }; |
280 let index = &*unsafe { leaked.try_borrow(py)? }; |
266 rev_pyiter_collect(py, &bases, index)? |
281 rev_pyiter_collect(py, &bases, index)? |
267 }; |
282 }; |
268 |
283 |
269 let mut leaked = self.inner(py).borrow_mut(); |
284 let mut leaked = self.inner(py).borrow_mut(); |
|
285 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
270 let inner: &mut CoreMissing<PySharedIndex> = |
286 let inner: &mut CoreMissing<PySharedIndex> = |
271 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
287 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
272 |
288 |
273 inner.add_bases(bases_vec); |
289 inner.add_bases(bases_vec); |
274 // cpython doc has examples with PyResult<()> but this gives me |
290 // cpython doc has examples with PyResult<()> but this gives me |
277 Ok(py.None()) |
293 Ok(py.None()) |
278 } |
294 } |
279 |
295 |
280 def bases(&self) -> PyResult<HashSet<PyRevision>> { |
296 def bases(&self) -> PyResult<HashSet<PyRevision>> { |
281 let leaked = self.inner(py).borrow(); |
297 let leaked = self.inner(py).borrow(); |
|
298 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
282 let inner: &CoreMissing<PySharedIndex> = |
299 let inner: &CoreMissing<PySharedIndex> = |
283 &*unsafe { leaked.try_borrow(py)? }; |
300 &*unsafe { leaked.try_borrow(py)? }; |
284 Ok(inner.get_bases() |
301 Ok(inner.get_bases() |
285 .iter() |
302 .iter() |
286 .map(|r| PyRevision(r.0)) |
303 .map(|r| PyRevision(r.0)) |
313 // discard |
331 // discard |
314 // - define a trait for sets of revisions in the core and |
332 // - define a trait for sets of revisions in the core and |
315 // implement it for a Python set rewrapped with the GIL marker |
333 // implement it for a Python set rewrapped with the GIL marker |
316 let leaked = py_rust_index_to_graph(py, |
334 let leaked = py_rust_index_to_graph(py, |
317 self.index(py).clone_ref(py))?; |
335 self.index(py).clone_ref(py))?; |
|
336 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
318 let index = &*unsafe { leaked.try_borrow(py)? }; |
337 let index = &*unsafe { leaked.try_borrow(py)? }; |
319 rev_pyiter_collect(py, &revs, &*index)? |
338 rev_pyiter_collect(py, &revs, &*index)? |
320 }; |
339 }; |
321 |
340 |
322 let mut leaked = self.inner(py).borrow_mut(); |
341 let mut leaked = self.inner(py).borrow_mut(); |
|
342 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
323 let inner: &mut CoreMissing<PySharedIndex> = |
343 let inner: &mut CoreMissing<PySharedIndex> = |
324 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
344 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
325 |
345 |
326 inner.remove_ancestors_from(&mut revs_pyset) |
346 inner.remove_ancestors_from(&mut revs_pyset) |
327 .map_err(|e| GraphError::pynew(py, e))?; |
347 .map_err(|e| GraphError::pynew(py, e))?; |
340 |
360 |
341 def missingancestors(&self, revs: PyObject) -> PyResult<PyList> { |
361 def missingancestors(&self, revs: PyObject) -> PyResult<PyList> { |
342 let revs_vec: Vec<Revision> = { |
362 let revs_vec: Vec<Revision> = { |
343 let leaked = py_rust_index_to_graph(py, |
363 let leaked = py_rust_index_to_graph(py, |
344 self.index(py).clone_ref(py))?; |
364 self.index(py).clone_ref(py))?; |
|
365 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
345 let index = &*unsafe { leaked.try_borrow(py)? }; |
366 let index = &*unsafe { leaked.try_borrow(py)? }; |
346 rev_pyiter_collect(py, &revs, index)? |
367 rev_pyiter_collect(py, &revs, index)? |
347 }; |
368 }; |
348 |
369 |
349 let mut leaked = self.inner(py).borrow_mut(); |
370 let mut leaked = self.inner(py).borrow_mut(); |
|
371 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
350 let inner: &mut CoreMissing<PySharedIndex> = |
372 let inner: &mut CoreMissing<PySharedIndex> = |
351 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
373 &mut *unsafe { leaked.try_borrow_mut(py)? }; |
352 |
374 |
353 let missing_vec = match inner.missing_ancestors(revs_vec) { |
375 let missing_vec = match inner.missing_ancestors(revs_vec) { |
354 Ok(missing) => missing, |
376 Ok(missing) => missing, |