diff -r 10b465d61556 -r 13b64247f48f rust/hg-cpython/src/discovery.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-cpython/src/discovery.rs Wed Feb 20 09:04:39 2019 +0100 @@ -0,0 +1,114 @@ +// discovery.rs +// +// Copyright 2018 Georges Racinet +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +//! Bindings for the `hg::discovery` module provided by the +//! `hg-core` crate. From Python, this will be seen as `rustext.discovery` +//! +//! # Classes visible from Python: +//! - [`PartialDiscover`] is the Rust implementation of +//! `mercurial.setdiscovery.partialdiscovery`. + +use crate::conversion::{py_set, rev_pyiter_collect}; +use cindex::Index; +use cpython::{ObjectProtocol, PyDict, PyModule, PyObject, PyResult, Python}; +use exceptions::GraphError; +use hg::discovery::PartialDiscovery as CorePartialDiscovery; +use hg::Revision; + +use std::cell::RefCell; + +py_class!(pub class PartialDiscovery |py| { + data inner: RefCell>>; + + def __new__( + _cls, + index: PyObject, + targetheads: PyObject + ) -> PyResult { + Self::create_instance( + py, + RefCell::new(Box::new(CorePartialDiscovery::new( + Index::new(py, index)?, + rev_pyiter_collect(py, &targetheads)?, + ))) + ) + } + + def addcommons(&self, commons: PyObject) -> PyResult { + let mut inner = self.inner(py).borrow_mut(); + let commons_vec: Vec = rev_pyiter_collect(py, &commons)?; + inner.add_common_revisions(commons_vec) + .map_err(|e| GraphError::pynew(py, e))?; + Ok(py.None()) + } + + def addmissings(&self, missings: PyObject) -> PyResult { + let mut inner = self.inner(py).borrow_mut(); + let missings_vec: Vec = rev_pyiter_collect(py, &missings)?; + inner.add_missing_revisions(missings_vec) + .map_err(|e| GraphError::pynew(py, e))?; + Ok(py.None()) + } + + def addinfo(&self, sample: PyObject) -> PyResult { + let mut missing: Vec = Vec::new(); + let mut common: Vec = Vec::new(); + for info in sample.iter(py)? { // info is a pair (Revision, bool) + let mut revknown = info?.iter(py)?; + let rev: Revision = revknown.next().unwrap()?.extract(py)?; + let known: bool = revknown.next().unwrap()?.extract(py)?; + if known { + common.push(rev); + } else { + missing.push(rev); + } + } + let mut inner = self.inner(py).borrow_mut(); + inner.add_common_revisions(common) + .map_err(|e| GraphError::pynew(py, e))?; + inner.add_missing_revisions(missing) + .map_err(|e| GraphError::pynew(py, e))?; + Ok(py.None()) + } + + def hasinfo(&self) -> PyResult { + Ok(self.inner(py).borrow().has_info()) + } + + def iscomplete(&self) -> PyResult { + Ok(self.inner(py).borrow().is_complete()) + } + + def commonheads(&self) -> PyResult { + py_set( + py, + &self.inner(py).borrow().common_heads() + .map_err(|e| GraphError::pynew(py, e))? + ) + } +}); + +/// Create the module, with __package__ given from parent +pub fn init_module(py: Python, package: &str) -> PyResult { + let dotted_name = &format!("{}.discovery", package); + let m = PyModule::new(py, dotted_name)?; + m.add(py, "__package__", package)?; + m.add( + py, + "__doc__", + "Discovery of common node sets - Rust implementation", + )?; + m.add_class::(py)?; + + let sys = PyModule::import(py, "sys")?; + let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; + sys_modules.set_item(py, dotted_name, &m)?; + // Example C code (see pyexpat.c and import.c) will "give away the + // reference", but we won't because it will be consumed once the + // Rust PyObject is dropped. + Ok(m) +}