##// END OF EJS Templates
rust-dirstate-status: update bridge for new rust version of `dirstate.status`...
Raphaël Gomès -
r44368:6a88ced3 default
parent child Browse files
Show More
@@ -1,173 +1,173 b''
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
2 //
2 //
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5 mod ancestors;
5 mod ancestors;
6 pub mod dagops;
6 pub mod dagops;
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
8 mod dirstate;
8 mod dirstate;
9 pub mod discovery;
9 pub mod discovery;
10 pub mod testing; // unconditionally built, for use from integration tests
10 pub mod testing; // unconditionally built, for use from integration tests
11 pub use dirstate::{
11 pub use dirstate::{
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
13 dirstate_map::DirstateMap,
13 dirstate_map::DirstateMap,
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
15 status::status,
15 status::{status, StatusResult},
16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
17 StateMap, StateMapIter,
17 StateMap, StateMapIter,
18 };
18 };
19 mod filepatterns;
19 mod filepatterns;
20 pub mod matchers;
20 pub mod matchers;
21 pub mod utils;
21 pub mod utils;
22
22
23 use crate::utils::hg_path::HgPathBuf;
23 use crate::utils::hg_path::HgPathBuf;
24 pub use filepatterns::{
24 pub use filepatterns::{
25 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
25 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
26 };
26 };
27 use std::collections::HashMap;
27 use std::collections::HashMap;
28 use twox_hash::RandomXxHashBuilder64;
28 use twox_hash::RandomXxHashBuilder64;
29
29
30 /// Mercurial revision numbers
30 /// Mercurial revision numbers
31 ///
31 ///
32 /// As noted in revlog.c, revision numbers are actually encoded in
32 /// As noted in revlog.c, revision numbers are actually encoded in
33 /// 4 bytes, and are liberally converted to ints, whence the i32
33 /// 4 bytes, and are liberally converted to ints, whence the i32
34 pub type Revision = i32;
34 pub type Revision = i32;
35
35
36 /// Marker expressing the absence of a parent
36 /// Marker expressing the absence of a parent
37 ///
37 ///
38 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
38 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
39 /// to be smaller that all existing revisions.
39 /// to be smaller that all existing revisions.
40 pub const NULL_REVISION: Revision = -1;
40 pub const NULL_REVISION: Revision = -1;
41
41
42 /// Same as `mercurial.node.wdirrev`
42 /// Same as `mercurial.node.wdirrev`
43 ///
43 ///
44 /// This is also equal to `i32::max_value()`, but it's better to spell
44 /// This is also equal to `i32::max_value()`, but it's better to spell
45 /// it out explicitely, same as in `mercurial.node`
45 /// it out explicitely, same as in `mercurial.node`
46 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
46 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
47
47
48 /// The simplest expression of what we need of Mercurial DAGs.
48 /// The simplest expression of what we need of Mercurial DAGs.
49 pub trait Graph {
49 pub trait Graph {
50 /// Return the two parents of the given `Revision`.
50 /// Return the two parents of the given `Revision`.
51 ///
51 ///
52 /// Each of the parents can be independently `NULL_REVISION`
52 /// Each of the parents can be independently `NULL_REVISION`
53 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
53 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
54 }
54 }
55
55
56 pub type LineNumber = usize;
56 pub type LineNumber = usize;
57
57
58 /// Rust's default hasher is too slow because it tries to prevent collision
58 /// Rust's default hasher is too slow because it tries to prevent collision
59 /// attacks. We are not concerned about those: if an ill-minded person has
59 /// attacks. We are not concerned about those: if an ill-minded person has
60 /// write access to your repository, you have other issues.
60 /// write access to your repository, you have other issues.
61 pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>;
61 pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>;
62
62
63 #[derive(Clone, Debug, PartialEq)]
63 #[derive(Clone, Debug, PartialEq)]
64 pub enum GraphError {
64 pub enum GraphError {
65 ParentOutOfRange(Revision),
65 ParentOutOfRange(Revision),
66 WorkingDirectoryUnsupported,
66 WorkingDirectoryUnsupported,
67 }
67 }
68
68
69 #[derive(Clone, Debug, PartialEq)]
69 #[derive(Clone, Debug, PartialEq)]
70 pub enum DirstateParseError {
70 pub enum DirstateParseError {
71 TooLittleData,
71 TooLittleData,
72 Overflow,
72 Overflow,
73 CorruptedEntry(String),
73 CorruptedEntry(String),
74 Damaged,
74 Damaged,
75 }
75 }
76
76
77 impl From<std::io::Error> for DirstateParseError {
77 impl From<std::io::Error> for DirstateParseError {
78 fn from(e: std::io::Error) -> Self {
78 fn from(e: std::io::Error) -> Self {
79 DirstateParseError::CorruptedEntry(e.to_string())
79 DirstateParseError::CorruptedEntry(e.to_string())
80 }
80 }
81 }
81 }
82
82
83 impl ToString for DirstateParseError {
83 impl ToString for DirstateParseError {
84 fn to_string(&self) -> String {
84 fn to_string(&self) -> String {
85 use crate::DirstateParseError::*;
85 use crate::DirstateParseError::*;
86 match self {
86 match self {
87 TooLittleData => "Too little data for dirstate.".to_string(),
87 TooLittleData => "Too little data for dirstate.".to_string(),
88 Overflow => "Overflow in dirstate.".to_string(),
88 Overflow => "Overflow in dirstate.".to_string(),
89 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
89 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
90 Damaged => "Dirstate appears to be damaged.".to_string(),
90 Damaged => "Dirstate appears to be damaged.".to_string(),
91 }
91 }
92 }
92 }
93 }
93 }
94
94
95 #[derive(Debug, PartialEq)]
95 #[derive(Debug, PartialEq)]
96 pub enum DirstatePackError {
96 pub enum DirstatePackError {
97 CorruptedEntry(String),
97 CorruptedEntry(String),
98 CorruptedParent,
98 CorruptedParent,
99 BadSize(usize, usize),
99 BadSize(usize, usize),
100 }
100 }
101
101
102 impl From<std::io::Error> for DirstatePackError {
102 impl From<std::io::Error> for DirstatePackError {
103 fn from(e: std::io::Error) -> Self {
103 fn from(e: std::io::Error) -> Self {
104 DirstatePackError::CorruptedEntry(e.to_string())
104 DirstatePackError::CorruptedEntry(e.to_string())
105 }
105 }
106 }
106 }
107 #[derive(Debug, PartialEq)]
107 #[derive(Debug, PartialEq)]
108 pub enum DirstateMapError {
108 pub enum DirstateMapError {
109 PathNotFound(HgPathBuf),
109 PathNotFound(HgPathBuf),
110 EmptyPath,
110 EmptyPath,
111 ConsecutiveSlashes,
111 ConsecutiveSlashes,
112 }
112 }
113
113
114 impl ToString for DirstateMapError {
114 impl ToString for DirstateMapError {
115 fn to_string(&self) -> String {
115 fn to_string(&self) -> String {
116 use crate::DirstateMapError::*;
116 use crate::DirstateMapError::*;
117 match self {
117 match self {
118 PathNotFound(_) => "expected a value, found none".to_string(),
118 PathNotFound(_) => "expected a value, found none".to_string(),
119 EmptyPath => "Overflow in dirstate.".to_string(),
119 EmptyPath => "Overflow in dirstate.".to_string(),
120 ConsecutiveSlashes => {
120 ConsecutiveSlashes => {
121 "found invalid consecutive slashes in path".to_string()
121 "found invalid consecutive slashes in path".to_string()
122 }
122 }
123 }
123 }
124 }
124 }
125 }
125 }
126
126
127 pub enum DirstateError {
127 pub enum DirstateError {
128 Parse(DirstateParseError),
128 Parse(DirstateParseError),
129 Pack(DirstatePackError),
129 Pack(DirstatePackError),
130 Map(DirstateMapError),
130 Map(DirstateMapError),
131 IO(std::io::Error),
131 IO(std::io::Error),
132 }
132 }
133
133
134 impl From<DirstateParseError> for DirstateError {
134 impl From<DirstateParseError> for DirstateError {
135 fn from(e: DirstateParseError) -> Self {
135 fn from(e: DirstateParseError) -> Self {
136 DirstateError::Parse(e)
136 DirstateError::Parse(e)
137 }
137 }
138 }
138 }
139
139
140 impl From<DirstatePackError> for DirstateError {
140 impl From<DirstatePackError> for DirstateError {
141 fn from(e: DirstatePackError) -> Self {
141 fn from(e: DirstatePackError) -> Self {
142 DirstateError::Pack(e)
142 DirstateError::Pack(e)
143 }
143 }
144 }
144 }
145
145
146 #[derive(Debug)]
146 #[derive(Debug)]
147 pub enum PatternError {
147 pub enum PatternError {
148 UnsupportedSyntax(String),
148 UnsupportedSyntax(String),
149 }
149 }
150
150
151 #[derive(Debug)]
151 #[derive(Debug)]
152 pub enum PatternFileError {
152 pub enum PatternFileError {
153 IO(std::io::Error),
153 IO(std::io::Error),
154 Pattern(PatternError, LineNumber),
154 Pattern(PatternError, LineNumber),
155 }
155 }
156
156
157 impl From<std::io::Error> for PatternFileError {
157 impl From<std::io::Error> for PatternFileError {
158 fn from(e: std::io::Error) -> Self {
158 fn from(e: std::io::Error) -> Self {
159 PatternFileError::IO(e)
159 PatternFileError::IO(e)
160 }
160 }
161 }
161 }
162
162
163 impl From<DirstateMapError> for DirstateError {
163 impl From<DirstateMapError> for DirstateError {
164 fn from(e: DirstateMapError) -> Self {
164 fn from(e: DirstateMapError) -> Self {
165 DirstateError::Map(e)
165 DirstateError::Map(e)
166 }
166 }
167 }
167 }
168
168
169 impl From<std::io::Error> for DirstateError {
169 impl From<std::io::Error> for DirstateError {
170 fn from(e: std::io::Error) -> Self {
170 fn from(e: std::io::Error) -> Self {
171 DirstateError::IO(e)
171 DirstateError::IO(e)
172 }
172 }
173 }
173 }
@@ -1,131 +1,132 b''
1 // dirstate.rs
1 // dirstate.rs
2 //
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Bindings for the `hg::dirstate` module provided by the
8 //! Bindings for the `hg::dirstate` module provided by the
9 //! `hg-core` package.
9 //! `hg-core` package.
10 //!
10 //!
11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
12 mod copymap;
12 mod copymap;
13 mod dirs_multiset;
13 mod dirs_multiset;
14 mod dirstate_map;
14 mod dirstate_map;
15 mod status;
15 mod status;
16 use crate::dirstate::{
16 use crate::dirstate::{
17 dirs_multiset::Dirs, dirstate_map::DirstateMap, status::status_wrapper,
17 dirs_multiset::Dirs, dirstate_map::DirstateMap, status::status_wrapper,
18 };
18 };
19 use cpython::{
19 use cpython::{
20 exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
20 exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
21 Python,
21 Python,
22 };
22 };
23 use hg::{
23 use hg::{
24 utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState,
24 utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState,
25 StateMap,
25 StateMap,
26 };
26 };
27 use libc::{c_char, c_int};
27 use libc::{c_char, c_int};
28 use std::convert::TryFrom;
28 use std::convert::TryFrom;
29
29
30 // C code uses a custom `dirstate_tuple` type, checks in multiple instances
30 // C code uses a custom `dirstate_tuple` type, checks in multiple instances
31 // for this type, and raises a Python `Exception` if the check does not pass.
31 // for this type, and raises a Python `Exception` if the check does not pass.
32 // Because this type differs only in name from the regular Python tuple, it
32 // Because this type differs only in name from the regular Python tuple, it
33 // would be a good idea in the near future to remove it entirely to allow
33 // would be a good idea in the near future to remove it entirely to allow
34 // for a pure Python tuple of the same effective structure to be used,
34 // for a pure Python tuple of the same effective structure to be used,
35 // rendering this type and the capsule below useless.
35 // rendering this type and the capsule below useless.
36 py_capsule_fn!(
36 py_capsule_fn!(
37 from mercurial.cext.parsers import make_dirstate_tuple_CAPI
37 from mercurial.cext.parsers import make_dirstate_tuple_CAPI
38 as make_dirstate_tuple_capi
38 as make_dirstate_tuple_capi
39 signature (
39 signature (
40 state: c_char,
40 state: c_char,
41 mode: c_int,
41 mode: c_int,
42 size: c_int,
42 size: c_int,
43 mtime: c_int,
43 mtime: c_int,
44 ) -> *mut RawPyObject
44 ) -> *mut RawPyObject
45 );
45 );
46
46
47 pub fn make_dirstate_tuple(
47 pub fn make_dirstate_tuple(
48 py: Python,
48 py: Python,
49 entry: &DirstateEntry,
49 entry: &DirstateEntry,
50 ) -> PyResult<PyObject> {
50 ) -> PyResult<PyObject> {
51 // might be silly to retrieve capsule function in hot loop
51 // might be silly to retrieve capsule function in hot loop
52 let make = make_dirstate_tuple_capi::retrieve(py)?;
52 let make = make_dirstate_tuple_capi::retrieve(py)?;
53
53
54 let &DirstateEntry {
54 let &DirstateEntry {
55 state,
55 state,
56 mode,
56 mode,
57 size,
57 size,
58 mtime,
58 mtime,
59 } = entry;
59 } = entry;
60 // Explicitly go through u8 first, then cast to platform-specific `c_char`
60 // Explicitly go through u8 first, then cast to platform-specific `c_char`
61 // because Into<u8> has a specific implementation while `as c_char` would
61 // because Into<u8> has a specific implementation while `as c_char` would
62 // just do a naive enum cast.
62 // just do a naive enum cast.
63 let state_code: u8 = state.into();
63 let state_code: u8 = state.into();
64
64
65 let maybe_obj = unsafe {
65 let maybe_obj = unsafe {
66 let ptr = make(state_code as c_char, mode, size, mtime);
66 let ptr = make(state_code as c_char, mode, size, mtime);
67 PyObject::from_owned_ptr_opt(py, ptr)
67 PyObject::from_owned_ptr_opt(py, ptr)
68 };
68 };
69 maybe_obj.ok_or_else(|| PyErr::fetch(py))
69 maybe_obj.ok_or_else(|| PyErr::fetch(py))
70 }
70 }
71
71
72 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
72 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
73 dmap.items(py)
73 dmap.items(py)
74 .iter()
74 .iter()
75 .map(|(filename, stats)| {
75 .map(|(filename, stats)| {
76 let stats = stats.extract::<PySequence>(py)?;
76 let stats = stats.extract::<PySequence>(py)?;
77 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
77 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
78 let state = EntryState::try_from(state.data(py)[0]).map_err(
78 let state = EntryState::try_from(state.data(py)[0]).map_err(
79 |e: DirstateParseError| {
79 |e: DirstateParseError| {
80 PyErr::new::<exc::ValueError, _>(py, e.to_string())
80 PyErr::new::<exc::ValueError, _>(py, e.to_string())
81 },
81 },
82 )?;
82 )?;
83 let mode = stats.get_item(py, 1)?.extract(py)?;
83 let mode = stats.get_item(py, 1)?.extract(py)?;
84 let size = stats.get_item(py, 2)?.extract(py)?;
84 let size = stats.get_item(py, 2)?.extract(py)?;
85 let mtime = stats.get_item(py, 3)?.extract(py)?;
85 let mtime = stats.get_item(py, 3)?.extract(py)?;
86 let filename = filename.extract::<PyBytes>(py)?;
86 let filename = filename.extract::<PyBytes>(py)?;
87 let filename = filename.data(py);
87 let filename = filename.data(py);
88 Ok((
88 Ok((
89 HgPathBuf::from(filename.to_owned()),
89 HgPathBuf::from(filename.to_owned()),
90 DirstateEntry {
90 DirstateEntry {
91 state,
91 state,
92 mode,
92 mode,
93 size,
93 size,
94 mtime,
94 mtime,
95 },
95 },
96 ))
96 ))
97 })
97 })
98 .collect()
98 .collect()
99 }
99 }
100
100
101 /// Create the module, with `__package__` given from parent
101 /// Create the module, with `__package__` given from parent
102 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
102 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
103 let dotted_name = &format!("{}.dirstate", package);
103 let dotted_name = &format!("{}.dirstate", package);
104 let m = PyModule::new(py, dotted_name)?;
104 let m = PyModule::new(py, dotted_name)?;
105
105
106 m.add(py, "__package__", package)?;
106 m.add(py, "__package__", package)?;
107 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
107 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
108
108
109 m.add_class::<Dirs>(py)?;
109 m.add_class::<Dirs>(py)?;
110 m.add_class::<DirstateMap>(py)?;
110 m.add_class::<DirstateMap>(py)?;
111 m.add(
111 m.add(
112 py,
112 py,
113 "status",
113 "status",
114 py_fn!(
114 py_fn!(
115 py,
115 py,
116 status_wrapper(
116 status_wrapper(
117 dmap: DirstateMap,
117 dmap: DirstateMap,
118 root_dir: PyObject,
118 root_dir: PyObject,
119 matcher: PyObject,
119 list_clean: bool,
120 list_clean: bool,
120 last_normal_time: i64,
121 last_normal_time: i64,
121 check_exec: bool
122 check_exec: bool
122 )
123 )
123 ),
124 ),
124 )?;
125 )?;
125
126
126 let sys = PyModule::import(py, "sys")?;
127 let sys = PyModule::import(py, "sys")?;
127 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
128 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
128 sys_modules.set_item(py, dotted_name, &m)?;
129 sys_modules.set_item(py, dotted_name, &m)?;
129
130
130 Ok(m)
131 Ok(m)
131 }
132 }
@@ -1,80 +1,129 b''
1 // status.rs
1 // status.rs
2 //
2 //
3 // Copyright 2019, Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019, Raphaël Gomès <rgomes@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Bindings for the `hg::status` module provided by the
8 //! Bindings for the `hg::status` module provided by the
9 //! `hg-core` crate. From Python, this will be seen as
9 //! `hg-core` crate. From Python, this will be seen as
10 //! `rustext.dirstate.status`.
10 //! `rustext.dirstate.status`.
11
11
12 use crate::dirstate::DirstateMap;
12 use crate::dirstate::DirstateMap;
13 use cpython::exc::ValueError;
13 use cpython::exc::ValueError;
14 use cpython::{
14 use cpython::{
15 PyBytes, PyErr, PyList, PyObject, PyResult, Python, PythonObject,
15 ObjectProtocol, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple,
16 ToPyObject,
16 Python, PythonObject, ToPyObject,
17 };
17 };
18 use hg::utils::files::get_path_from_bytes;
18 use hg::utils::hg_path::HgPathBuf;
19
19 use hg::{
20 use hg::matchers::AlwaysMatcher;
20 matchers::{AlwaysMatcher, FileMatcher},
21 use hg::status;
21 status,
22 use hg::utils::hg_path::HgPath;
22 utils::{files::get_path_from_bytes, hg_path::HgPath},
23 StatusResult,
24 };
25 use std::borrow::Borrow;
23
26
24 /// This will be useless once trait impls for collection are added to `PyBytes`
27 /// This will be useless once trait impls for collection are added to `PyBytes`
25 /// upstream.
28 /// upstream.
26 fn collect_pybytes_list<P: AsRef<HgPath>>(
29 fn collect_pybytes_list<P: AsRef<HgPath>>(
27 py: Python,
30 py: Python,
28 collection: &[P],
31 collection: &[P],
29 ) -> PyList {
32 ) -> PyList {
30 let list = PyList::new(py, &[]);
33 let list = PyList::new(py, &[]);
31
34
32 for (i, path) in collection.iter().enumerate() {
35 for (i, path) in collection.iter().enumerate() {
33 list.insert_item(
36 list.insert_item(
34 py,
37 py,
35 i,
38 i,
36 PyBytes::new(py, path.as_ref().as_bytes()).into_object(),
39 PyBytes::new(py, path.as_ref().as_bytes()).into_object(),
37 )
40 )
38 }
41 }
39
42
40 list
43 list
41 }
44 }
42
45
43 pub fn status_wrapper(
46 pub fn status_wrapper(
44 py: Python,
47 py: Python,
45 dmap: DirstateMap,
48 dmap: DirstateMap,
49 matcher: PyObject,
46 root_dir: PyObject,
50 root_dir: PyObject,
47 list_clean: bool,
51 list_clean: bool,
48 last_normal_time: i64,
52 last_normal_time: i64,
49 check_exec: bool,
53 check_exec: bool,
50 ) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
54 ) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
51 let bytes = root_dir.extract::<PyBytes>(py)?;
55 let bytes = root_dir.extract::<PyBytes>(py)?;
52 let root_dir = get_path_from_bytes(bytes.data(py));
56 let root_dir = get_path_from_bytes(bytes.data(py));
53
57
54 let dmap: DirstateMap = dmap.to_py_object(py);
58 let dmap: DirstateMap = dmap.to_py_object(py);
55 let dmap = dmap.get_inner(py);
59 let dmap = dmap.get_inner(py);
56
60
57 // TODO removed in the next patch to get the code to compile. This patch
61 match matcher.get_type(py).name(py).borrow() {
58 // is part of a series and does not make real sense on its own.
62 "alwaysmatcher" => {
59 let matcher = AlwaysMatcher;
63 let matcher = AlwaysMatcher;
64 let (lookup, status_res) = status(
65 &dmap,
66 &matcher,
67 &root_dir,
68 list_clean,
69 last_normal_time,
70 check_exec,
71 )
72 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
73 build_response(lookup, status_res, py)
74 }
75 "exactmatcher" => {
76 let files = matcher.call_method(
77 py,
78 "files",
79 PyTuple::new(py, &[]),
80 None,
81 )?;
82 let files: PyList = files.cast_into(py)?;
83 let files: PyResult<Vec<HgPathBuf>> = files
84 .iter(py)
85 .map(|f| {
86 Ok(HgPathBuf::from_bytes(
87 f.extract::<PyBytes>(py)?.data(py),
88 ))
89 })
90 .collect();
60
91
61 let (lookup, status_res) = status(
92 let files = files?;
62 &dmap,
93 let matcher = FileMatcher::new(&files)
63 &matcher,
94 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
64 &root_dir,
95 let (lookup, status_res) = status(
65 list_clean,
96 &dmap,
66 last_normal_time,
97 &matcher,
67 check_exec,
98 &root_dir,
68 )
99 list_clean,
69 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
100 last_normal_time,
101 check_exec,
102 )
103 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
104 build_response(lookup, status_res, py)
105 }
106 e => {
107 return Err(PyErr::new::<ValueError, _>(
108 py,
109 format!("Unsupported matcher {}", e),
110 ));
111 }
112 }
113 }
70
114
115 fn build_response(
116 lookup: Vec<&HgPath>,
117 status_res: StatusResult,
118 py: Python,
119 ) -> PyResult<(PyList, PyList, PyList, PyList, PyList, PyList, PyList)> {
71 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
120 let modified = collect_pybytes_list(py, status_res.modified.as_ref());
72 let added = collect_pybytes_list(py, status_res.added.as_ref());
121 let added = collect_pybytes_list(py, status_res.added.as_ref());
73 let removed = collect_pybytes_list(py, status_res.removed.as_ref());
122 let removed = collect_pybytes_list(py, status_res.removed.as_ref());
74 let deleted = collect_pybytes_list(py, status_res.deleted.as_ref());
123 let deleted = collect_pybytes_list(py, status_res.deleted.as_ref());
75 let clean = collect_pybytes_list(py, status_res.clean.as_ref());
124 let clean = collect_pybytes_list(py, status_res.clean.as_ref());
76 let lookup = collect_pybytes_list(py, lookup.as_ref());
125 let lookup = collect_pybytes_list(py, lookup.as_ref());
77 let unknown = PyList::new(py, &[]);
126 let unknown = PyList::new(py, &[]);
78
127
79 Ok((lookup, modified, added, removed, deleted, unknown, clean))
128 Ok((lookup, modified, added, removed, deleted, unknown, clean))
80 }
129 }
General Comments 0
You need to be logged in to leave comments. Login now