rust/hg-cpython/src/dirstate/status.rs
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Fri, 05 Apr 2024 17:57:26 +0100
changeset 51603 a2afa35641c9
parent 51602 68929cf3c0c6
child 51604 32ba01b5669d
permissions -rw-r--r--
matchers: support patternmatcher in rust
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
// status.rs
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
//
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
// Copyright 2019, Raphaël Gomès <rgomes@octobus.net>
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
//
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
//! Bindings for the `hg::status` module provided by the
43431
21a1b2094649 rust-cpython: run cargo fmt
Yuya Nishihara <yuya@tcha.org>
parents: 43273
diff changeset
     9
//! `hg-core` crate. From Python, this will be seen as
21a1b2094649 rust-cpython: run cargo fmt
Yuya Nishihara <yuya@tcha.org>
parents: 43273
diff changeset
    10
//! `rustext.dirstate.status`.
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    12
use crate::{dirstate::DirstateMap, exceptions::FallbackError};
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    13
use cpython::{
51602
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
    14
    exc::ValueError, ObjectProtocol, PyBool, PyBytes, PyErr, PyList, PyObject,
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    15
    PyResult, PyTuple, Python, PythonObject, ToPyObject,
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    16
};
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    17
use hg::dirstate::status::StatusPath;
49479
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
    18
use hg::matchers::{
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
    19
    DifferenceMatcher, IntersectionMatcher, Matcher, NeverMatcher,
51603
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
    20
    PatternMatcher, UnionMatcher,
49479
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
    21
};
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
    22
use hg::{
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    23
    matchers::{AlwaysMatcher, FileMatcher, IncludeMatcher},
47093
787ff5d21bcd dirstate-tree: Make Rust DirstateMap bindings go through a trait object
Simon Sapin <simon.sapin@octobus.net>
parents: 45861
diff changeset
    24
    parse_pattern_syntax,
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    25
    utils::{
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    26
        files::{get_bytes_from_path, get_path_from_bytes},
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    27
        hg_path::{HgPath, HgPathBuf},
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    28
    },
51602
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
    29
    BadMatch, DirstateStatus, IgnorePattern, PatternError, PatternFileWarning,
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
    30
    StatusError, StatusOptions,
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
    31
};
47110
9c6b458a08e1 rust: Move "lookup" a.k.a. "unsure" paths into `DirstateStatus` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47093
diff changeset
    32
