##// END OF EJS Templates
tests: add test showing crash when shelving ghosted rename target...
tests: add test showing crash when shelving ghosted rename target When you `hg rename` a file and then delete the rename target, `hg shelve` will give you a traceback. Note that the shelve succeeds and the shelve is correct, it's just the update to the parent that fails (i.e. to the parent of the commit that was created for the shelve). This can be squashed into the next commit if the reviewer prefers. Differential Revision: https://phab.mercurial-scm.org/D8045

File last commit:

r44368:6a88ced3 default
r44690:ae4d729e default
Show More
status.rs
129 lines | 4.0 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 // status.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::status` module provided by the
Yuya Nishihara
rust-cpython: run cargo fmt
r43612 //! `hg-core` crate. From Python, this will be seen as
//! `rustext.dirstate.status`.
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567
use crate::dirstate::DirstateMap;
use cpython::exc::ValueError;
use cpython::{
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 ObjectProtocol, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple,
Python, PythonObject, ToPyObject,
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 };
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 use hg::utils::hg_path::HgPathBuf;
use hg::{
matchers::{AlwaysMatcher, FileMatcher},
status,
utils::{files::get_path_from_bytes, hg_path::HgPath},
StatusResult,
};
use std::borrow::Borrow;
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567
/// This will be useless once trait impls for collection are added to `PyBytes`
/// upstream.
fn collect_pybytes_list<P: AsRef<HgPath>>(
py: Python,
collection: &[P],
) -> PyList {
let list = PyList::new(py, &[]);
for (i, path) in collection.iter().enumerate() {
list.insert_item(
py,
i,
PyBytes::new(py, path.as_ref().as_bytes()).into_object(),
)
}
list
}
pub fn status_wrapper(
py: Python,
dmap: DirstateMap,
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 matcher: PyObject,
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 root_dir: PyObject,
list_clean: bool,
last_normal_time: i64,
check_exec: bool,
) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
let bytes = root_dir.extract::<PyBytes>(py)?;
let root_dir = get_path_from_bytes(bytes.data(py));
let dmap: DirstateMap = dmap.to_py_object(py);
let dmap = dmap.get_inner(py);
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 match matcher.get_type(py).name(py).borrow() {
"alwaysmatcher" => {
let matcher = AlwaysMatcher;
let (lookup, status_res) = status(
&dmap,
&matcher,
&root_dir,
list_clean,
last_normal_time,
check_exec,
)
.map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
build_response(lookup, status_res, py)
}
"exactmatcher" => {
let files = matcher.call_method(
py,
"files",
PyTuple::new(py, &[]),
None,
)?;
let files: PyList = files.cast_into(py)?;
let files: PyResult<Vec<HgPathBuf>> = files
.iter(py)
.map(|f| {
Ok(HgPathBuf::from_bytes(
f.extract::<PyBytes>(py)?.data(py),
))
})
.collect();
Raphaël Gomès
rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait...
r44367
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 let files = files?;
let matcher = FileMatcher::new(&files)
.map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
let (lookup, status_res) = status(
&dmap,
&matcher,
&root_dir,
list_clean,
last_normal_time,
check_exec,
)
.map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
build_response(lookup, status_res, py)
}
e => {
return Err(PyErr::new::<ValueError, _>(
py,
format!("Unsupported matcher {}", e),
));
}
}
}
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567
Raphaël Gomès
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
r44368 fn build_response(
lookup: Vec<&HgPath>,
status_res: StatusResult,
py: Python,
) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
let added = collect_pybytes_list(py, status_res.added.as_ref());
let removed = collect_pybytes_list(py, status_res.removed.as_ref());
let deleted = collect_pybytes_list(py, status_res.deleted.as_ref());
let clean = collect_pybytes_list(py, status_res.clean.as_ref());
let lookup = collect_pybytes_list(py, lookup.as_ref());
let unknown = PyList::new(py, &[]);
Ok((lookup, modified, added, removed, deleted, unknown, clean))
}