#[cfg(feature = "python27")]
extern crate python27_sys as python_sys;
#[cfg(feature = "python3")]
extern crate python3_sys as python_sys;
use self::python_sys::PyCapsule_Import;
use cpython::{PyClone, PyErr, PyObject, PyResult, Python};
use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
use libc::c_int;
use std::ffi::CStr;
use std::mem::transmute;
type IndexParentsFn = unsafe extern "C" fn(
index: *mut python_sys::PyObject,
rev: c_int,
ps: *mut [c_int; 2],
) -> c_int;
pub struct Index {
index: PyObject,
parents: IndexParentsFn,
}
impl Index {
pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
Ok(Index {
index: index,
parents: decapsule_parents_fn(py)?,
})
}
}
impl Clone for Index {
fn clone(&self) -> Self {
let guard = Python::acquire_gil();
Index {
index: self.index.clone_ref(guard.python()),
parents: self.parents.clone(),
}
}
}
impl Graph for Index {
fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
if rev == WORKING_DIRECTORY_REVISION {
return Err(GraphError::WorkingDirectoryUnsupported);
}
let mut res: [c_int; 2] = [0; 2];
let code = unsafe {
(self.parents)(
self.index.as_ptr(),
rev as c_int,
&mut res as *mut [c_int; 2],
)
};
match code {
0 => Ok(res),
_ => Err(GraphError::ParentOutOfRange(rev)),
}
}
}
fn decapsule_parents_fn(py: Python) -> PyResult<IndexParentsFn> {
unsafe {
let caps_name = CStr::from_bytes_with_nul_unchecked(
b"mercurial.cext.parsers.index_get_parents_CAPI\0",
);
let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
if from_caps.is_null() {
return Err(PyErr::fetch(py));
}
Ok(transmute(from_caps))
}
}