dirs_multiset.rs
140 lines
| 4.2 KiB
| application/rls-services+xml
|
RustLexer
Raphaël Gomès
|
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; | ||||
Raphaël Gomès
|
r42997 | use std::convert::TryInto; | ||
Raphaël Gomès
|
r42991 | |||
use cpython::{ | ||||
Raphaël Gomès
|
r42997 | exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, | ||
Yuya Nishihara
|
r44703 | Python, UnsafePyLeaked, | ||
Raphaël Gomès
|
r42991 | }; | ||
Yuya Nishihara
|
r43447 | use crate::dirstate::extract_dirstate; | ||
Yuya Nishihara
|
r43157 | use hg::{ | ||
Simon Sapin
|
r47169 | errors::HgError, | ||
Raphaël Gomès
|
r43227 | utils::hg_path::{HgPath, HgPathBuf}, | ||
Simon Sapin
|
r47169 | DirsMultiset, DirsMultisetIter, DirstateMapError, EntryState, | ||
Yuya Nishihara
|
r43157 | }; | ||
Raphaël Gomès
|
r42991 | |||
py_class!(pub class Dirs |py| { | ||||
Yuya Nishihara
|
r44703 | @shared data inner: DirsMultiset; | ||
Raphaël Gomès
|
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> { | ||||
Raphaël Gomès
|
r42994 | let mut skip_state: Option<EntryState> = None; | ||
Raphaël Gomès
|
r42991 | if let Some(skip) = skip { | ||
Raphaël Gomès
|
r42994 | skip_state = Some( | ||
skip.extract::<PyBytes>(py)?.data(py)[0] | ||||
.try_into() | ||||
Simon Sapin
|
r47169 | .map_err(|e: HgError| { | ||
Raphaël Gomès
|
r42994 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||
})?, | ||||
); | ||||
Raphaël Gomès
|
r42991 | } | ||
Raphaël Gomès
|
r42993 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | ||
let dirstate = extract_dirstate(py, &map)?; | ||||
Yuya Nishihara
|
r43070 | DirsMultiset::from_dirstate(&dirstate, skip_state) | ||
Simon Sapin
|
r47169 | .map_err(|e: DirstateMapError| { | ||
Raphaël Gomès
|
r44315 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||
})? | ||||
Raphaël Gomès
|
r42991 | } else { | ||
Raphaël Gomès
|
r43227 | let map: Result<Vec<HgPathBuf>, PyErr> = map | ||
Raphaël Gomès
|
r42991 | .iter(py)? | ||
Raphaël Gomès
|
r43227 | .map(|o| { | ||
Ok(HgPathBuf::from_bytes( | ||||
o?.extract::<PyBytes>(py)?.data(py), | ||||
)) | ||||
}) | ||||
Raphaël Gomès
|
r42991 | .collect(); | ||
Yuya Nishihara
|
r43070 | DirsMultiset::from_manifest(&map?) | ||
Raphaël Gomès
|
r44315 | .map_err(|e| { | ||
PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||||
})? | ||||
Raphaël Gomès
|
r42993 | }; | ||
Raphaël Gomès
|
r42991 | |||
Yuya Nishihara
|
r44703 | Self::create_instance(py, inner) | ||
Raphaël Gomès
|
r42991 | } | ||
def addpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
Yuya Nishihara
|
r44702 | self.inner(py).borrow_mut().add_path( | ||
Raphaël Gomès
|
r43227 | HgPath::new(path.extract::<PyBytes>(py)?.data(py)), | ||
Raphaël Gomès
|
r44227 | ).and(Ok(py.None())).or_else(|e| { | ||
match e { | ||||
DirstateMapError::EmptyPath => { | ||||
Ok(py.None()) | ||||
}, | ||||
e => { | ||||
Err(PyErr::new::<exc::ValueError, _>( | ||||
py, | ||||
e.to_string(), | ||||
)) | ||||
} | ||||
} | ||||
}) | ||||
Raphaël Gomès
|
r42991 | } | ||
def delpath(&self, path: PyObject) -> PyResult<PyObject> { | ||||
Yuya Nishihara
|
r44702 | self.inner(py).borrow_mut().delete_path( | ||
Raphaël Gomès
|
r43227 | HgPath::new(path.extract::<PyBytes>(py)?.data(py)), | ||
Raphaël Gomès
|
r42991 | ) | ||
.and(Ok(py.None())) | ||||
.or_else(|e| { | ||||
match e { | ||||
Raphaël Gomès
|
r44227 | DirstateMapError::EmptyPath => { | ||
Ok(py.None()) | ||||
}, | ||||
e => { | ||||
Raphaël Gomès
|
r42991 | Err(PyErr::new::<exc::ValueError, _>( | ||
py, | ||||
Raphaël Gomès
|
r44227 | e.to_string(), | ||
Raphaël Gomès
|
r42991 | )) | ||
} | ||||
} | ||||
}) | ||||
} | ||||
Raphaël Gomès
|
r42997 | def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> { | ||
Yuya Nishihara
|
r44702 | let leaked_ref = self.inner(py).leak_immutable(); | ||
Yuya Nishihara
|
r43161 | DirsMultisetKeysIterator::from_inner( | ||
Raphaël Gomès
|
r42997 | py, | ||
Yuya Nishihara
|
r43579 | unsafe { leaked_ref.map(py, |o| o.iter()) }, | ||
Raphaël Gomès
|
r42997 | ) | ||
Raphaël Gomès
|
r42991 | } | ||
def __contains__(&self, item: PyObject) -> PyResult<bool> { | ||||
Yuya Nishihara
|
r44702 | Ok(self.inner(py).borrow().contains(HgPath::new( | ||
Raphaël Gomès
|
r43227 | item.extract::<PyBytes>(py)?.data(py).as_ref(), | ||
))) | ||||
Raphaël Gomès
|
r42991 | } | ||
}); | ||||
Raphaël Gomès
|
r42997 | |||
impl Dirs { | ||||
pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> { | ||||
Yuya Nishihara
|
r44703 | Self::create_instance(py, d) | ||
Raphaël Gomès
|
r42997 | } | ||
Raphaël Gomès
|
r43227 | fn translate_key( | ||
py: Python, | ||||
res: &HgPathBuf, | ||||
) -> PyResult<Option<PyBytes>> { | ||||
Raphaël Gomès
|
r45500 | Ok(Some(PyBytes::new(py, res.as_bytes()))) | ||
Raphaël Gomès
|
r42997 | } | ||
} | ||||
Yuya Nishihara
|
r43159 | py_shared_iterator!( | ||
Raphaël Gomès
|
r42997 | DirsMultisetKeysIterator, | ||
Yuya Nishihara
|
r44703 | UnsafePyLeaked<DirsMultisetIter<'static>>, | ||
Raphaël Gomès
|
r42997 | Dirs::translate_key, | ||
Option<PyBytes> | ||||
); | ||||