rust-dirstate: create dirstate submodule in hg-cpython
This module will soon hold multiple files, this change is to make the
review process easier.
Differential Revision: https://phab.mercurial-scm.org/D6626
--- a/rust/hg-cpython/src/dirstate.rs Wed Feb 20 09:04:54 2019 +0100
+++ b/rust/hg-cpython/src/dirstate.rs Mon Jul 08 18:01:39 2019 +0200
@@ -9,22 +9,21 @@
//! `hg-core` package.
//!
//! From Python, this will be seen as `mercurial.rustext.dirstate`
-
+mod dirs_multiset;
+use crate::dirstate::dirs_multiset::Dirs;
use cpython::{
- exc, ObjectProtocol, PyBytes, PyDict, PyErr, PyInt, PyModule, PyObject,
- PyResult, PySequence, PyTuple, Python, PythonObject, ToPyObject,
+ exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyObject, PyResult,
+ PySequence, PyTuple, Python, PythonObject, ToPyObject,
};
use hg::{
- pack_dirstate, parse_dirstate, CopyVecEntry, DirsIterable, DirsMultiset,
- DirstateEntry, DirstateMapError, DirstatePackError, DirstateParents,
- DirstateParseError, DirstateVec,
+ pack_dirstate, parse_dirstate, CopyVecEntry, DirstateEntry,
+ DirstatePackError, DirstateParents, DirstateParseError, DirstateVec,
};
use libc::{c_char, c_int};
#[cfg(feature = "python27")]
use python27_sys::PyCapsule_Import;
#[cfg(feature = "python3")]
use python3_sys::PyCapsule_Import;
-use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::CStr;
use std::mem::transmute;
@@ -201,97 +200,6 @@
}
}
-py_class!(pub class Dirs |py| {
- data dirs_map: RefCell<DirsMultiset>;
-
- // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes
- // a `list`)
- def __new__(
- _cls,
- map: PyObject,
- skip: Option<PyObject> = None
- ) -> PyResult<Self> {
- let mut skip_state: Option<i8> = None;
- if let Some(skip) = skip {
- skip_state = Some(skip.extract::<PyBytes>(py)?.data(py)[0] as i8);
- }
- let dirs_map;
-
- if let Ok(map) = map.cast_as::<PyDict>(py) {
- let dirstate_vec = extract_dirstate_vec(py, &map)?;
- dirs_map = DirsMultiset::new(
- DirsIterable::Dirstate(dirstate_vec),
- skip_state,
- )
- } else {
- let map: Result<Vec<Vec<u8>>, PyErr> = map
- .iter(py)?
- .map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
- .collect();
- dirs_map = DirsMultiset::new(
- DirsIterable::Manifest(map?),
- skip_state,
- )
- }
-
- Self::create_instance(py, RefCell::new(dirs_map))
- }
-
- def addpath(&self, path: PyObject) -> PyResult<PyObject> {
- self.dirs_map(py).borrow_mut().add_path(
- path.extract::<PyBytes>(py)?.data(py),
- );
- Ok(py.None())
- }
-
- def delpath(&self, path: PyObject) -> PyResult<PyObject> {
- self.dirs_map(py).borrow_mut().delete_path(
- path.extract::<PyBytes>(py)?.data(py),
- )
- .and(Ok(py.None()))
- .or_else(|e| {
- match e {
- DirstateMapError::PathNotFound(_p) => {
- Err(PyErr::new::<exc::ValueError, _>(
- py,
- "expected a value, found none".to_string(),
- ))
- }
- DirstateMapError::EmptyPath => {
- Ok(py.None())
- }
- }
- })
- }
-
- // This is really inefficient on top of being ugly, but it's an easy way
- // of having it work to continue working on the rest of the module
- // hopefully bypassing Python entirely pretty soon.
- def __iter__(&self) -> PyResult<PyObject> {
- let dict = PyDict::new(py);
-
- for (key, value) in self.dirs_map(py).borrow().iter() {
- dict.set_item(
- py,
- PyBytes::new(py, &key[..]),
- value.to_py_object(py),
- )?;
- }
-
- let locals = PyDict::new(py);
- locals.set_item(py, "obj", dict)?;
-
- py.eval("iter(obj)", None, Some(&locals))
- }
-
- def __contains__(&self, item: PyObject) -> PyResult<bool> {
- Ok(self
- .dirs_map(py)
- .borrow()
- .contains_key(item.extract::<PyBytes>(py)?.data(py).as_ref()))
- }
-});
-
/// Create the module, with `__package__` given from parent
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
let dotted_name = &format!("{}.dirstate", package);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-cpython/src/dirstate/dirs_multiset.rs Mon Jul 08 18:01:39 2019 +0200
@@ -0,0 +1,110 @@
+// dirs_multiset.rs
+//
+// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
+//
+// 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::dirstate::dirs_multiset` file provided by the
+//! `hg-core` package.
+
+use std::cell::RefCell;
+
+use cpython::{
+ exc, ObjectProtocol, PyBytes, PyDict, PyErr, PyObject, PyResult,
+ ToPyObject,
+};
+
+use crate::dirstate::extract_dirstate_vec;
+use hg::{DirsIterable, DirsMultiset, DirstateMapError};
+
+py_class!(pub class Dirs |py| {
+ data dirs_map: RefCell<DirsMultiset>;
+
+ // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes
+ // a `list`)
+ def __new__(
+ _cls,
+ map: PyObject,
+ skip: Option<PyObject> = None
+ ) -> PyResult<Self> {
+ let mut skip_state: Option<i8> = None;
+ if let Some(skip) = skip {
+ skip_state = Some(skip.extract::<PyBytes>(py)?.data(py)[0] as i8);
+ }
+ let dirs_map;
+
+ if let Ok(map) = map.cast_as::<PyDict>(py) {
+ let dirstate_vec = extract_dirstate_vec(py, &map)?;
+ dirs_map = DirsMultiset::new(
+ DirsIterable::Dirstate(dirstate_vec),
+ skip_state,
+ )
+ } else {
+ let map: Result<Vec<Vec<u8>>, PyErr> = map
+ .iter(py)?
+ .map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
+ .collect();
+ dirs_map = DirsMultiset::new(
+ DirsIterable::Manifest(map?),
+ skip_state,
+ )
+ }
+
+ Self::create_instance(py, RefCell::new(dirs_map))
+ }
+
+ def addpath(&self, path: PyObject) -> PyResult<PyObject> {
+ self.dirs_map(py).borrow_mut().add_path(
+ path.extract::<PyBytes>(py)?.data(py),
+ );
+ Ok(py.None())
+ }
+
+ def delpath(&self, path: PyObject) -> PyResult<PyObject> {
+ self.dirs_map(py).borrow_mut().delete_path(
+ path.extract::<PyBytes>(py)?.data(py),
+ )
+ .and(Ok(py.None()))
+ .or_else(|e| {
+ match e {
+ DirstateMapError::PathNotFound(_p) => {
+ Err(PyErr::new::<exc::ValueError, _>(
+ py,
+ "expected a value, found none".to_string(),
+ ))
+ }
+ DirstateMapError::EmptyPath => {
+ Ok(py.None())
+ }
+ }
+ })
+ }
+
+ // This is really inefficient on top of being ugly, but it's an easy way
+ // of having it work to continue working on the rest of the module
+ // hopefully bypassing Python entirely pretty soon.
+ def __iter__(&self) -> PyResult<PyObject> {
+ let dict = PyDict::new(py);
+
+ for (key, value) in self.dirs_map(py).borrow().iter() {
+ dict.set_item(
+ py,
+ PyBytes::new(py, &key[..]),
+ value.to_py_object(py),
+ )?;
+ }
+
+ let locals = PyDict::new(py);
+ locals.set_item(py, "obj", dict)?;
+
+ py.eval("iter(obj)", None, Some(&locals))
+ }
+
+ def __contains__(&self, item: PyObject) -> PyResult<bool> {
+ Ok(self
+ .dirs_map(py)
+ .borrow()
+ .contains_key(item.extract::<PyBytes>(py)?.data(py).as_ref()))
+ }
+});