##// END OF EJS Templates
rust-dirstate: create dirstate submodule in hg-cpython...
Raphaël Gomès -
r42973:85cb54e7 default draft
parent child Browse files
Show More
@@ -0,0 +1,110 b''
1 // dirs_multiset.rs
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
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.
7
8 //! Bindings for the `hg::dirstate::dirs_multiset` file provided by the
9 //! `hg-core` package.
10
11 use std::cell::RefCell;
12
13 use cpython::{
14 exc, ObjectProtocol, PyBytes, PyDict, PyErr, PyObject, PyResult,
15 ToPyObject,
16 };
17
18 use crate::dirstate::extract_dirstate_vec;
19 use hg::{DirsIterable, DirsMultiset, DirstateMapError};
20
21 py_class!(pub class Dirs |py| {
22 data dirs_map: RefCell<DirsMultiset>;
23
24 // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes
25 // a `list`)
26 def __new__(
27 _cls,
28 map: PyObject,
29 skip: Option<PyObject> = None
30 ) -> PyResult<Self> {
31 let mut skip_state: Option<i8> = None;
32 if let Some(skip) = skip {
33 skip_state = Some(skip.extract::<PyBytes>(py)?.data(py)[0] as i8);
34 }
35 let dirs_map;
36
37 if let Ok(map) = map.cast_as::<PyDict>(py) {
38 let dirstate_vec = extract_dirstate_vec(py, &map)?;
39 dirs_map = DirsMultiset::new(
40 DirsIterable::Dirstate(dirstate_vec),
41 skip_state,
42 )
43 } else {
44 let map: Result<Vec<Vec<u8>>, PyErr> = map
45 .iter(py)?
46 .map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
47 .collect();
48 dirs_map = DirsMultiset::new(
49 DirsIterable::Manifest(map?),
50 skip_state,
51 )
52 }
53
54 Self::create_instance(py, RefCell::new(dirs_map))
55 }
56
57 def addpath(&self, path: PyObject) -> PyResult<PyObject> {
58 self.dirs_map(py).borrow_mut().add_path(
59 path.extract::<PyBytes>(py)?.data(py),
60 );
61 Ok(py.None())
62 }
63
64 def delpath(&self, path: PyObject) -> PyResult<PyObject> {
65 self.dirs_map(py).borrow_mut().delete_path(
66 path.extract::<PyBytes>(py)?.data(py),
67 )
68 .and(Ok(py.None()))
69 .or_else(|e| {
70 match e {
71 DirstateMapError::PathNotFound(_p) => {
72 Err(PyErr::new::<exc::ValueError, _>(
73 py,
74 "expected a value, found none".to_string(),
75 ))
76 }
77 DirstateMapError::EmptyPath => {
78 Ok(py.None())
79 }
80 }
81 })
82 }
83
84 // This is really inefficient on top of being ugly, but it's an easy way
85 // of having it work to continue working on the rest of the module
86 // hopefully bypassing Python entirely pretty soon.
87 def __iter__(&self) -> PyResult<PyObject> {
88 let dict = PyDict::new(py);
89
90 for (key, value) in self.dirs_map(py).borrow().iter() {
91 dict.set_item(
92 py,
93 PyBytes::new(py, &key[..]),
94 value.to_py_object(py),
95 )?;
96 }
97
98 let locals = PyDict::new(py);
99 locals.set_item(py, "obj", dict)?;
100
101 py.eval("iter(obj)", None, Some(&locals))
102 }
103
104 def __contains__(&self, item: PyObject) -> PyResult<bool> {
105 Ok(self
106 .dirs_map(py)
107 .borrow()
108 .contains_key(item.extract::<PyBytes>(py)?.data(py).as_ref()))
109 }
110 });
@@ -9,22 +9,21 b''
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
12 mod dirs_multiset;
13 use crate::dirstate::dirs_multiset::Dirs;
13 use cpython::{
14 use cpython::{
14 exc, ObjectProtocol, PyBytes, PyDict, PyErr, PyInt, PyModule, PyObject,
15 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyObject, PyResult,
15 PyResult, PySequence, PyTuple, Python, PythonObject, ToPyObject,
16 PySequence, PyTuple, Python, PythonObject, ToPyObject,
16 };
17 };
17 use hg::{
18 use hg::{
18 pack_dirstate, parse_dirstate, CopyVecEntry, DirsIterable, DirsMultiset,
19 pack_dirstate, parse_dirstate, CopyVecEntry, DirstateEntry,
19 DirstateEntry, DirstateMapError, DirstatePackError, DirstateParents,
20 DirstatePackError, DirstateParents, DirstateParseError, DirstateVec,
20 DirstateParseError, DirstateVec,
21 };
21 };
22 use libc::{c_char, c_int};
22 use libc::{c_char, c_int};
23 #[cfg(feature = "python27")]
23 #[cfg(feature = "python27")]
24 use python27_sys::PyCapsule_Import;
24 use python27_sys::PyCapsule_Import;
25 #[cfg(feature = "python3")]
25 #[cfg(feature = "python3")]
26 use python3_sys::PyCapsule_Import;
26 use python3_sys::PyCapsule_Import;
27 use std::cell::RefCell;
28 use std::collections::HashMap;
27 use std::collections::HashMap;
29 use std::ffi::CStr;
28 use std::ffi::CStr;
30 use std::mem::transmute;
29 use std::mem::transmute;
@@ -201,97 +200,6 b' fn pack_dirstate_wrapper('
201 }
200 }
202 }
201 }
203
202
204 py_class!(pub class Dirs |py| {
205 data dirs_map: RefCell<DirsMultiset>;
206
207 // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes
208 // a `list`)
209 def __new__(
210 _cls,
211 map: PyObject,
212 skip: Option<PyObject> = None
213 ) -> PyResult<Self> {
214 let mut skip_state: Option<i8> = None;
215 if let Some(skip) = skip {
216 skip_state = Some(skip.extract::<PyBytes>(py)?.data(py)[0] as i8);
217 }
218 let dirs_map;
219
220 if let Ok(map) = map.cast_as::<PyDict>(py) {
221 let dirstate_vec = extract_dirstate_vec(py, &map)?;
222 dirs_map = DirsMultiset::new(
223 DirsIterable::Dirstate(dirstate_vec),
224 skip_state,
225 )
226 } else {
227 let map: Result<Vec<Vec<u8>>, PyErr> = map
228 .iter(py)?
229 .map(|o| Ok(o?.extract::<PyBytes>(py)?.data(py).to_owned()))
230 .collect();
231 dirs_map = DirsMultiset::new(
232 DirsIterable::Manifest(map?),
233 skip_state,
234 )
235 }
236
237 Self::create_instance(py, RefCell::new(dirs_map))
238 }
239
240 def addpath(&self, path: PyObject) -> PyResult<PyObject> {
241 self.dirs_map(py).borrow_mut().add_path(
242 path.extract::<PyBytes>(py)?.data(py),
243 );
244 Ok(py.None())
245 }
246
247 def delpath(&self, path: PyObject) -> PyResult<PyObject> {
248 self.dirs_map(py).borrow_mut().delete_path(
249 path.extract::<PyBytes>(py)?.data(py),
250 )
251 .and(Ok(py.None()))
252 .or_else(|e| {
253 match e {
254 DirstateMapError::PathNotFound(_p) => {
255 Err(PyErr::new::<exc::ValueError, _>(
256 py,
257 "expected a value, found none".to_string(),
258 ))
259 }
260 DirstateMapError::EmptyPath => {
261 Ok(py.None())
262 }
263 }
264 })
265 }
266
267 // This is really inefficient on top of being ugly, but it's an easy way
268 // of having it work to continue working on the rest of the module
269 // hopefully bypassing Python entirely pretty soon.
270 def __iter__(&self) -> PyResult<PyObject> {
271 let dict = PyDict::new(py);
272
273 for (key, value) in self.dirs_map(py).borrow().iter() {
274 dict.set_item(
275 py,
276 PyBytes::new(py, &key[..]),
277 value.to_py_object(py),
278 )?;
279 }
280
281 let locals = PyDict::new(py);
282 locals.set_item(py, "obj", dict)?;
283
284 py.eval("iter(obj)", None, Some(&locals))
285 }
286
287 def __contains__(&self, item: PyObject) -> PyResult<bool> {
288 Ok(self
289 .dirs_map(py)
290 .borrow()
291 .contains_key(item.extract::<PyBytes>(py)?.data(py).as_ref()))
292 }
293 });
294
295 /// Create the module, with `__package__` given from parent
203 /// Create the module, with `__package__` given from parent
296 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
204 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
297 let dotted_name = &format!("{}.dirstate", package);
205 let dotted_name = &format!("{}.dirstate", package);
General Comments 0
You need to be logged in to leave comments. Login now