use std::borrow::Borrow;
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    34
fn collect_status_path_list(py: Python, paths: &[StatusPath<'_>]) -> PyList {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    35
    collect_pybytes_list(py, paths.iter().map(|item| &*item.path))
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    36
}
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    37
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
/// This will be useless once trait impls for collection are added to `PyBytes`
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
/// upstream.
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    40
fn collect_pybytes_list(
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    41
    py: Python,
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    42
    iter: impl Iterator<Item = impl AsRef<HgPath>>,
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    43
) -> PyList {
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    44
    let list = PyList::new(py, &[]);
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    45
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
    46
    for path in iter {
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    47
        list.append(
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    48
            py,
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    49
            PyBytes::new(py, path.as_ref().as_bytes()).into_object(),
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    50
        )
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
    }
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
    list
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
}
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    56
fn collect_bad_matches(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    57
    py: Python,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    58
    collection: &[(impl AsRef<HgPath>, BadMatch)],
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    59
) -> PyResult<PyList> {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    60
    let list = PyList::new(py, &[]);
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    61
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    62
    let os = py.import("os")?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    63
    let get_error_message = |code: i32| -> PyResult<_> {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    64
        os.call(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    65
            py,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    66
            "strerror",
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    67
            PyTuple::new(py, &[code.to_py_object(py).into_object()]),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    68
            None,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    69
        )
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    70
    };
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    71
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    72
    for (path, bad_match) in collection.iter() {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    73
        let message = match bad_match {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    74
            BadMatch::OsError(code) => get_error_message(*code)?,
49914
58074252db3c rust: run `cargo clippy`
Raphaël Gomès <rgomes@octobus.net>
parents: 49479
diff changeset
    75
            BadMatch::BadType(bad_type) => {
58074252db3c rust: run `cargo clippy`
Raphaël Gomès <rgomes@octobus.net>
parents: 49479
diff changeset
    76
                format!("unsupported file type (type is {})", bad_type)
58074252db3c rust: run `cargo clippy`
Raphaël Gomès <rgomes@octobus.net>
parents: 49479
diff changeset
    77
                    .to_py_object(py)
58074252db3c rust: run `cargo clippy`
Raphaël Gomès <rgomes@octobus.net>
parents: 49479
diff changeset
    78
                    .into_object()
58074252db3c rust: run `cargo clippy`
Raphaël Gomès <rgomes@octobus.net>
parents: 49479
diff changeset
    79
            }
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    80
        };
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    81
        list.append(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    82
            py,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    83
            (PyBytes::new(py, path.as_ref().as_bytes()), message)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    84
                .to_py_object(py)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    85
                .into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    86
        )
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    87
    }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    88
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    89
    Ok(list)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    90
}
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    91
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    92
fn handle_fallback(py: Python, err: StatusError) -> PyErr {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    93
    match err {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    94
        StatusError::Pattern(e) => {
44572
245aec57d76a rust-status: add trace-level logging for Rust status fallback for debugging
Raphaël Gomès <rgomes@octobus.net>
parents: 44529
diff changeset
    95
            let as_string = e.to_string();
245aec57d76a rust-status: add trace-level logging for Rust status fallback for debugging
Raphaël Gomès <rgomes@octobus.net>
parents: 44529
diff changeset
    96
            log::trace!("Rust status fallback: `{}`", &as_string);
245aec57d76a rust-status: add trace-level logging for Rust status fallback for debugging
Raphaël Gomès <rgomes@octobus.net>
parents: 44529
diff changeset
    97
245aec57d76a rust-status: add trace-level logging for Rust status fallback for debugging
Raphaël Gomès <rgomes@octobus.net>
parents: 44529
diff changeset
    98
            PyErr::new::<FallbackError, _>(py, &as_string)
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
    99
        }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   100
        e => PyErr::new::<ValueError, _>(py, e.to_string()),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   101
    }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   102
}
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   103
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   104
pub fn status_wrapper(
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   105
    py: Python,
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   106
    dmap: DirstateMap,
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   107
    matcher: PyObject,
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   108
    root_dir: PyObject,
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   109
    ignore_files: PyList,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   110
    check_exec: bool,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   111
    list_clean: bool,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   112
    list_ignored: bool,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   113
    list_unknown: bool,
44839
01afda7e7d6c rust-hg-cpython: update status bridge with the new `traversedir` support
Raphaël Gomès <rgomes@octobus.net>
parents: 44597
diff changeset
   114
    collect_traversed_dirs: bool,
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   115
) -> PyResult<PyTuple> {
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   116
    let bytes = root_dir.extract::<PyBytes>(py)?;
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   117
    let root_dir = get_path_from_bytes(bytes.data(py));
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   118
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   119
    let dmap: DirstateMap = dmap.to_py_object(py);
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents: 47110
diff changeset
   120
    let mut dmap = dmap.get_inner_mut(py);
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   121
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   122
    let ignore_files: PyResult<Vec<_>> = ignore_files
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   123
        .iter(py)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   124
        .map(|b| {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   125
            let file = b.extract::<PyBytes>(py)?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   126
            Ok(get_path_from_bytes(file.data(py)).to_owned())
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   127
        })
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   128
        .collect();
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   129
    let ignore_files = ignore_files?;
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   130
    // The caller may call `copymap.items()` separately
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   131
    let list_copies = false;
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   132
49000
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   133
    let after_status = |res: Result<(DirstateStatus<'_>, _), StatusError>| {
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   134
        let (status_res, warnings) =
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   135
            res.map_err(|e| handle_fallback(py, e))?;
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   136
        build_response(py, status_res, warnings)
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   137
    };
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48744
diff changeset
   138
49347
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   139
    let matcher = extract_matcher(py, matcher)?;
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   140
    dmap.with_status(
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   141
        &*matcher,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   142
        root_dir.to_path_buf(),
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   143
        ignore_files,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   144
        StatusOptions {
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   145
            check_exec,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   146
            list_clean,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   147
            list_ignored,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   148
            list_unknown,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   149
            list_copies,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   150
            collect_traversed_dirs,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   151
        },
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   152
        after_status,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   153
    )
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   154
}
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   155
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   156
/// Transform a Python matcher into a Rust matcher.
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   157
fn extract_matcher(
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   158
    py: Python,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   159
    matcher: PyObject,
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   160
) -> PyResult<Box<dyn Matcher + Sync>> {
51602
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   161
    let tampered = matcher
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   162
        .call_method(py, "was_tampered_with", PyTuple::empty(py), None)?
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   163
        .extract::<PyBool>(py)?
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   164
        .is_true();
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   165
    if tampered {
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   166
        return Err(handle_fallback(
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   167
            py,
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   168
            StatusError::Pattern(PatternError::UnsupportedSyntax(
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   169
                "Pattern matcher was tampered with!".to_string(),
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   170
            )),
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   171
        ));
68929cf3c0c6 match: avoid rust fast path if the matcher was tampered with
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51120
diff changeset
   172
    };
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   173
    match matcher.get_type(py).name(py).borrow() {
49347
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   174
        "alwaysmatcher" => Ok(Box::new(AlwaysMatcher)),
49352
97dcd6906e6f rust-dirstate: add support for nevermatcher
Raphaël Gomès <rgomes@octobus.net>
parents: 49351
diff changeset
   175
        "nevermatcher" => Ok(Box::new(NeverMatcher)),
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   176
        "exactmatcher" => {
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   177
            let files = matcher.call_method(
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   178
                py,
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   179
                "files",
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   180
                PyTuple::new(py, &[]),
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   181
                None,
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   182
            )?;
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   183
            let files: PyList = files.cast_into(py)?;
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   184
            let files: PyResult<Vec<HgPathBuf>> = files
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   185
                .iter(py)
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   186
                .map(|f| {
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   187
                    Ok(HgPathBuf::from_bytes(
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   188
                        f.extract::<PyBytes>(py)?.data(py),
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   189
                    ))
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   190
                })
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   191
                .collect();
43915
8c77826116f7 rust-dirstate-status: add `walk_explicit` implementation, use `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43818
diff changeset
   192
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   193
            let files = files?;
49347
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   194
            let file_matcher = FileMatcher::new(files)
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   195
                .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
49347
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   196
            Ok(Box::new(file_matcher))
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   197
        }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   198
        "includematcher" => {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   199
            // Get the patterns from Python even though most of them are
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   200
            // redundant with those we will parse later on, as they include
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   201
            // those passed from the command line.
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   202
            let ignore_patterns: PyResult<Vec<_>> = matcher
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   203
                .getattr(py, "_kindpats")?
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   204
                .iter(py)?
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   205
                .map(|k| {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   206
                    let k = k?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   207
                    let syntax = parse_pattern_syntax(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   208
                        &[
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   209
                            k.get_item(py, 0)?
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   210
                                .extract::<PyBytes>(py)?
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   211
                                .data(py),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   212
                            &b":"[..],
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   213
                        ]
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   214
                        .concat(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   215
                    )
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   216
                    .map_err(|e| {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   217
                        handle_fallback(py, StatusError::Pattern(e))
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   218
                    })?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   219
                    let pattern = k.get_item(py, 1)?.extract::<PyBytes>(py)?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   220
                    let pattern = pattern.data(py);
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   221
                    let source = k.get_item(py, 2)?.extract::<PyBytes>(py)?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   222
                    let source = get_path_from_bytes(source.data(py));
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   223
                    let new = IgnorePattern::new(syntax, pattern, source);
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   224
                    Ok(new)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   225
                })
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   226
                .collect();
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   227
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   228
            let ignore_patterns = ignore_patterns?;
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   229
47379
f6bb181c75f8 rust: Parse "subinclude"d files along the way, not later
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
   230
            let matcher = IncludeMatcher::new(ignore_patterns)
f6bb181c75f8 rust: Parse "subinclude"d files along the way, not later
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
   231
                .map_err(|e| handle_fallback(py, e.into()))?;
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   232
49347
75119bbee3d1 hg-cpython: refactor matcher transformation logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49346
diff changeset
   233
            Ok(Box::new(matcher))
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   234
        }
49349
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   235
        "unionmatcher" => {
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   236
            let matchers: PyResult<Vec<_>> = matcher
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   237
                .getattr(py, "_matchers")?
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   238
                .iter(py)?
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   239
                .map(|py_matcher| extract_matcher(py, py_matcher?))
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   240
                .collect();
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   241
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   242
            Ok(Box::new(UnionMatcher::new(matchers?)))
0043c7aa3250 rust-dirstate: add `unionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49347
diff changeset
   243
        }
49351
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   244
        "intersectionmatcher" => {
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   245
            let m1 = extract_matcher(py, matcher.getattr(py, "_m1")?)?;
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   246
            let m2 = extract_matcher(py, matcher.getattr(py, "_m2")?)?;
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   247
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   248
            Ok(Box::new(IntersectionMatcher::new(m1, m2)))
0b00998e336a rust-dirstate: add `intersectionmatcher` to the allowed matchers
Raphaël Gomès <rgomes@octobus.net>
parents: 49349
diff changeset
   249
        }
49479
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   250
        "differencematcher" => {
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   251
            let m1 = extract_matcher(py, matcher.getattr(py, "_m1")?)?;
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   252
            let m2 = extract_matcher(py, matcher.getattr(py, "_m2")?)?;
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   253
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   254
            Ok(Box::new(DifferenceMatcher::new(m1, m2)))
6193e846cb65 rust-status: expose DifferenceMatcher from Rust to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 49352
diff changeset
   255
        }
51603
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   256
        "patternmatcher" => {
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   257
            let ignore_patterns = matcher
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   258
                .getattr(py, "_kindpats")?
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   259
                .iter(py)?
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   260
                .map(|k| {
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   261
                    let k = k?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   262
                    let syntax = parse_pattern_syntax(
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   263
                        &[
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   264
                            k.get_item(py, 0)?
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   265
                                .extract::<PyBytes>(py)?
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   266
                                .data(py),
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   267
                            &b":"[..],
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   268
                        ]
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   269
                        .concat(),
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   270
                    )
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   271
                    .map_err(|e| {
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   272
                        handle_fallback(py, StatusError::Pattern(e))
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   273
                    })?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   274
                    let pattern = k.get_item(py, 1)?.extract::<PyBytes>(py)?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   275
                    let pattern = pattern.data(py);
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   276
                    let source = k.get_item(py, 2)?.extract::<PyBytes>(py)?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   277
                    let source = get_path_from_bytes(source.data(py));
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   278
                    let new = IgnorePattern::new(syntax, pattern, source);
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   279
                    Ok(new)
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   280
                })
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   281
                .collect::<PyResult<Vec<_>>>()?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   282
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   283
            let matcher = PatternMatcher::new(ignore_patterns)
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   284
                .map_err(|e| handle_fallback(py, e.into()))?;
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   285
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   286
            Ok(Box::new(matcher))
a2afa35641c9 matchers: support patternmatcher in rust
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51602
diff changeset
   287
        }
49345
44319aa4a2a4 hg-cpython: fallback when encountering an unknown matcher
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
   288
        e => Err(PyErr::new::<FallbackError, _>(
44973
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44839
diff changeset
   289
            py,
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44839
diff changeset
   290
            format!("Unsupported matcher {}", e),
26114bd6ec60 rust: do a clippy pass
Raphaël Gomès <rgomes@octobus.net>
parents: 44839
diff changeset
   291
        )),
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   292
    }
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   293
}
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   294
43916
6a88ced33c40 rust-dirstate-status: update bridge for new rust version of `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents: 43915
diff changeset
   295
fn build_response(
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   296
    py: Python,
44525
f13d19549efd rust-status: rename `StatusResult` to `DirstateStatus`
Raphaël Gomès <rgomes@octobus.net>
parents: 44232
diff changeset
   297
    status_res: DirstateStatus,
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   298
    warnings: Vec<PatternFileWarning>,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   299
) -> PyResult<PyTuple> {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   300
    let modified = collect_status_path_list(py, &status_res.modified);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   301
    let added = collect_status_path_list(py, &status_res.added);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   302
    let removed = collect_status_path_list(py, &status_res.removed);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   303
    let deleted = collect_status_path_list(py, &status_res.deleted);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   304
    let clean = collect_status_path_list(py, &status_res.clean);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   305
    let ignored = collect_status_path_list(py, &status_res.ignored);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   306
    let unknown = collect_status_path_list(py, &status_res.unknown);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   307
    let unsure = collect_status_path_list(py, &status_res.unsure);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   308
    let bad = collect_bad_matches(py, &status_res.bad)?;
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
   309
    let traversed = collect_pybytes_list(py, status_res.traversed.iter());
47350
04d1f17f49e7 dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   310
    let dirty = status_res.dirty.to_py_object(py);
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   311
    let py_warnings = PyList::new(py, &[]);
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   312
    for warning in warnings.iter() {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   313
        // We use duck-typing on the Python side for dispatch, good enough for
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   314
        // now.
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   315
        match warning {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   316
            PatternFileWarning::InvalidSyntax(file, syn) => {
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   317
                py_warnings.append(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   318
                    py,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   319
                    (
51120
532e74ad3ff6 rust: run a clippy pass with the latest stable version
Raphaël Gomès <rgomes@octobus.net>
parents: 49914
diff changeset
   320
                        PyBytes::new(py, &get_bytes_from_path(file)),
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   321
                        PyBytes::new(py, syn),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   322
                    )
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   323
                        .to_py_object(py)
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   324
                        .into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   325
                );
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   326
            }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   327
            PatternFileWarning::NoSuchFile(file) => py_warnings.append(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   328
                py,
51120
532e74ad3ff6 rust: run a clippy pass with the latest stable version
Raphaël Gomès <rgomes@octobus.net>
parents: 49914
diff changeset
   329
                PyBytes::new(py, &get_bytes_from_path(file)).into_object(),
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   330
            ),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   331
        }
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   332
    }
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   333
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   334
    Ok(PyTuple::new(
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   335
        py,
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   336
        &[
47110
9c6b458a08e1 rust: Move "lookup" a.k.a. "unsure" paths into `DirstateStatus` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47093
diff changeset
   337
            unsure.into_object(),
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   338
            modified.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   339
            added.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   340
            removed.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   341
            deleted.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   342
            clean.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   343
            ignored.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   344
            unknown.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   345
            py_warnings.into_object(),
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   346
            bad.into_object(),
44839
01afda7e7d6c rust-hg-cpython: update status bridge with the new `traversedir` support
Raphaël Gomès <rgomes@octobus.net>
parents: 44597
diff changeset
   347
            traversed.into_object(),
47350
04d1f17f49e7 dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
   348
            dirty.into_object(),
44529
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   349
        ][..],
f96b28aa4b79 rust-status: update rust-cpython bridge to account for the changes in core
Raphaël Gomès <rgomes@octobus.net>
parents: 44525
diff changeset
   350
    ))
43273
478d0b1bf0c5 rust-dirstate-status: rust-cpython bindings for `dirstate.status`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   351
}