dirs_multiset.rs
129 lines
| 3.9 KiB
| application/rls-services+xml
|
RustLexer
|
r42991 | // 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; | ||||
|
r42997 | use std::convert::TryInto; | ||
|
r42991 | |||
use cpython::{ | ||||
|
r42997 | exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, | ||
Python, | ||||
|
r42991 | }; | ||
|
r43447 | use crate::dirstate::extract_dirstate; | ||
|
r43603 | use crate::ref_sharing::{PyLeaked, PySharedRefCell}; | ||
|
r43157 | use hg::{ | ||
|
r43227 | utils::hg_path::{HgPath, HgPathBuf}, | ||
|
r43157 | DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError, | ||
EntryState, | ||||
}; | ||||
|
r42991 | |||
py_class!(pub class Dirs |py| { | ||||
|
r43115 | data inner: PySharedRefCell<DirsMultiset>; | ||
|
r42991 | |||
// `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> { | ||||
|
r42994 | let mut skip_state: Option<EntryState> = None; | ||
|
r42991 | if let Some(skip) = skip { | ||
|
r42994 | skip_state = Some( | ||
skip.extract::<PyBytes>(py)?.data(py)[0] | ||||
.try_into() | ||||
.map_err(|e: DirstateParseError| { | ||||
PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||||
})?, | ||||
); | ||||
|
r42991 | } | ||
|
r42993 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | ||
let dirstate = extract_dirstate(py, &map)?; | ||||
|
r43070 | DirsMultiset::from_dirstate(&dirstate, skip_state) | ||
|
r42991 | } else { | ||
|
r43227 | let map: Result<Vec<HgPathBuf>, PyErr> = map | ||
|
r42991 | .iter(py)? | ||
|
r43227 | .map(|o| { | ||
Ok(HgPathBuf::from_bytes( | ||||
o?.extract::<PyBytes>(py)?.data(py), | ||||
)) | ||||
}) | ||||
|
r42991 | .collect(); | ||
|
r43070 | DirsMultiset::from_manifest(&map?) | ||
|
r42993 | }; | ||
|
r42991 | |||
|
r42997 | Self::create_instance( | ||
py, | ||||
|
r43115 | PySharedRefCell::new(inner), | ||
|
r42997 | ) | ||
|
r42991 | } | ||
def addpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
|
r43450 | self.inner_shared(py).borrow_mut()?.add_path( | ||
|
r43227 | HgPath::new(path.extract::<PyBytes>(py)?.data(py)), | ||
|
r42991 | ); | ||
Ok(py.None()) | ||||
} | ||||
def delpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
|
r43450 | self.inner_shared(py).borrow_mut()?.delete_path( | ||
|
r43227 | HgPath::new(path.extract::<PyBytes>(py)?.data(py)), | ||
|
r42991 | ) | ||
.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()) | ||||
} | ||||
} | ||||
}) | ||||
} | ||||
|
r42997 | def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { | ||
|
r43611 | let leaked_ref = self.inner_shared(py).leak_immutable(); | ||
|
r43161 | DirsMultisetKeysIterator::from_inner( | ||
|
r42997 | py, | ||
|
r43579 | unsafe { leaked_ref.map(py, |o| o.iter()) }, | ||
|
r42997 | ) | ||
|
r42991 | } | ||
def __contains__(&self, item: PyObject) -> PyResult<bool> { | ||||
|
r43580 | Ok(self.inner_shared(py).borrow().contains(HgPath::new( | ||
|
r43227 | item.extract::<PyBytes>(py)?.data(py).as_ref(), | ||
))) | ||||
|
r42991 | } | ||
}); | ||||
|
r42997 | |||
|
r43448 | py_shared_ref!(Dirs, DirsMultiset, inner, inner_shared); | ||
|
r42997 | |||
impl Dirs { | ||||
pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> { | ||||
|
r43443 | Self::create_instance(py, PySharedRefCell::new(d)) | ||
|
r42997 | } | ||
|
r43227 | fn translate_key( | ||
py: Python, | ||||
res: &HgPathBuf, | ||||
) -> PyResult<Option<PyBytes>> { | ||||
Ok(Some(PyBytes::new(py, res.as_ref()))) | ||||
|
r42997 | } | ||
} | ||||
|
r43159 | py_shared_iterator!( | ||
|
r42997 | DirsMultisetKeysIterator, | ||
|
r43603 | PyLeaked<DirsMultisetIter<'static>>, | ||
|
r42997 | Dirs::translate_key, | ||
Option<PyBytes> | ||||
); | ||||