rust/hg-cpython/src/discovery.rs
changeset 51245 0b81440e2a73
parent 51243 0993a3520dc6
child 51255 24d3298189d7
equal deleted inserted replaced
51244:03fdd4d7b5bd 51245:0b81440e2a73
    12 //! - [`PartialDiscovery`] is the Rust implementation of
    12 //! - [`PartialDiscovery`] is the Rust implementation of
    13 //!   `mercurial.setdiscovery.partialdiscovery`.
    13 //!   `mercurial.setdiscovery.partialdiscovery`.
    14 
    14 
    15 use crate::PyRevision;
    15 use crate::PyRevision;
    16 use crate::{
    16 use crate::{
    17     cindex::Index, conversion::rev_pyiter_collect, exceptions::GraphError,
    17     conversion::rev_pyiter_collect, exceptions::GraphError,
       
    18     revlog::PySharedIndex,
    18 };
    19 };
    19 use cpython::{
    20 use cpython::{
    20     ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple,
    21     ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple,
    21     Python, PythonObject, ToPyObject,
    22     Python, PythonObject, ToPyObject, UnsafePyLeaked,
    22 };
    23 };
    23 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
    24 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
    24 use hg::Revision;
    25 use hg::Revision;
    25 use std::collections::HashSet;
    26 use std::collections::HashSet;
    26 
    27 
    27 use std::cell::RefCell;
    28 use std::cell::RefCell;
    28 
    29 
    29 use crate::revlog::pyindex_to_graph;
    30 use crate::revlog::py_rust_index_to_graph;
    30 
    31 
    31 py_class!(pub class PartialDiscovery |py| {
    32 py_class!(pub class PartialDiscovery |py| {
    32     data inner: RefCell<Box<CorePartialDiscovery<Index>>>;
    33     data inner: RefCell<UnsafePyLeaked<CorePartialDiscovery<PySharedIndex>>>;
    33     data index: RefCell<Index>;
    34     data index: RefCell<UnsafePyLeaked<PySharedIndex>>;
    34 
    35 
    35     // `_respectsize` is currently only here to replicate the Python API and
    36     // `_respectsize` is currently only here to replicate the Python API and
    36     // will be used in future patches inside methods that are yet to be
    37     // will be used in future patches inside methods that are yet to be
    37     // implemented.
    38     // implemented.
    38     def __new__(
    39     def __new__(
    56     def addinfo(&self, sample: PyObject) -> PyResult<PyObject> {
    57     def addinfo(&self, sample: PyObject) -> PyResult<PyObject> {
    57         self.inner_addinfo(py, sample)
    58         self.inner_addinfo(py, sample)
    58     }
    59     }
    59 
    60 
    60     def hasinfo(&self) -> PyResult<bool> {
    61     def hasinfo(&self) -> PyResult<bool> {
    61         Ok(self.inner(py).borrow().has_info())
    62         let leaked = self.inner(py).borrow();
       
    63         let inner = unsafe { leaked.try_borrow(py)? };
       
    64         Ok(inner.has_info())
    62     }
    65     }
    63 
    66 
    64     def iscomplete(&self) -> PyResult<bool> {
    67     def iscomplete(&self) -> PyResult<bool> {
    65         Ok(self.inner(py).borrow().is_complete())
    68         let leaked = self.inner(py).borrow();
       
    69         let inner = unsafe { leaked.try_borrow(py)? };
       
    70         Ok(inner.is_complete())
    66     }
    71     }
    67 
    72 
    68     def stats(&self) -> PyResult<PyDict> {
    73     def stats(&self) -> PyResult<PyDict> {
    69         let stats = self.inner(py).borrow().stats();
    74         let leaked = self.inner(py).borrow();
       
    75         let inner = unsafe { leaked.try_borrow(py)? };
       
    76         let stats = inner.stats();
    70         let as_dict: PyDict = PyDict::new(py);
    77         let as_dict: PyDict = PyDict::new(py);
    71         as_dict.set_item(py, "undecided",
    78         as_dict.set_item(py, "undecided",
    72                          stats.undecided.map(
    79                          stats.undecided.map(
    73                              |l| l.to_py_object(py).into_object())
    80                              |l| l.to_py_object(py).into_object())
    74                              .unwrap_or_else(|| py.None()))?;
    81                              .unwrap_or_else(|| py.None()))?;
    75         Ok(as_dict)
    82         Ok(as_dict)
    76     }
    83     }
    77 
    84 
    78     def commonheads(&self) -> PyResult<HashSet<PyRevision>> {
    85     def commonheads(&self) -> PyResult<HashSet<PyRevision>> {
    79         let res = self.inner(py).borrow().common_heads()
    86         let leaked = self.inner(py).borrow();
       
    87         let inner = unsafe { leaked.try_borrow(py)? };
       
    88         let res = inner.common_heads()
    80                     .map_err(|e| GraphError::pynew(py, e))?;
    89                     .map_err(|e| GraphError::pynew(py, e))?;
    81         Ok(res.into_iter().map(Into::into).collect())
    90         Ok(res.into_iter().map(Into::into).collect())
    82     }
    91     }
    83 
    92 
    84     def takefullsample(&self, headrevs: PyObject,
    93     def takefullsample(&self, headrevs: PyObject,
   100         targetheads: PyObject,
   109         targetheads: PyObject,
   101         respectsize: bool,
   110         respectsize: bool,
   102         randomize: bool,
   111         randomize: bool,
   103     ) -> PyResult<Self> {
   112     ) -> PyResult<Self> {
   104         let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
   113         let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
   105         let index = pyindex_to_graph(py, index)?;
   114         let cloned_index = py_rust_index_to_graph(py, index.clone_ref(py))?;
   106         let target_heads = rev_pyiter_collect(py, &targetheads, &index)?;
   115         let index = py_rust_index_to_graph(py, index)?;
       
   116 
       
   117         let target_heads = {
       
   118             let borrowed_idx = unsafe { index.try_borrow(py)? };
       
   119             rev_pyiter_collect(py, &targetheads, &*borrowed_idx)?
       
   120         };
       
   121         let lazy_disco = unsafe {
       
   122             index.map(py, |idx| {
       
   123                 CorePartialDiscovery::new(
       
   124                     idx,
       
   125                     target_heads,
       
   126                     respectsize,
       
   127                     randomize,
       
   128                 )
       
   129             })
       
   130         };
   107         Self::create_instance(
   131         Self::create_instance(
   108             py,
   132             py,
   109             RefCell::new(Box::new(CorePartialDiscovery::new(
   133             RefCell::new(lazy_disco),
   110                 index.clone_ref(py),
   134             RefCell::new(cloned_index),
   111                 target_heads,
       
   112                 respectsize,
       
   113                 randomize,
       
   114             ))),
       
   115             RefCell::new(index),
       
   116         )
   135         )
   117     }
   136     }
   118 
   137 
   119     /// Convert a Python iterator of revisions into a vector
   138     /// Convert a Python iterator of revisions into a vector
   120     fn pyiter_to_vec(
   139     fn pyiter_to_vec(
   121         &self,
   140         &self,
   122         py: Python,
   141         py: Python,
   123         iter: &PyObject,
   142         iter: &PyObject,
   124     ) -> PyResult<Vec<Revision>> {
   143     ) -> PyResult<Vec<Revision>> {
   125         let index = self.index(py).borrow();
   144         let leaked = self.index(py).borrow();
       
   145         let index = unsafe { leaked.try_borrow(py)? };
   126         rev_pyiter_collect(py, iter, &*index)
   146         rev_pyiter_collect(py, iter, &*index)
   127     }
   147     }
   128 
   148 
   129     fn inner_addinfo(
   149     fn inner_addinfo(
   130         &self,
   150         &self,
   145                 common.push(rev);
   165                 common.push(rev);
   146             } else {
   166             } else {
   147                 missing.push(rev);
   167                 missing.push(rev);
   148             }
   168             }
   149         }
   169         }
   150         let mut inner = self.inner(py).borrow_mut();
   170         let mut leaked = self.inner(py).borrow_mut();
       
   171         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   151         inner
   172         inner
   152             .add_common_revisions(common)
   173             .add_common_revisions(common)
   153             .map_err(|e| GraphError::pynew(py, e))?;
   174             .map_err(|e| GraphError::pynew(py, e))?;
   154         inner
   175         inner
   155             .add_missing_revisions(missing)
   176             .add_missing_revisions(missing)
   161         &self,
   182         &self,
   162         py: Python,
   183         py: Python,
   163         commons: PyObject,
   184         commons: PyObject,
   164     ) -> PyResult<PyObject> {
   185     ) -> PyResult<PyObject> {
   165         let commons_vec = self.pyiter_to_vec(py, &commons)?;
   186         let commons_vec = self.pyiter_to_vec(py, &commons)?;
   166         let mut inner = self.inner(py).borrow_mut();
   187         let mut leaked = self.inner(py).borrow_mut();
       
   188         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   167         inner
   189         inner
   168             .add_common_revisions(commons_vec)
   190             .add_common_revisions(commons_vec)
   169             .map_err(|e| GraphError::pynew(py, e))?;
   191             .map_err(|e| GraphError::pynew(py, e))?;
   170         Ok(py.None())
   192         Ok(py.None())
   171     }
   193     }
   174         &self,
   196         &self,
   175         py: Python,
   197         py: Python,
   176         missings: PyObject,
   198         missings: PyObject,
   177     ) -> PyResult<PyObject> {
   199     ) -> PyResult<PyObject> {
   178         let missings_vec = self.pyiter_to_vec(py, &missings)?;
   200         let missings_vec = self.pyiter_to_vec(py, &missings)?;
   179         let mut inner = self.inner(py).borrow_mut();
   201         let mut leaked = self.inner(py).borrow_mut();
       
   202         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   180         inner
   203         inner
   181             .add_missing_revisions(missings_vec)
   204             .add_missing_revisions(missings_vec)
   182             .map_err(|e| GraphError::pynew(py, e))?;
   205             .map_err(|e| GraphError::pynew(py, e))?;
   183         Ok(py.None())
   206         Ok(py.None())
   184     }
   207     }
   187         &self,
   210         &self,
   188         py: Python,
   211         py: Python,
   189         _headrevs: PyObject,
   212         _headrevs: PyObject,
   190         size: usize,
   213         size: usize,
   191     ) -> PyResult<PyObject> {
   214     ) -> PyResult<PyObject> {
   192         let mut inner = self.inner(py).borrow_mut();
   215         let mut leaked = self.inner(py).borrow_mut();
       
   216         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   193         let sample = inner
   217         let sample = inner
   194             .take_full_sample(size)
   218             .take_full_sample(size)
   195             .map_err(|e| GraphError::pynew(py, e))?;
   219             .map_err(|e| GraphError::pynew(py, e))?;
   196         let as_vec: Vec<PyObject> = sample
   220         let as_vec: Vec<PyObject> = sample
   197             .iter()
   221             .iter()
   205         py: Python,
   229         py: Python,
   206         headrevs: PyObject,
   230         headrevs: PyObject,
   207         size: usize,
   231         size: usize,
   208     ) -> PyResult<PyObject> {
   232     ) -> PyResult<PyObject> {
   209         let revsvec = self.pyiter_to_vec(py, &headrevs)?;
   233         let revsvec = self.pyiter_to_vec(py, &headrevs)?;
   210         let mut inner = self.inner(py).borrow_mut();
   234         let mut leaked = self.inner(py).borrow_mut();
       
   235         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   211         let sample = inner
   236         let sample = inner
   212             .take_quick_sample(revsvec, size)
   237             .take_quick_sample(revsvec, size)
   213             .map_err(|e| GraphError::pynew(py, e))?;
   238             .map_err(|e| GraphError::pynew(py, e))?;
   214         let as_vec: Vec<PyObject> = sample
   239         let as_vec: Vec<PyObject> = sample
   215             .iter()
   240             .iter()