status.rs
129 lines
| 4.0 KiB
| application/rls-services+xml
|
RustLexer
Raphaël Gomès
|
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
|
r43612 | //! `hg-core` crate. From Python, this will be seen as | ||
//! `rustext.dirstate.status`. | ||||
Raphaël Gomès
|
r43567 | |||
use crate::dirstate::DirstateMap; | ||||
use cpython::exc::ValueError; | ||||
use cpython::{ | ||||
Raphaël Gomès
|
r44368 | ObjectProtocol, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple, | ||
Python, PythonObject, ToPyObject, | ||||
Raphaël Gomès
|
r43567 | }; | ||
Raphaël Gomès
|
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
|
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
|
r44368 | matcher: PyObject, | ||
Raphaël Gomès
|
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
|
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
|
r44367 | |||
Raphaël Gomès
|
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
|
r43567 | |||
Raphaël Gomès
|
r44368 | fn build_response( | ||
lookup: Vec<&HgPath>, | ||||
status_res: StatusResult, | ||||
py: Python, | ||||
) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> { | ||||
Raphaël Gomès
|
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)) | ||||
} | ||||