##// END OF EJS Templates
rust-cpython: switch to upstreamed version of PySharedRefCell...
Yuya Nishihara -
r44703:bad4e7b3 default
parent child Browse files
Show More
@@ -1,117 +1,118 b''
1 1 // copymap.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for `hg::dirstate::dirstate_map::CopyMap` provided by the
9 9 //! `hg-core` package.
10 10
11 use cpython::{PyBytes, PyClone, PyDict, PyObject, PyResult, Python};
11 use cpython::{
12 PyBytes, PyClone, PyDict, PyObject, PyResult, Python, UnsafePyLeaked,
13 };
12 14 use std::cell::RefCell;
13 15
14 16 use crate::dirstate::dirstate_map::DirstateMap;
15 use crate::ref_sharing::PyLeaked;
16 17 use hg::{utils::hg_path::HgPathBuf, CopyMapIter};
17 18
18 19 py_class!(pub class CopyMap |py| {
19 20 data dirstate_map: DirstateMap;
20 21
21 22 def __getitem__(&self, key: PyObject) -> PyResult<PyBytes> {
22 23 (*self.dirstate_map(py)).copymapgetitem(py, key)
23 24 }
24 25
25 26 def __len__(&self) -> PyResult<usize> {
26 27 self.dirstate_map(py).copymaplen(py)
27 28 }
28 29
29 30 def __contains__(&self, key: PyObject) -> PyResult<bool> {
30 31 self.dirstate_map(py).copymapcontains(py, key)
31 32 }
32 33
33 34 def get(
34 35 &self,
35 36 key: PyObject,
36 37 default: Option<PyObject> = None
37 38 ) -> PyResult<Option<PyObject>> {
38 39 self.dirstate_map(py).copymapget(py, key, default)
39 40 }
40 41
41 42 def pop(
42 43 &self,
43 44 key: PyObject,
44 45 default: Option<PyObject> = None
45 46 ) -> PyResult<Option<PyObject>> {
46 47 self.dirstate_map(py).copymappop(py, key, default)
47 48 }
48 49
49 50 def __iter__(&self) -> PyResult<CopyMapKeysIterator> {
50 51 self.dirstate_map(py).copymapiter(py)
51 52 }
52 53
53 54 // Python's `dict()` builtin works with either a subclass of dict
54 55 // or an abstract mapping. Said mapping needs to implement `__getitem__`
55 56 // and `keys`.
56 57 def keys(&self) -> PyResult<CopyMapKeysIterator> {
57 58 self.dirstate_map(py).copymapiter(py)
58 59 }
59 60
60 61 def items(&self) -> PyResult<CopyMapItemsIterator> {
61 62 self.dirstate_map(py).copymapitemsiter(py)
62 63 }
63 64
64 65 def iteritems(&self) -> PyResult<CopyMapItemsIterator> {
65 66 self.dirstate_map(py).copymapitemsiter(py)
66 67 }
67 68
68 69 def __setitem__(
69 70 &self,
70 71 key: PyObject,
71 72 item: PyObject
72 73 ) -> PyResult<()> {
73 74 self.dirstate_map(py).copymapsetitem(py, key, item)?;
74 75 Ok(())
75 76 }
76 77
77 78 def copy(&self) -> PyResult<PyDict> {
78 79 self.dirstate_map(py).copymapcopy(py)
79 80 }
80 81
81 82 });
82 83
83 84 impl CopyMap {
84 85 pub fn from_inner(py: Python, dm: DirstateMap) -> PyResult<Self> {
85 86 Self::create_instance(py, dm)
86 87 }
87 88 fn translate_key(
88 89 py: Python,
89 90 res: (&HgPathBuf, &HgPathBuf),
90 91 ) -> PyResult<Option<PyBytes>> {
91 92 Ok(Some(PyBytes::new(py, res.0.as_ref())))
92 93 }
93 94 fn translate_key_value(
94 95 py: Python,
95 96 res: (&HgPathBuf, &HgPathBuf),
96 97 ) -> PyResult<Option<(PyBytes, PyBytes)>> {
97 98 let (k, v) = res;
98 99 Ok(Some((
99 100 PyBytes::new(py, k.as_ref()),
100 101 PyBytes::new(py, v.as_ref()),
101 102 )))
102 103 }
103 104 }
104 105
105 106 py_shared_iterator!(
106 107 CopyMapKeysIterator,
107 PyLeaked<CopyMapIter<'static>>,
108 UnsafePyLeaked<CopyMapIter<'static>>,
108 109 CopyMap::translate_key,
109 110 Option<PyBytes>
110 111 );
111 112
112 113 py_shared_iterator!(
113 114 CopyMapItemsIterator,
114 PyLeaked<CopyMapIter<'static>>,
115 UnsafePyLeaked<CopyMapIter<'static>>,
115 116 CopyMap::translate_key_value,
116 117 Option<(PyBytes, PyBytes)>
117 118 );
@@ -1,146 +1,140 b''
1 1 // dirs_multiset.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate::dirs_multiset` file provided by the
9 9 //! `hg-core` package.
10 10
11 11 use std::cell::RefCell;
12 12 use std::convert::TryInto;
13 13
14 14 use cpython::{
15 15 exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult,
16 Python,
16 Python, UnsafePyLeaked,
17 17 };
18 18
19 19 use crate::dirstate::extract_dirstate;
20 use crate::ref_sharing::{PyLeaked, PySharedRefCell};
21 20 use hg::{
22 21 utils::hg_path::{HgPath, HgPathBuf},
23 22 DirsMultiset, DirsMultisetIter, DirstateMapError, DirstateParseError,
24 23 EntryState,
25 24 };
26 25
27 26 py_class!(pub class Dirs |py| {
28 data inner_: PySharedRefCell<DirsMultiset>;
27 @shared data inner: DirsMultiset;
29 28
30 29 // `map` is either a `dict` or a flat iterator (usually a `set`, sometimes
31 30 // a `list`)
32 31 def __new__(
33 32 _cls,
34 33 map: PyObject,
35 34 skip: Option<PyObject> = None
36 35 ) -> PyResult<Self> {
37 36 let mut skip_state: Option<EntryState> = None;
38 37 if let Some(skip) = skip {
39 38 skip_state = Some(
40 39 skip.extract::<PyBytes>(py)?.data(py)[0]
41 40 .try_into()
42 41 .map_err(|e: DirstateParseError| {
43 42 PyErr::new::<exc::ValueError, _>(py, e.to_string())
44 43 })?,
45 44 );
46 45 }
47 46 let inner = if let Ok(map) = map.cast_as::<PyDict>(py) {
48 47 let dirstate = extract_dirstate(py, &map)?;
49 48 DirsMultiset::from_dirstate(&dirstate, skip_state)
50 49 .map_err(|e| {
51 50 PyErr::new::<exc::ValueError, _>(py, e.to_string())
52 51 })?
53 52 } else {
54 53 let map: Result<Vec<HgPathBuf>, PyErr> = map
55 54 .iter(py)?
56 55 .map(|o| {
57 56 Ok(HgPathBuf::from_bytes(
58 57 o?.extract::<PyBytes>(py)?.data(py),
59 58 ))
60 59 })
61 60 .collect();
62 61 DirsMultiset::from_manifest(&map?)
63 62 .map_err(|e| {
64 63 PyErr::new::<exc::ValueError, _>(py, e.to_string())
65 64 })?
66 65 };
67 66
68 Self::create_instance(
69 py,
70 PySharedRefCell::new(inner),
71 )
67 Self::create_instance(py, inner)
72 68 }
73 69
74 70 def addpath(&self, path: PyObject) -> PyResult<PyObject> {
75 71 self.inner(py).borrow_mut().add_path(
76 72 HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
77 73 ).and(Ok(py.None())).or_else(|e| {
78 74 match e {
79 75 DirstateMapError::EmptyPath => {
80 76 Ok(py.None())
81 77 },
82 78 e => {
83 79 Err(PyErr::new::<exc::ValueError, _>(
84 80 py,
85 81 e.to_string(),
86 82 ))
87 83 }
88 84 }
89 85 })
90 86 }
91 87
92 88 def delpath(&self, path: PyObject) -> PyResult<PyObject> {
93 89 self.inner(py).borrow_mut().delete_path(
94 90 HgPath::new(path.extract::<PyBytes>(py)?.data(py)),
95 91 )
96 92 .and(Ok(py.None()))
97 93 .or_else(|e| {
98 94 match e {
99 95 DirstateMapError::EmptyPath => {
100 96 Ok(py.None())
101 97 },
102 98 e => {
103 99 Err(PyErr::new::<exc::ValueError, _>(
104 100 py,
105 101 e.to_string(),
106 102 ))
107 103 }
108 104 }
109 105 })
110 106 }
111 107 def __iter__(&self) -> PyResult<DirsMultisetKeysIterator> {
112 108 let leaked_ref = self.inner(py).leak_immutable();
113 109 DirsMultisetKeysIterator::from_inner(
114 110 py,
115 111 unsafe { leaked_ref.map(py, |o| o.iter()) },
116 112 )
117 113 }
118 114
119 115 def __contains__(&self, item: PyObject) -> PyResult<bool> {
120 116 Ok(self.inner(py).borrow().contains(HgPath::new(
121 117 item.extract::<PyBytes>(py)?.data(py).as_ref(),
122 118 )))
123 119 }
124 120 });
125 121
126 py_shared_ref!(Dirs, DirsMultiset, inner_, inner);
127
128 122 impl Dirs {
129 123 pub fn from_inner(py: Python, d: DirsMultiset) -> PyResult<Self> {
130 Self::create_instance(py, PySharedRefCell::new(d))
124 Self::create_instance(py, d)
131 125 }
132 126
133 127 fn translate_key(
134 128 py: Python,
135 129 res: &HgPathBuf,
136 130 ) -> PyResult<Option<PyBytes>> {
137 131 Ok(Some(PyBytes::new(py, res.as_ref())))
138 132 }
139 133 }
140 134
141 135 py_shared_iterator!(
142 136 DirsMultisetKeysIterator,
143 PyLeaked<DirsMultisetIter<'static>>,
137 UnsafePyLeaked<DirsMultisetIter<'static>>,
144 138 Dirs::translate_key,
145 139 Option<PyBytes>
146 140 );
@@ -1,522 +1,516 b''
1 1 // dirstate_map.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate::dirstate_map` file provided by the
9 9 //! `hg-core` package.
10 10
11 11 use std::cell::{Ref, RefCell};
12 12 use std::convert::TryInto;
13 13 use std::time::Duration;
14 14
15 15 use cpython::{
16 16 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyObject,
17 PyResult, PyTuple, Python, PythonObject, ToPyObject,
17 PyResult, PyTuple, Python, PythonObject, ToPyObject, UnsafePyLeaked,
18 18 };
19 19
20 20 use crate::{
21 21 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
22 22 dirstate::{dirs_multiset::Dirs, make_dirstate_tuple},
23 ref_sharing::{PyLeaked, PySharedRefCell},
24 23 };
25 24 use hg::{
26 25 utils::hg_path::{HgPath, HgPathBuf},
27 26 DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap,
28 27 DirstateMapError, DirstateParents, DirstateParseError, EntryState,
29 28 StateMapIter, PARENT_SIZE,
30 29 };
31 30
32 31 // TODO
33 32 // This object needs to share references to multiple members of its Rust
34 33 // inner struct, namely `copy_map`, `dirs` and `all_dirs`.
35 34 // Right now `CopyMap` is done, but it needs to have an explicit reference
36 35 // to `RustDirstateMap` which itself needs to have an encapsulation for
37 36 // every method in `CopyMap` (copymapcopy, etc.).
38 37 // This is ugly and hard to maintain.
39 38 // The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
40 39 // `py_class!` is already implemented and does not mention
41 40 // `RustDirstateMap`, rightfully so.
42 41 // All attributes also have to have a separate refcount data attribute for
43 42 // leaks, with all methods that go along for reference sharing.
44 43 py_class!(pub class DirstateMap |py| {
45 data inner_: PySharedRefCell<RustDirstateMap>;
44 @shared data inner: RustDirstateMap;
46 45
47 46 def __new__(_cls, _root: PyObject) -> PyResult<Self> {
48 47 let inner = RustDirstateMap::default();
49 Self::create_instance(
50 py,
51 PySharedRefCell::new(inner),
52 )
48 Self::create_instance(py, inner)
53 49 }
54 50
55 51 def clear(&self) -> PyResult<PyObject> {
56 52 self.inner(py).borrow_mut().clear();
57 53 Ok(py.None())
58 54 }
59 55
60 56 def get(
61 57 &self,
62 58 key: PyObject,
63 59 default: Option<PyObject> = None
64 60 ) -> PyResult<Option<PyObject>> {
65 61 let key = key.extract::<PyBytes>(py)?;
66 62 match self.inner(py).borrow().get(HgPath::new(key.data(py))) {
67 63 Some(entry) => {
68 64 Ok(Some(make_dirstate_tuple(py, entry)?))
69 65 },
70 66 None => Ok(default)
71 67 }
72 68 }
73 69
74 70 def addfile(
75 71 &self,
76 72 f: PyObject,
77 73 oldstate: PyObject,
78 74 state: PyObject,
79 75 mode: PyObject,
80 76 size: PyObject,
81 77 mtime: PyObject
82 78 ) -> PyResult<PyObject> {
83 79 self.inner(py).borrow_mut().add_file(
84 80 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
85 81 oldstate.extract::<PyBytes>(py)?.data(py)[0]
86 82 .try_into()
87 83 .map_err(|e: DirstateParseError| {
88 84 PyErr::new::<exc::ValueError, _>(py, e.to_string())
89 85 })?,
90 86 DirstateEntry {
91 87 state: state.extract::<PyBytes>(py)?.data(py)[0]
92 88 .try_into()
93 89 .map_err(|e: DirstateParseError| {
94 90 PyErr::new::<exc::ValueError, _>(py, e.to_string())
95 91 })?,
96 92 mode: mode.extract(py)?,
97 93 size: size.extract(py)?,
98 94 mtime: mtime.extract(py)?,
99 95 },
100 96 ).and(Ok(py.None())).or_else(|e: DirstateMapError| {
101 97 Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
102 98 })
103 99 }
104 100
105 101 def removefile(
106 102 &self,
107 103 f: PyObject,
108 104 oldstate: PyObject,
109 105 size: PyObject
110 106 ) -> PyResult<PyObject> {
111 107 self.inner(py).borrow_mut()
112 108 .remove_file(
113 109 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
114 110 oldstate.extract::<PyBytes>(py)?.data(py)[0]
115 111 .try_into()
116 112 .map_err(|e: DirstateParseError| {
117 113 PyErr::new::<exc::ValueError, _>(py, e.to_string())
118 114 })?,
119 115 size.extract(py)?,
120 116 )
121 117 .or_else(|_| {
122 118 Err(PyErr::new::<exc::OSError, _>(
123 119 py,
124 120 "Dirstate error".to_string(),
125 121 ))
126 122 })?;
127 123 Ok(py.None())
128 124 }
129 125
130 126 def dropfile(
131 127 &self,
132 128 f: PyObject,
133 129 oldstate: PyObject
134 130 ) -> PyResult<PyBool> {
135 131 self.inner(py).borrow_mut()
136 132 .drop_file(
137 133 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
138 134 oldstate.extract::<PyBytes>(py)?.data(py)[0]
139 135 .try_into()
140 136 .map_err(|e: DirstateParseError| {
141 137 PyErr::new::<exc::ValueError, _>(py, e.to_string())
142 138 })?,
143 139 )
144 140 .and_then(|b| Ok(b.to_py_object(py)))
145 141 .or_else(|_| {
146 142 Err(PyErr::new::<exc::OSError, _>(
147 143 py,
148 144 "Dirstate error".to_string(),
149 145 ))
150 146 })
151 147 }
152 148
153 149 def clearambiguoustimes(
154 150 &self,
155 151 files: PyObject,
156 152 now: PyObject
157 153 ) -> PyResult<PyObject> {
158 154 let files: PyResult<Vec<HgPathBuf>> = files
159 155 .iter(py)?
160 156 .map(|filename| {
161 157 Ok(HgPathBuf::from_bytes(
162 158 filename?.extract::<PyBytes>(py)?.data(py),
163 159 ))
164 160 })
165 161 .collect();
166 162 self.inner(py).borrow_mut()
167 163 .clear_ambiguous_times(files?, now.extract(py)?);
168 164 Ok(py.None())
169 165 }
170 166
171 167 // TODO share the reference
172 168 def nonnormalentries(&self) -> PyResult<PyObject> {
173 169 let (non_normal, other_parent) =
174 170 self.inner(py).borrow().non_normal_other_parent_entries();
175 171
176 172 let locals = PyDict::new(py);
177 173 locals.set_item(
178 174 py,
179 175 "non_normal",
180 176 non_normal
181 177 .iter()
182 178 .map(|v| PyBytes::new(py, v.as_ref()))
183 179 .collect::<Vec<PyBytes>>()
184 180 .to_py_object(py),
185 181 )?;
186 182 locals.set_item(
187 183 py,
188 184 "other_parent",
189 185 other_parent
190 186 .iter()
191 187 .map(|v| PyBytes::new(py, v.as_ref()))
192 188 .collect::<Vec<PyBytes>>()
193 189 .to_py_object(py),
194 190 )?;
195 191
196 192 py.eval("set(non_normal), set(other_parent)", None, Some(&locals))
197 193 }
198 194
199 195 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
200 196 let d = d.extract::<PyBytes>(py)?;
201 197 Ok(self.inner(py).borrow_mut()
202 198 .has_tracked_dir(HgPath::new(d.data(py)))
203 199 .map_err(|e| {
204 200 PyErr::new::<exc::ValueError, _>(py, e.to_string())
205 201 })?
206 202 .to_py_object(py))
207 203 }
208 204
209 205 def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
210 206 let d = d.extract::<PyBytes>(py)?;
211 207 Ok(self.inner(py).borrow_mut()
212 208 .has_dir(HgPath::new(d.data(py)))
213 209 .map_err(|e| {
214 210 PyErr::new::<exc::ValueError, _>(py, e.to_string())
215 211 })?
216 212 .to_py_object(py))
217 213 }
218 214
219 215 def parents(&self, st: PyObject) -> PyResult<PyTuple> {
220 216 self.inner(py).borrow_mut()
221 217 .parents(st.extract::<PyBytes>(py)?.data(py))
222 218 .and_then(|d| {
223 219 Ok((PyBytes::new(py, &d.p1), PyBytes::new(py, &d.p2))
224 220 .to_py_object(py))
225 221 })
226 222 .or_else(|_| {
227 223 Err(PyErr::new::<exc::OSError, _>(
228 224 py,
229 225 "Dirstate error".to_string(),
230 226 ))
231 227 })
232 228 }
233 229
234 230 def setparents(&self, p1: PyObject, p2: PyObject) -> PyResult<PyObject> {
235 231 let p1 = extract_node_id(py, &p1)?;
236 232 let p2 = extract_node_id(py, &p2)?;
237 233
238 234 self.inner(py).borrow_mut()
239 235 .set_parents(&DirstateParents { p1, p2 });
240 236 Ok(py.None())
241 237 }
242 238
243 239 def read(&self, st: PyObject) -> PyResult<Option<PyObject>> {
244 240 match self.inner(py).borrow_mut()
245 241 .read(st.extract::<PyBytes>(py)?.data(py))
246 242 {
247 243 Ok(Some(parents)) => Ok(Some(
248 244 (PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2))
249 245 .to_py_object(py)
250 246 .into_object(),
251 247 )),
252 248 Ok(None) => Ok(Some(py.None())),
253 249 Err(_) => Err(PyErr::new::<exc::OSError, _>(
254 250 py,
255 251 "Dirstate error".to_string(),
256 252 )),
257 253 }
258 254 }
259 255 def write(
260 256 &self,
261 257 p1: PyObject,
262 258 p2: PyObject,
263 259 now: PyObject
264 260 ) -> PyResult<PyBytes> {
265 261 let now = Duration::new(now.extract(py)?, 0);
266 262 let parents = DirstateParents {
267 263 p1: extract_node_id(py, &p1)?,
268 264 p2: extract_node_id(py, &p2)?,
269 265 };
270 266
271 267 match self.inner(py).borrow_mut().pack(parents, now) {
272 268 Ok(packed) => Ok(PyBytes::new(py, &packed)),
273 269 Err(_) => Err(PyErr::new::<exc::OSError, _>(
274 270 py,
275 271 "Dirstate error".to_string(),
276 272 )),
277 273 }
278 274 }
279 275
280 276 def filefoldmapasdict(&self) -> PyResult<PyDict> {
281 277 let dict = PyDict::new(py);
282 278 for (key, value) in
283 279 self.inner(py).borrow_mut().build_file_fold_map().iter()
284 280 {
285 281 dict.set_item(py, key.as_ref().to_vec(), value.as_ref().to_vec())?;
286 282 }
287 283 Ok(dict)
288 284 }
289 285
290 286 def __len__(&self) -> PyResult<usize> {
291 287 Ok(self.inner(py).borrow().len())
292 288 }
293 289
294 290 def __contains__(&self, key: PyObject) -> PyResult<bool> {
295 291 let key = key.extract::<PyBytes>(py)?;
296 292 Ok(self.inner(py).borrow().contains_key(HgPath::new(key.data(py))))
297 293 }
298 294
299 295 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
300 296 let key = key.extract::<PyBytes>(py)?;
301 297 let key = HgPath::new(key.data(py));
302 298 match self.inner(py).borrow().get(key) {
303 299 Some(entry) => {
304 300 Ok(make_dirstate_tuple(py, entry)?)
305 301 },
306 302 None => Err(PyErr::new::<exc::KeyError, _>(
307 303 py,
308 304 String::from_utf8_lossy(key.as_bytes()),
309 305 )),
310 306 }
311 307 }
312 308
313 309 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
314 310 let leaked_ref = self.inner(py).leak_immutable();
315 311 DirstateMapKeysIterator::from_inner(
316 312 py,
317 313 unsafe { leaked_ref.map(py, |o| o.iter()) },
318 314 )
319 315 }
320 316
321 317 def items(&self) -> PyResult<DirstateMapItemsIterator> {
322 318 let leaked_ref = self.inner(py).leak_immutable();
323 319 DirstateMapItemsIterator::from_inner(
324 320 py,
325 321 unsafe { leaked_ref.map(py, |o| o.iter()) },
326 322 )
327 323 }
328 324
329 325 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
330 326 let leaked_ref = self.inner(py).leak_immutable();
331 327 DirstateMapKeysIterator::from_inner(
332 328 py,
333 329 unsafe { leaked_ref.map(py, |o| o.iter()) },
334 330 )
335 331 }
336 332
337 333 def getdirs(&self) -> PyResult<Dirs> {
338 334 // TODO don't copy, share the reference
339 335 self.inner(py).borrow_mut().set_dirs()
340 336 .map_err(|e| {
341 337 PyErr::new::<exc::ValueError, _>(py, e.to_string())
342 338 })?;
343 339 Dirs::from_inner(
344 340 py,
345 341 DirsMultiset::from_dirstate(
346 342 &self.inner(py).borrow(),
347 343 Some(EntryState::Removed),
348 344 )
349 345 .map_err(|e| {
350 346 PyErr::new::<exc::ValueError, _>(py, e.to_string())
351 347 })?,
352 348 )
353 349 }
354 350 def getalldirs(&self) -> PyResult<Dirs> {
355 351 // TODO don't copy, share the reference
356 352 self.inner(py).borrow_mut().set_all_dirs()
357 353 .map_err(|e| {
358 354 PyErr::new::<exc::ValueError, _>(py, e.to_string())
359 355 })?;
360 356 Dirs::from_inner(
361 357 py,
362 358 DirsMultiset::from_dirstate(
363 359 &self.inner(py).borrow(),
364 360 None,
365 361 ).map_err(|e| {
366 362 PyErr::new::<exc::ValueError, _>(py, e.to_string())
367 363 })?,
368 364 )
369 365 }
370 366
371 367 // TODO all copymap* methods, see docstring above
372 368 def copymapcopy(&self) -> PyResult<PyDict> {
373 369 let dict = PyDict::new(py);
374 370 for (key, value) in self.inner(py).borrow().copy_map.iter() {
375 371 dict.set_item(
376 372 py,
377 373 PyBytes::new(py, key.as_ref()),
378 374 PyBytes::new(py, value.as_ref()),
379 375 )?;
380 376 }
381 377 Ok(dict)
382 378 }
383 379
384 380 def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
385 381 let key = key.extract::<PyBytes>(py)?;
386 382 match self.inner(py).borrow().copy_map.get(HgPath::new(key.data(py))) {
387 383 Some(copy) => Ok(PyBytes::new(py, copy.as_ref())),
388 384 None => Err(PyErr::new::<exc::KeyError, _>(
389 385 py,
390 386 String::from_utf8_lossy(key.data(py)),
391 387 )),
392 388 }
393 389 }
394 390 def copymap(&self) -> PyResult<CopyMap> {
395 391 CopyMap::from_inner(py, self.clone_ref(py))
396 392 }
397 393
398 394 def copymaplen(&self) -> PyResult<usize> {
399 395 Ok(self.inner(py).borrow().copy_map.len())
400 396 }
401 397 def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
402 398 let key = key.extract::<PyBytes>(py)?;
403 399 Ok(self
404 400 .inner(py)
405 401 .borrow()
406 402 .copy_map
407 403 .contains_key(HgPath::new(key.data(py))))
408 404 }
409 405 def copymapget(
410 406 &self,
411 407 key: PyObject,
412 408 default: Option<PyObject>
413 409 ) -> PyResult<Option<PyObject>> {
414 410 let key = key.extract::<PyBytes>(py)?;
415 411 match self
416 412 .inner(py)
417 413 .borrow()
418 414 .copy_map
419 415 .get(HgPath::new(key.data(py)))
420 416 {
421 417 Some(copy) => Ok(Some(
422 418 PyBytes::new(py, copy.as_ref()).into_object(),
423 419 )),
424 420 None => Ok(default),
425 421 }
426 422 }
427 423 def copymapsetitem(
428 424 &self,
429 425 key: PyObject,
430 426 value: PyObject
431 427 ) -> PyResult<PyObject> {
432 428 let key = key.extract::<PyBytes>(py)?;
433 429 let value = value.extract::<PyBytes>(py)?;
434 430 self.inner(py).borrow_mut().copy_map.insert(
435 431 HgPathBuf::from_bytes(key.data(py)),
436 432 HgPathBuf::from_bytes(value.data(py)),
437 433 );
438 434 Ok(py.None())
439 435 }
440 436 def copymappop(
441 437 &self,
442 438 key: PyObject,
443 439 default: Option<PyObject>
444 440 ) -> PyResult<Option<PyObject>> {
445 441 let key = key.extract::<PyBytes>(py)?;
446 442 match self
447 443 .inner(py)
448 444 .borrow_mut()
449 445 .copy_map
450 446 .remove(HgPath::new(key.data(py)))
451 447 {
452 448 Some(_) => Ok(None),
453 449 None => Ok(default),
454 450 }
455 451 }
456 452
457 453 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
458 454 let leaked_ref = self.inner(py).leak_immutable();
459 455 CopyMapKeysIterator::from_inner(
460 456 py,
461 457 unsafe { leaked_ref.map(py, |o| o.copy_map.iter()) },
462 458 )
463 459 }
464 460
465 461 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
466 462 let leaked_ref = self.inner(py).leak_immutable();
467 463 CopyMapItemsIterator::from_inner(
468 464 py,
469 465 unsafe { leaked_ref.map(py, |o| o.copy_map.iter()) },
470 466 )
471 467 }
472 468
473 469 });
474 470
475 471 impl DirstateMap {
476 472 pub fn get_inner<'a>(
477 473 &'a self,
478 474 py: Python<'a>,
479 475 ) -> Ref<'a, RustDirstateMap> {
480 476 self.inner(py).borrow()
481 477 }
482 478 fn translate_key(
483 479 py: Python,
484 480 res: (&HgPathBuf, &DirstateEntry),
485 481 ) -> PyResult<Option<PyBytes>> {
486 482 Ok(Some(PyBytes::new(py, res.0.as_ref())))
487 483 }
488 484 fn translate_key_value(
489 485 py: Python,
490 486 res: (&HgPathBuf, &DirstateEntry),
491 487 ) -> PyResult<Option<(PyBytes, PyObject)>> {
492 488 let (f, entry) = res;
493 489 Ok(Some((
494 490 PyBytes::new(py, f.as_ref()),
495 491 make_dirstate_tuple(py, entry)?,
496 492 )))
497 493 }
498 494 }
499 495
500 py_shared_ref!(DirstateMap, RustDirstateMap, inner_, inner);
501
502 496 py_shared_iterator!(
503 497 DirstateMapKeysIterator,
504 PyLeaked<StateMapIter<'static>>,
498 UnsafePyLeaked<StateMapIter<'static>>,
505 499 DirstateMap::translate_key,
506 500 Option<PyBytes>
507 501 );
508 502
509 503 py_shared_iterator!(
510 504 DirstateMapItemsIterator,
511 PyLeaked<StateMapIter<'static>>,
505 UnsafePyLeaked<StateMapIter<'static>>,
512 506 DirstateMap::translate_key_value,
513 507 Option<(PyBytes, PyObject)>
514 508 );
515 509
516 510 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<[u8; PARENT_SIZE]> {
517 511 let bytes = obj.extract::<PyBytes>(py)?;
518 512 match bytes.data(py).try_into() {
519 513 Ok(s) => Ok(s),
520 514 Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
521 515 }
522 516 }
General Comments 0
You need to be logged in to leave comments. Login now