Mercurial > hg
comparison rust/hg-cpython/src/ancestors.rs @ 51240:59d81768ad6d
rust-index: using `hg::index::Index` in MissingAncestors
With this, the whole `hg-cpython::ancestors` module can now work without
the C index.
author | Georges Racinet on incendie.racinet.fr <georges@racinet.fr> |
---|---|
date | Sat, 28 Oct 2023 22:50:10 +0200 |
parents | 7eea2e4109ae |
children | 24d3298189d7 |
comparison
equal
deleted
inserted
replaced
51239:7eea2e4109ae | 51240:59d81768ad6d |
---|---|
32 //! instance. | 32 //! instance. |
33 //! | 33 //! |
34 //! [`LazyAncestors`]: struct.LazyAncestors.html | 34 //! [`LazyAncestors`]: struct.LazyAncestors.html |
35 //! [`MissingAncestors`]: struct.MissingAncestors.html | 35 //! [`MissingAncestors`]: struct.MissingAncestors.html |
36 //! [`AncestorsIterator`]: struct.AncestorsIterator.html | 36 //! [`AncestorsIterator`]: struct.AncestorsIterator.html |
37 use crate::revlog::{py_rust_index_to_graph, pyindex_to_graph}; | 37 use crate::revlog::py_rust_index_to_graph; |
38 use crate::PyRevision; | 38 use crate::PyRevision; |
39 use crate::{ | 39 use crate::{ |
40 cindex::Index, conversion::rev_pyiter_collect, exceptions::GraphError, | 40 conversion::rev_pyiter_collect, exceptions::GraphError, |
41 revlog::PySharedIndex, | 41 revlog::PySharedIndex, |
42 }; | 42 }; |
43 use cpython::{ | 43 use cpython::{ |
44 ObjectProtocol, PyClone, PyDict, PyErr, PyList, PyModule, PyObject, | 44 ObjectProtocol, PyClone, PyDict, PyErr, PyList, PyModule, PyObject, |
45 PyResult, Python, PythonObject, ToPyObject, UnsafePyLeaked, | 45 PyResult, Python, PythonObject, ToPyObject, UnsafePyLeaked, |
221 } | 221 } |
222 | 222 |
223 }); | 223 }); |
224 | 224 |
225 py_class!(pub class MissingAncestors |py| { | 225 py_class!(pub class MissingAncestors |py| { |
226 data inner: RefCell<Box<CoreMissing<Index>>>; | 226 data inner: RefCell<UnsafePyLeaked< |
227 data index: RefCell<Index>; | 227 CoreMissing<PySharedIndex> |
228 >>; | |
229 data index: PyObject; | |
228 | 230 |
229 def __new__( | 231 def __new__( |
230 _cls, | 232 _cls, |
231 index: PyObject, | 233 index: PyObject, |
232 bases: PyObject | 234 bases: PyObject |
233 ) | 235 ) |
234 -> PyResult<MissingAncestors> { | 236 -> PyResult<MissingAncestors> { |
235 let index = pyindex_to_graph(py, index)?; | 237 let cloned_index = index.clone_ref(py); |
236 let bases_vec: Vec<_> = rev_pyiter_collect(py, &bases, &index)?; | 238 let inner_index = py_rust_index_to_graph(py, index)?; |
237 | 239 let bases_vec: Vec<_> = { |
238 let inner = CoreMissing::new(index.clone_ref(py), bases_vec); | 240 let borrowed_idx = unsafe { inner_index.try_borrow(py)? }; |
241 rev_pyiter_collect(py, &bases, &*borrowed_idx)? | |
242 }; | |
243 | |
244 let inner = unsafe { | |
245 inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec)) | |
246 }; | |
239 MissingAncestors::create_instance( | 247 MissingAncestors::create_instance( |
240 py, | 248 py, |
241 RefCell::new(Box::new(inner)), | 249 RefCell::new(inner), |
242 RefCell::new(index) | 250 cloned_index, |
243 ) | 251 ) |
244 } | 252 } |
245 | 253 |
246 def hasbases(&self) -> PyResult<bool> { | 254 def hasbases(&self) -> PyResult<bool> { |
247 Ok(self.inner(py).borrow().has_bases()) | 255 let leaked = self.inner(py).borrow(); |
256 let inner: &CoreMissing<PySharedIndex> = | |
257 &*unsafe { leaked.try_borrow(py)? }; | |
258 Ok(inner.has_bases()) | |
248 } | 259 } |
249 | 260 |
250 def addbases(&self, bases: PyObject) -> PyResult<PyObject> { | 261 def addbases(&self, bases: PyObject) -> PyResult<PyObject> { |
251 let index = self.index(py).borrow(); | 262 let bases_vec: Vec<_> = { |
252 let bases_vec: Vec<_> = rev_pyiter_collect(py, &bases, &*index)?; | 263 let leaked = py_rust_index_to_graph(py, |
253 let mut inner = self.inner(py).borrow_mut(); | 264 self.index(py).clone_ref(py))?; |
265 let index = &*unsafe { leaked.try_borrow(py)? }; | |
266 rev_pyiter_collect(py, &bases, index)? | |
267 }; | |
268 | |
269 let mut leaked = self.inner(py).borrow_mut(); | |
270 let inner: &mut CoreMissing<PySharedIndex> = | |
271 &mut *unsafe { leaked.try_borrow_mut(py)? }; | |
272 | |
254 inner.add_bases(bases_vec); | 273 inner.add_bases(bases_vec); |
255 // cpython doc has examples with PyResult<()> but this gives me | 274 // cpython doc has examples with PyResult<()> but this gives me |
256 // the trait `cpython::ToPyObject` is not implemented for `()` | 275 // the trait `cpython::ToPyObject` is not implemented for `()` |
257 // so let's return an explicit None | 276 // so let's return an explicit None |
258 Ok(py.None()) | 277 Ok(py.None()) |
259 } | 278 } |
260 | 279 |
261 def bases(&self) -> PyResult<HashSet<PyRevision>> { | 280 def bases(&self) -> PyResult<HashSet<PyRevision>> { |
262 Ok( | 281 let leaked = self.inner(py).borrow(); |
263 self.inner(py) | 282 let inner: &CoreMissing<PySharedIndex> = |
264 .borrow() | 283 &*unsafe { leaked.try_borrow(py)? }; |
265 .get_bases() | 284 Ok(inner.get_bases() |
266 .iter() | 285 .iter() |
267 .map(|r| PyRevision(r.0)) | 286 .map(|r| PyRevision(r.0)) |
268 .collect() | 287 .collect() |
269 ) | 288 ) |
270 } | 289 } |
271 | 290 |
272 def basesheads(&self) -> PyResult<HashSet<PyRevision>> { | 291 def basesheads(&self) -> PyResult<HashSet<PyRevision>> { |
273 let inner = self.inner(py).borrow(); | 292 let leaked = self.inner(py).borrow(); |
293 let inner: &CoreMissing<PySharedIndex> = | |
294 &*unsafe { leaked.try_borrow(py)? }; | |
274 Ok( | 295 Ok( |
275 inner | 296 inner |
276 .bases_heads() | 297 .bases_heads() |
277 .map_err(|e| GraphError::pynew(py, e))? | 298 .map_err(|e| GraphError::pynew(py, e))? |
278 .into_iter() | 299 .into_iter() |
280 .collect() | 301 .collect() |
281 ) | 302 ) |
282 } | 303 } |
283 | 304 |
284 def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> { | 305 def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> { |
285 let index = self.index(py).borrow(); | 306 let mut revs_pyset: HashSet<Revision> = { |
286 // this is very lame: we convert to a Rust set, update it in place | 307 // this is very lame: we convert to a Rust set, update it in place |
287 // and then convert back to Python, only to have Python remove the | 308 // and then convert back to Python, only to have Python remove the |
288 // excess (thankfully, Python is happy with a list or even an iterator) | 309 // excess (thankfully, Python is happy with a list or even an |
289 // Leads to improve this: | 310 // iterator) |
290 // - have the CoreMissing instead do something emit revisions to | 311 // Leads to improve this: |
291 // discard | 312 // - have the CoreMissing instead do something emit revisions to |
292 // - define a trait for sets of revisions in the core and implement | 313 // discard |
293 // it for a Python set rewrapped with the GIL marker | 314 // - define a trait for sets of revisions in the core and |
294 let mut revs_pyset: HashSet<Revision> = rev_pyiter_collect( | 315 // implement it for a Python set rewrapped with the GIL marker |
295 py, &revs, &*index | 316 let leaked = py_rust_index_to_graph(py, |
296 )?; | 317 self.index(py).clone_ref(py))?; |
297 let mut inner = self.inner(py).borrow_mut(); | 318 let index = &*unsafe { leaked.try_borrow(py)? }; |
319 rev_pyiter_collect(py, &revs, &*index)? | |
320 }; | |
321 | |
322 let mut leaked = self.inner(py).borrow_mut(); | |
323 let inner: &mut CoreMissing<PySharedIndex> = | |
324 &mut *unsafe { leaked.try_borrow_mut(py)? }; | |
325 | |
298 inner.remove_ancestors_from(&mut revs_pyset) | 326 inner.remove_ancestors_from(&mut revs_pyset) |
299 .map_err(|e| GraphError::pynew(py, e))?; | 327 .map_err(|e| GraphError::pynew(py, e))?; |
300 | 328 |
301 // convert as Python list | 329 // convert as Python list |
302 let mut remaining_pyint_vec: Vec<PyObject> = Vec::with_capacity( | 330 let mut remaining_pyint_vec: Vec<PyObject> = Vec::with_capacity( |
309 let remaining_pylist = PyList::new(py, remaining_pyint_vec.as_slice()); | 337 let remaining_pylist = PyList::new(py, remaining_pyint_vec.as_slice()); |
310 revs.call_method(py, "intersection_update", (remaining_pylist, ), None) | 338 revs.call_method(py, "intersection_update", (remaining_pylist, ), None) |
311 } | 339 } |
312 | 340 |
313 def missingancestors(&self, revs: PyObject) -> PyResult<PyList> { | 341 def missingancestors(&self, revs: PyObject) -> PyResult<PyList> { |
314 let index = self.index(py).borrow(); | 342 let revs_vec: Vec<Revision> = { |
315 let revs_vec: Vec<Revision> = rev_pyiter_collect(py, &revs, &*index)?; | 343 let leaked = py_rust_index_to_graph(py, |
316 | 344 self.index(py).clone_ref(py))?; |
317 let mut inner = self.inner(py).borrow_mut(); | 345 let index = &*unsafe { leaked.try_borrow(py)? }; |
346 rev_pyiter_collect(py, &revs, index)? | |
347 }; | |
348 | |
349 let mut leaked = self.inner(py).borrow_mut(); | |
350 let inner: &mut CoreMissing<PySharedIndex> = | |
351 &mut *unsafe { leaked.try_borrow_mut(py)? }; | |
352 | |
318 let missing_vec = match inner.missing_ancestors(revs_vec) { | 353 let missing_vec = match inner.missing_ancestors(revs_vec) { |
319 Ok(missing) => missing, | 354 Ok(missing) => missing, |
320 Err(e) => { | 355 Err(e) => { |
321 return Err(GraphError::pynew(py, e)); | 356 return Err(GraphError::pynew(py, e)); |
322 } | 357 } |