##// END OF EJS Templates
discovery: replace "heads" by "changesets" in a output note (BC)...
discovery: replace "heads" by "changesets" in a output note (BC) When using `hg push --rev X`, the subset considered by discovery is only `::X`. In addition, `X` can be any local revisions not just local heads. As a result the message "all local heads known locally" can be misleading. We replace it with the more accurate "all local changesets known remotely". The message appears when in verbose not, so this is stricly speaking a BC breakage. I am not sure this would be a real issue in practice...

File last commit:

r43117:64e28b89 default
r43154:775224e2 default
Show More
dirs_multiset.rs
127 lines | 3.8 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,
};
use crate::dirstate::extract_dirstate;
use crate::ref_sharing::{PySharedRefCell, PySharedState};
use hg::{DirsMultiset, DirstateMapError, DirstateParseError, EntryState};
py_class!(pub class Dirs |py| {
data inner: PySharedRefCell<DirsMultiset>;
data py_shared_state: PySharedState;
// `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)
} else {
let map: Result<Vec<Vec<u8>>, PyErr> = map
.iter(py)?
.map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
.collect();
DirsMultiset::from_manifest(&map?)
};
Self::create_instance(
py,
PySharedRefCell::new(inner),
PySharedState::default()
)
}
def addpath(&self, path: PyObject) -> PyResult<PyObject> {
self.borrow_mut(py)?.add_path(
path.extract::<PyBytes>(py)?.data(py),
);
Ok(py.None())
}
def delpath(&self, path: PyObject) -> PyResult<PyObject> {
self.borrow_mut(py)?.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())
}
}
})
}
def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> {
let (leak_handle, leaked_ref) = unsafe { self.leak_immutable(py)? };
DirsMultisetKeysIterator::create_instance(
py,
RefCell::new(Some(leak_handle)),
RefCell::new(Box::new(leaked_ref.iter())),
)
}
def __contains__(&self, item: PyObject) -> PyResult<bool> {
Ok(self
.inner(py)
.borrow()
.contains(item.extract::<PyBytes>(py)?.data(py).as_ref()))
}
});
py_shared_ref!(Dirs, DirsMultiset, inner, DirsMultisetLeakedRef,);
impl Dirs {
pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> {
Self::create_instance(
py,
PySharedRefCell::new(d),
PySharedState::default(),
)
}
fn translate_key(py: Python, res: &Vec<u8>) -> PyResult<Option<PyBytes>> {
Ok(Some(PyBytes::new(py, res)))
}
}
py_shared_sequence_iterator!(
DirsMultisetKeysIterator,
DirsMultisetLeakedRef,
Vec<u8>,
Dirs::translate_key,
Option<PyBytes>
);