diff -r 18b3060fe598 -r ed1583a845d2 rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs Wed May 19 13:15:00 2021 +0200 +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs Wed May 19 13:15:00 2021 +0200 @@ -29,13 +29,13 @@ use hg::{ dirstate::parsers::Timestamp, dirstate_tree::dispatch::DirstateMapMethods, + dirstate_tree::on_disk::DirstateV2ParseError, errors::HgError, revlog::Node, utils::files::normalize_case, utils::hg_path::{HgPath, HgPathBuf}, DirsMultiset, DirstateEntry, DirstateError, - DirstateMap as RustDirstateMap, DirstateMapError, DirstateParents, - EntryState, StateMapIter, + DirstateMap as RustDirstateMap, DirstateParents, EntryState, StateMapIter, }; // TODO @@ -90,7 +90,12 @@ default: Option = None ) -> PyResult> { let key = key.extract::(py)?; - match self.inner(py).borrow().get(HgPath::new(key.data(py))) { + match self + .inner(py) + .borrow() + .get(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e))? + { Some(entry) => { Ok(Some(make_dirstate_tuple(py, &entry)?)) }, @@ -124,7 +129,7 @@ size: size.extract(py)?, mtime: mtime.extract(py)?, }, - ).and(Ok(py.None())).or_else(|e: DirstateMapError| { + ).and(Ok(py.None())).or_else(|e: DirstateError| { Err(PyErr::new::(py, e.to_string())) }) } @@ -190,8 +195,10 @@ )) }) .collect(); - self.inner(py).borrow_mut() - .clear_ambiguous_times(files?, now.extract(py)?); + self.inner(py) + .borrow_mut() + .clear_ambiguous_times(files?, now.extract(py)?) + .map_err(|e| v2_error(py, e))?; Ok(py.None()) } @@ -199,6 +206,7 @@ let mut inner_shared = self.inner(py).borrow_mut(); let set = PySet::empty(py)?; for path in inner_shared.iter_other_parent_paths() { + let path = path.map_err(|e| v2_error(py, e))?; set.add(py, PyBytes::new(py, path.as_bytes()))?; } Ok(set.into_object()) @@ -210,28 +218,20 @@ def non_normal_entries_contains(&self, key: PyObject) -> PyResult { let key = key.extract::(py)?; - Ok(self - .inner(py) + self.inner(py) .borrow_mut() - .non_normal_entries_contains(HgPath::new(key.data(py)))) + .non_normal_entries_contains(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e)) } def non_normal_entries_display(&self) -> PyResult { - Ok( - PyString::new( - py, - &format!( - "NonNormalEntries: {}", - hg::utils::join_display( - self - .inner(py) - .borrow_mut() - .iter_non_normal_paths(), - ", " - ) - ) - ) - ) + let mut inner = self.inner(py).borrow_mut(); + let paths = inner + .iter_non_normal_paths() + .collect::, _>>() + .map_err(|e| v2_error(py, e))?; + let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", ")); + Ok(PyString::new(py, &formatted)) } def non_normal_entries_remove(&self, key: PyObject) -> PyResult { @@ -248,6 +248,7 @@ let ret = PyList::new(py, &[]); for filename in inner.non_normal_or_other_parent_paths() { + let filename = filename.map_err(|e| v2_error(py, e))?; let as_pystring = PyBytes::new(py, filename.as_bytes()); ret.append(py, as_pystring.into_object()); } @@ -320,7 +321,8 @@ def filefoldmapasdict(&self) -> PyResult { let dict = PyDict::new(py); - for (path, entry) in self.inner(py).borrow_mut().iter() { + for item in self.inner(py).borrow_mut().iter() { + let (path, entry) = item.map_err(|e| v2_error(py, e))?; if entry.state != EntryState::Removed { let key = normalize_case(path); let value = path; @@ -340,13 +342,21 @@ def __contains__(&self, key: PyObject) -> PyResult { let key = key.extract::(py)?; - Ok(self.inner(py).borrow().contains_key(HgPath::new(key.data(py)))) + self.inner(py) + .borrow() + .contains_key(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e)) } def __getitem__(&self, key: PyObject) -> PyResult { let key = key.extract::(py)?; let key = HgPath::new(key.data(py)); - match self.inner(py).borrow().get(key) { + match self + .inner(py) + .borrow() + .get(key) + .map_err(|e| v2_error(py, e))? + { Some(entry) => { Ok(make_dirstate_tuple(py, &entry)?) }, @@ -418,7 +428,8 @@ // TODO all copymap* methods, see docstring above def copymapcopy(&self) -> PyResult { let dict = PyDict::new(py); - for (key, value) in self.inner(py).borrow().copy_map_iter() { + for item in self.inner(py).borrow().copy_map_iter() { + let (key, value) = item.map_err(|e| v2_error(py, e))?; dict.set_item( py, PyBytes::new(py, key.as_bytes()), @@ -430,7 +441,12 @@ def copymapgetitem(&self, key: PyObject) -> PyResult { let key = key.extract::(py)?; - match self.inner(py).borrow().copy_map_get(HgPath::new(key.data(py))) { + match self + .inner(py) + .borrow() + .copy_map_get(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e))? + { Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())), None => Err(PyErr::new::( py, @@ -447,10 +463,10 @@ } def copymapcontains(&self, key: PyObject) -> PyResult { let key = key.extract::(py)?; - Ok(self - .inner(py) + self.inner(py) .borrow() - .copy_map_contains_key(HgPath::new(key.data(py)))) + .copy_map_contains_key(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e)) } def copymapget( &self, @@ -462,6 +478,7 @@ .inner(py) .borrow() .copy_map_get(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e))? { Some(copy) => Ok(Some( PyBytes::new(py, copy.as_bytes()).into_object(), @@ -476,10 +493,13 @@ ) -> PyResult { let key = key.extract::(py)?; let value = value.extract::(py)?; - self.inner(py).borrow_mut().copy_map_insert( - HgPathBuf::from_bytes(key.data(py)), - HgPathBuf::from_bytes(value.data(py)), - ); + self.inner(py) + .borrow_mut() + .copy_map_insert( + HgPathBuf::from_bytes(key.data(py)), + HgPathBuf::from_bytes(value.data(py)), + ) + .map_err(|e| v2_error(py, e))?; Ok(py.None()) } def copymappop( @@ -492,6 +512,7 @@ .inner(py) .borrow_mut() .copy_map_remove(HgPath::new(key.data(py))) + .map_err(|e| v2_error(py, e))? { Some(_) => Ok(None), None => Ok(default), @@ -525,15 +546,16 @@ } fn translate_key( py: Python, - res: (&HgPath, DirstateEntry), + res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>, ) -> PyResult> { - Ok(Some(PyBytes::new(py, res.0.as_bytes()))) + let (f, _entry) = res.map_err(|e| v2_error(py, e))?; + Ok(Some(PyBytes::new(py, f.as_bytes()))) } fn translate_key_value( py: Python, - res: (&HgPath, DirstateEntry), + res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>, ) -> PyResult> { - let (f, entry) = res; + let (f, entry) = res.map_err(|e| v2_error(py, e))?; Ok(Some(( PyBytes::new(py, f.as_bytes()), make_dirstate_tuple(py, &entry)?, @@ -562,3 +584,7 @@ Err(e) => Err(PyErr::new::(py, e.to_string())), } } + +pub(super) fn v2_error(py: Python<'_>, _: DirstateV2ParseError) -> PyErr { + PyErr::new::(py, "corrupted dirstate-v2") +}