##// END OF EJS Templates
nodemap: refresh the persistent data on nodemap creation...
nodemap: refresh the persistent data on nodemap creation The logic to read the data and validate the docket are still in python, so we need to "help" whatever compiled code live in the index to refresh it. Otherwise clearing the cache could lead to an expensive full recomputation and disk update even when the persisted data are still valid. Differential Revision: https://phab.mercurial-scm.org/D8174

File last commit:

r44703:bad4e7b3 default
r44988:87b327de default
Show More
dirs_multiset.rs
140 lines | 4.2 KiB | application/rls-services+xml | RustLexer
// 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 std::convert::TryInto;
use cpython::{
exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult,
Python, UnsafePyLeaked,
};
use crate::dirstate::extract_dirstate;
use hg::{
utils::hg_path::{HgPath, HgPathBuf},
DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
EntryState,
};
py_class!(pub class Dirs |py| {
@shared data inner: 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<EntryState> = None;
if let Some(skip) = skip {
skip_state = Some(
skip.extract::<PyBytes>(py)?.data(py)[0]
.try_into()
.map_err(|e: DirstateParseError| {
PyErr::new::<exc::ValueError, _>(py, e.to_string())
})?,
);
}
let inner = if let Ok(map) = map.cast_as::<PyDict>(py) {
let dirstate = extract_dirstate(py, &map)?;
DirsMultiset::from_dirstate(&dirstate, skip_state)
.map_err(|e| {
PyErr::new::<exc::ValueError, _>(py, e.to_string())
})?
} else {
let map: Result<Vec<HgPathBuf>, PyErr> = map
.iter(py)?
.map(|o| {
Ok(HgPathBuf::from_bytes(
o?.extract::<PyBytes>(py)?.data(py),
))
})
.collect();
DirsMultiset::from_manifest(&map?)
.map_err(|e| {
PyErr::new::<exc::ValueError, _>(py, e.to_string())
})?
};
Self::create_instance(py, inner)
}
def addpath(&self, path: PyObject) -> PyResult<PyObject> {
self.inner(py).borrow_mut().add_path(
HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
).and(Ok(py.None())).or_else(|e| {
match e {
DirstateMapError::EmptyPath => {
Ok(py.None())
},
e => {
Err(PyErr::new::<exc::ValueError, _>(
py,
e.to_string(),
))
}
}
})
}
def delpath(&self, path: PyObject) -> PyResult<PyObject> {
self.inner(py).borrow_mut().delete_path(
HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
)
.and(Ok(py.None()))
.or_else(|e| {
match e {
DirstateMapError::EmptyPath => {
Ok(py.None())
},
e => {
Err(PyErr::new::<exc::ValueError, _>(
py,
e.to_string(),
))
}
}
})
}
def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> {
let leaked_ref = self.inner(py).leak_immutable();
DirsMultisetKeysIterator::from_inner(
py,
unsafe { leaked_ref.map(py, |o| o.iter()) },
)
}
def __contains__(&self, item: PyObject) -> PyResult<bool> {
Ok(self.inner(py).borrow().contains(HgPath::new(
item.extract::<PyBytes>(py)?.data(py).as_ref(),
)))
}
});
impl Dirs {
pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> {
Self::create_instance(py, d)
}
fn translate_key(
py: Python,
res: &HgPathBuf,
) -> PyResult<Option<PyBytes>> {
Ok(Some(PyBytes::new(py, res.as_ref())))
}
}
py_shared_iterator!(
DirsMultisetKeysIterator,
UnsafePyLeaked<DirsMultisetIter<'static>>,
Dirs::translate_key,
Option<PyBytes>
);