Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-core/src/revlog/manifest.rs @ 48391:10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
The Rust parser for the manifest file format is an iterator. Now every item
from that iterator is a `Result`, which makes error handling required
in multiple new places.
This makes better recovery on errors possible, compare to a run time panic.
Differential Revision: https://phab.mercurial-scm.org/D11771
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Tue, 23 Nov 2021 18:27:42 +0100 |
parents | 87e3f878e65f |
children | eb428010aad2 |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/manifest.rs Fri Nov 19 17:34:48 2021 +0100 +++ b/rust/hg-core/src/revlog/manifest.rs Tue Nov 23 18:27:42 2021 +0100 @@ -63,26 +63,28 @@ } /// Return an iterator over the files of the entry. - pub fn files(&self) -> impl Iterator<Item = &HgPath> { + pub fn files(&self) -> impl Iterator<Item = Result<&HgPath, HgError>> { self.lines().filter(|line| !line.is_empty()).map(|line| { - let pos = line - .iter() - .position(|x| x == &b'\0') - .expect("manifest line should contain \\0"); - HgPath::new(&line[..pos]) + let pos = + line.iter().position(|x| x == &b'\0').ok_or_else(|| { + HgError::corrupted("manifest line should contain \\0") + })?; + Ok(HgPath::new(&line[..pos])) }) } /// Return an iterator over the files of the entry. - pub fn files_with_nodes(&self) -> impl Iterator<Item = (&HgPath, &[u8])> { + pub fn files_with_nodes( + &self, + ) -> impl Iterator<Item = Result<(&HgPath, &[u8]), HgError>> { self.lines().filter(|line| !line.is_empty()).map(|line| { - let pos = line - .iter() - .position(|x| x == &b'\0') - .expect("manifest line should contain \\0"); + let pos = + line.iter().position(|x| x == &b'\0').ok_or_else(|| { + HgError::corrupted("manifest line should contain \\0") + })?; let hash_start = pos + 1; let hash_end = hash_start + 40; - (HgPath::new(&line[..pos]), &line[hash_start..hash_end]) + Ok((HgPath::new(&line[..pos]), &line[hash_start..hash_end])) }) } @@ -91,7 +93,8 @@ // TODO: use binary search instead of linear scan. This may involve // building (and caching) an index of the byte indicex of each manifest // line. - for (manifest_path, node) in self.files_with_nodes() { + for entry in self.files_with_nodes() { + let (manifest_path, node) = entry?; if manifest_path == path { return Ok(Some(Node::from_hex_for_repo(node)?)); }