rust-dirstate-status: update bridge for new rust version of `dirstate.status`
authorRaphaël Gomès <rgomes@octobus.net>
Fri, 29 Nov 2019 17:30:10 +0100
changeset 43922 6a88ced33c40
parent 43921 8c77826116f7
child 43923 40fd1ef4e4c1
rust-dirstate-status: update bridge for new rust version of `dirstate.status` Differential Revision: https://phab.mercurial-scm.org/D7530
rust/hg-core/src/lib.rs
rust/hg-cpython/src/dirstate.rs
rust/hg-cpython/src/dirstate/status.rs
--- a/rust/hg-core/src/lib.rs	Fri Nov 29 17:29:06 2019 +0100
+++ b/rust/hg-core/src/lib.rs	Fri Nov 29 17:30:10 2019 +0100
@@ -12,7 +12,7 @@
     dirs_multiset::{DirsMultiset, DirsMultisetIter},
     dirstate_map::DirstateMap,
     parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
-    status::status,
+    status::{status, StatusResult},
     CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
     StateMap, StateMapIter,
 };
--- a/rust/hg-cpython/src/dirstate.rs	Fri Nov 29 17:29:06 2019 +0100
+++ b/rust/hg-cpython/src/dirstate.rs	Fri Nov 29 17:30:10 2019 +0100
@@ -116,6 +116,7 @@
             status_wrapper(
                 dmap: DirstateMap,
                 root_dir: PyObject,
+                matcher: PyObject,
                 list_clean: bool,
                 last_normal_time: i64,
                 check_exec: bool
--- a/rust/hg-cpython/src/dirstate/status.rs	Fri Nov 29 17:29:06 2019 +0100
+++ b/rust/hg-cpython/src/dirstate/status.rs	Fri Nov 29 17:30:10 2019 +0100
@@ -12,14 +12,17 @@
 use crate::dirstate::DirstateMap;
 use cpython::exc::ValueError;
 use cpython::{
-    PyBytes, PyErr, PyList, PyObject, PyResult, Python, PythonObject,
-    ToPyObject,
+    ObjectProtocol, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple,
+    Python, PythonObject, ToPyObject,
 };
-use hg::utils::files::get_path_from_bytes;
-
-use hg::matchers::AlwaysMatcher;
-use hg::status;
-use hg::utils::hg_path::HgPath;
+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;
 
 /// This will be useless once trait impls for collection are added to `PyBytes`
 /// upstream.
@@ -43,6 +46,7 @@
 pub fn status_wrapper(
     py: Python,
     dmap: DirstateMap,
+    matcher: PyObject,
     root_dir: PyObject,
     list_clean: bool,
     last_normal_time: i64,
@@ -54,20 +58,65 @@
     let dmap: DirstateMap = dmap.to_py_object(py);
     let dmap = dmap.get_inner(py);
 
-    // TODO removed in the next patch to get the code to compile. This patch
-    // is part of a series and does not make real sense on its own.
-    let matcher = AlwaysMatcher;
+    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();
 
-    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()))?;
+            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),
+            ));
+        }
+    }
+}
 
+fn build_response(
+    lookup: Vec<&HgPath>,
+    status_res: StatusResult,
+    py: Python,
+) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
     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());