Mercurial > hg
view rust/hg-cpython/src/dirstate/dirs_multiset.rs @ 42746:b3518b0baa47
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
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 08 Jul 2019 18:01:39 +0200 |
parents | rust/hg-cpython/src/dirstate.rs@326fdce22fb2 |
children | 7cae6bc29ff9 |
line wrap: on
line source
// 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())) } });