##// END OF EJS Templates
pathutil: replace the `skip` argument of `dirs` with a boolean...
marmoute -
r48756:e02f9af7 default
parent child Browse files
Show More
@@ -161,7 +161,7 b' bail:'
161 return ret;
161 return ret;
162 }
162 }
163
163
164 static int dirs_fromdict(PyObject *dirs, PyObject *source, char skipchar)
164 static int dirs_fromdict(PyObject *dirs, PyObject *source, bool only_tracked)
165 {
165 {
166 PyObject *key, *value;
166 PyObject *key, *value;
167 Py_ssize_t pos = 0;
167 Py_ssize_t pos = 0;
@@ -171,13 +171,13 b' static int dirs_fromdict(PyObject *dirs,'
171 PyErr_SetString(PyExc_TypeError, "expected string key");
171 PyErr_SetString(PyExc_TypeError, "expected string key");
172 return -1;
172 return -1;
173 }
173 }
174 if (skipchar) {
174 if (only_tracked) {
175 if (!dirstate_tuple_check(value)) {
175 if (!dirstate_tuple_check(value)) {
176 PyErr_SetString(PyExc_TypeError,
176 PyErr_SetString(PyExc_TypeError,
177 "expected a dirstate tuple");
177 "expected a dirstate tuple");
178 return -1;
178 return -1;
179 }
179 }
180 if (((dirstateItemObject *)value)->state == skipchar)
180 if (((dirstateItemObject *)value)->state == 'r')
181 continue;
181 continue;
182 }
182 }
183
183
@@ -218,15 +218,17 b' static int dirs_fromiter(PyObject *dirs,'
218 * Calculate a refcounted set of directory names for the files in a
218 * Calculate a refcounted set of directory names for the files in a
219 * dirstate.
219 * dirstate.
220 */
220 */
221 static int dirs_init(dirsObject *self, PyObject *args)
221 static int dirs_init(dirsObject *self, PyObject *args, PyObject *kwargs)
222 {
222 {
223 PyObject *dirs = NULL, *source = NULL;
223 PyObject *dirs = NULL, *source = NULL;
224 char skipchar = 0;
224 int only_tracked = 0;
225 int ret = -1;
225 int ret = -1;
226 static char *keywords_name[] = {"map", "only_tracked", NULL};
226
227
227 self->dict = NULL;
228 self->dict = NULL;
228
229
229 if (!PyArg_ParseTuple(args, "|Oc:__init__", &source, &skipchar))
230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:__init__",
231 keywords_name, &source, &only_tracked))
230 return -1;
232 return -1;
231
233
232 dirs = PyDict_New();
234 dirs = PyDict_New();
@@ -237,10 +239,10 b' static int dirs_init(dirsObject *self, P'
237 if (source == NULL)
239 if (source == NULL)
238 ret = 0;
240 ret = 0;
239 else if (PyDict_Check(source))
241 else if (PyDict_Check(source))
240 ret = dirs_fromdict(dirs, source, skipchar);
242 ret = dirs_fromdict(dirs, source, (bool)only_tracked);
241 else if (skipchar)
243 else if (only_tracked)
242 PyErr_SetString(PyExc_ValueError,
244 PyErr_SetString(PyExc_ValueError,
243 "skip character is only supported "
245 "`only_tracked` is only supported "
244 "with a dict source");
246 "with a dict source");
245 else
247 else
246 ret = dirs_fromiter(dirs, source);
248 ret = dirs_fromiter(dirs, source);
@@ -377,7 +377,7 b' class dirstatemap(object):'
377
377
378 @propertycache
378 @propertycache
379 def _dirs(self):
379 def _dirs(self):
380 return pathutil.dirs(self._map, b'r')
380 return pathutil.dirs(self._map, only_tracked=True)
381
381
382 @propertycache
382 @propertycache
383 def _alldirs(self):
383 def _alldirs(self):
@@ -315,20 +315,19 b' def finddirs(path):'
315 class dirs(object):
315 class dirs(object):
316 '''a multiset of directory names from a set of file paths'''
316 '''a multiset of directory names from a set of file paths'''
317
317
318 def __init__(self, map, skip=None):
318 def __init__(self, map, only_tracked=False):
319 """
319 """
320 a dict map indicates a dirstate while a list indicates a manifest
320 a dict map indicates a dirstate while a list indicates a manifest
321 """
321 """
322 self._dirs = {}
322 self._dirs = {}
323 addpath = self.addpath
323 addpath = self.addpath
324 if isinstance(map, dict) and skip is not None:
324 if isinstance(map, dict) and only_tracked:
325 for f, s in pycompat.iteritems(map):
325 for f, s in pycompat.iteritems(map):
326 if s.state != skip:
326 if s.state != b'r':
327 addpath(f)
327 addpath(f)
328 elif skip is not None:
328 elif only_tracked:
329 raise error.ProgrammingError(
329 msg = b"`only_tracked` is only supported with a dict source"
330 b"skip character is only supported with a dict source"
330 raise error.ProgrammingError(msg)
331 )
332 else:
331 else:
333 for f in map:
332 for f in map:
334 addpath(f)
333 addpath(f)
@@ -33,7 +33,7 b' impl DirsMultiset {'
33 /// If `skip_state` is provided, skips dirstate entries with equal state.
33 /// If `skip_state` is provided, skips dirstate entries with equal state.
34 pub fn from_dirstate<I, P>(
34 pub fn from_dirstate<I, P>(
35 dirstate: I,
35 dirstate: I,
36 skip_state: Option<EntryState>,
36 only_tracked: bool,
37 ) -> Result<Self, DirstateError>
37 ) -> Result<Self, DirstateError>
38 where
38 where
39 I: IntoIterator<
39 I: IntoIterator<
@@ -48,8 +48,8 b' impl DirsMultiset {'
48 let (filename, entry) = item?;
48 let (filename, entry) = item?;
49 let filename = filename.as_ref();
49 let filename = filename.as_ref();
50 // This `if` is optimized out of the loop
50 // This `if` is optimized out of the loop
51 if let Some(skip) = skip_state {
51 if only_tracked {
52 if skip != entry.state {
52 if entry.state != EntryState::Removed {
53 multiset.add_path(filename)?;
53 multiset.add_path(filename)?;
54 }
54 }
55 } else {
55 } else {
@@ -343,7 +343,7 b' mod tests {'
343
343
344 let new = DirsMultiset::from_dirstate(
344 let new = DirsMultiset::from_dirstate(
345 StateMap::default().into_iter().map(Ok),
345 StateMap::default().into_iter().map(Ok),
346 None,
346 false,
347 )
347 )
348 .unwrap();
348 .unwrap();
349 let expected = DirsMultiset {
349 let expected = DirsMultiset {
@@ -385,7 +385,7 b' mod tests {'
385 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
385 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
386 .collect();
386 .collect();
387
387
388 let new = DirsMultiset::from_dirstate(input_map, None).unwrap();
388 let new = DirsMultiset::from_dirstate(input_map, false).unwrap();
389 let expected = DirsMultiset {
389 let expected = DirsMultiset {
390 inner: expected_inner,
390 inner: expected_inner,
391 };
391 };
@@ -414,14 +414,12 b' mod tests {'
414 });
414 });
415
415
416 // "a" incremented with "a/c" and "a/d/"
416 // "a" incremented with "a/c" and "a/d/"
417 let expected_inner = [("", 1), ("a", 2)]
417 let expected_inner = [("", 1), ("a", 3)]
418 .iter()
418 .iter()
419 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
419 .map(|(k, v)| (HgPathBuf::from_bytes(k.as_bytes()), *v))
420 .collect();
420 .collect();
421
421
422 let new =
422 let new = DirsMultiset::from_dirstate(input_map, true).unwrap();
423 DirsMultiset::from_dirstate(input_map, Some(EntryState::Normal))
424 .unwrap();
425 let expected = DirsMultiset {
423 let expected = DirsMultiset {
426 inner: expected_inner,
424 inner: expected_inner,
427 };
425 };
@@ -334,7 +334,7 b' impl DirstateMap {'
334 if self.all_dirs.is_none() {
334 if self.all_dirs.is_none() {
335 self.all_dirs = Some(DirsMultiset::from_dirstate(
335 self.all_dirs = Some(DirsMultiset::from_dirstate(
336 self.state_map.iter().map(|(k, v)| Ok((k, *v))),
336 self.state_map.iter().map(|(k, v)| Ok((k, *v))),
337 None,
337 false,
338 )?);
338 )?);
339 }
339 }
340 Ok(())
340 Ok(())
@@ -344,7 +344,7 b' impl DirstateMap {'
344 if self.dirs.is_none() {
344 if self.dirs.is_none() {
345 self.dirs = Some(DirsMultiset::from_dirstate(
345 self.dirs = Some(DirsMultiset::from_dirstate(
346 self.state_map.iter().map(|(k, v)| Ok((k, *v))),
346 self.state_map.iter().map(|(k, v)| Ok((k, *v))),
347 Some(EntryState::Removed),
347 true,
348 )?);
348 )?);
349 }
349 }
350 Ok(())
350 Ok(())
@@ -9,19 +9,16 b''
9 //! `hg-core` package.
9 //! `hg-core` package.
10
10
11 use std::cell::RefCell;
11 use std::cell::RefCell;
12 use std::convert::TryInto;
13
12
14 use cpython::{
13 use cpython::{
15 exc, ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult,
14 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyObject,
16 Python, UnsafePyLeaked,
15 PyResult, Python, UnsafePyLeaked,
17 };
16 };
18
17
19 use crate::dirstate::extract_dirstate;
18 use crate::dirstate::extract_dirstate;
20 use hg::{
19 use hg::{
21 errors::HgError,
22 utils::hg_path::{HgPath, HgPathBuf},
20 utils::hg_path::{HgPath, HgPathBuf},
23 DirsMultiset, DirsMultisetIter, DirstateError, DirstateMapError,
21 DirsMultiset, DirsMultisetIter, DirstateError, DirstateMapError,
24 EntryState,
25 };
22 };
26
23
27 py_class!(pub class Dirs |py| {
24 py_class!(pub class Dirs |py| {
@@ -32,22 +29,17 b' py_class!(pub class Dirs |py| {'
32 def __new__(
29 def __new__(
33 _cls,
30 _cls,
34 map: PyObject,
31 map: PyObject,
35 skip: Option<PyObject> = None
32 only_tracked: Option<PyObject> = None
36 ) -> PyResult<Self> {
33 ) -> PyResult<Self> {
37 let mut skip_state: Option<EntryState> = None;
34 let only_tracked_b = if let Some(only_tracked) = only_tracked {
38 if let Some(skip) = skip {
35 only_tracked.extract::<PyBool>(py)?.is_true()
39 skip_state = Some(
36 } else {
40 skip.extract::<PyBytes>(py)?.data(py)[0]
37 false
41 .try_into()
38 };
42 .map_err(|e: HgError| {
43 PyErr::new::<exc::ValueError, _>(py, e.to_string())
44 })?,
45 );
46 }
47 let inner = if let Ok(map) = map.cast_as::<PyDict>(py) {
39 let inner = if let Ok(map) = map.cast_as::<PyDict>(py) {
48 let dirstate = extract_dirstate(py, &map)?;
40 let dirstate = extract_dirstate(py, &map)?;
49 let dirstate = dirstate.iter().map(|(k, v)| Ok((k, *v)));
41 let dirstate = dirstate.iter().map(|(k, v)| Ok((k, *v)));
50 DirsMultiset::from_dirstate(dirstate, skip_state)
42 DirsMultiset::from_dirstate(dirstate, only_tracked_b)
51 .map_err(|e: DirstateError| {
43 .map_err(|e: DirstateError| {
52 PyErr::new::<exc::ValueError, _>(py, e.to_string())
44 PyErr::new::<exc::ValueError, _>(py, e.to_string())
53 })?
45 })?
General Comments 0
You need to be logged in to leave comments. Login now