History

[commitgraph] Clean up `{file,graph}::verify::Error` types.

Get rid of `file::verify::EitherError` in favor of having `graph::verify::Error` manually copy file errors into the graph error object.

Conor Davis committed 6 years ago

Commit fa22cab1 parent 25711133 files · +64 −44Browse files

Showing the changes to git-commitgraph/src/file (1 of 3 files). Show all

Unified · Split

git-commitgraph/src/file/verify.rs+17−37
@@ -10,7 +10,7 @@ use std::convert::TryFrom; · 9 unmodified lines
1010 use std::path::Path;
1111
1212 #[derive(thiserror::Error, Debug)]
13−pub enum Error {
13+pub enum Error<E: std::error::Error + 'static> {
1414 #[error(transparent)]
1515 Commit(#[from] file::commit::Error),
1616 #[error("commit at file position {pos} has invalid ID {id}")]
@@ -26,24 +26,13 @@ pub enum Error { · 9 unmodified lines
2626 #[error("commit {id} has invalid generation {generation}")]
2727 Generation { generation: u32, id: owned::Id },
2828 #[error("checksum mismatch: expected {expected}, got {actual}")]
29− Mismatch { expected: owned::Id, actual: owned::Id },
29+ Mismatch { actual: owned::Id, expected: owned::Id },
30+ #[error("{0}")]
31+ Processor(#[source] E),
3032 #[error("commit {id} has invalid root tree ID {root_tree_id}")]
3133 RootTreeId { id: owned::Id, root_tree_id: owned::Id },
3234 }
3335
34−// This is a separate type to let `traverse`'s caller use the same error type for its result and its
35−// processor error type while also letting that error type contain file::verify::Error values.
36−// Is there a better way? Should the caller's error type just use boxes to avoid recursive type
37−// errors?
38−#[derive(thiserror::Error, Debug)]
39−pub enum EitherError<E1: std::error::Error + 'static, E2: std::error::Error + 'static> {
40− #[error(transparent)]
41− Internal(#[from] E1),
42− // Why can't I use #[from] here? Boo!
43− #[error("{0}")]
44− Processor(#[source] E2),
45−}
46−
4736 #[derive(Clone, Debug, Eq, PartialEq)]
4837 #[cfg_attr(feature = "serde1", derive(serde::Deserialize, serde::Serialize))]
4938 pub struct Outcome {
@@ -59,13 +48,14 @@ impl File { · 9 unmodified lines
5948 borrowed::Id::try_from(&self.data[self.data.len() - SHA1_SIZE..]).expect("file to be large enough for a hash")
6049 }
6150
62− pub fn traverse<'a, E, Processor>(&'a self, mut processor: Processor) -> Result<Outcome, EitherError<Error, E>>
51+ pub fn traverse<'a, E, Processor>(&'a self, mut processor: Processor) -> Result<Outcome, Error<E>>
6352 where
6453 E: std::error::Error + 'static,
6554 Processor: FnMut(&file::Commit<'a>) -> Result<(), E>,
6655 {
67− self.verify_checksum()?;
68− verify_split_chain_filename_hash(&self.path, self.checksum())?;
56+ self.verify_checksum()
57+ .map_err(|(actual, expected)| Error::Mismatch { actual, expected })?;
58+ verify_split_chain_filename_hash(&self.path, self.checksum()).map_err(Error::Filename)?;
6959
7060 // This probably belongs in borrowed::Id itself?
7161 let null_id = borrowed::Id::from(&[0u8; SHA1_SIZE]);
@@ -86,32 +76,28 @@ impl File { · 14 unmodified lines
8676 return Err(Error::CommitId {
8777 pos: commit.position(),
8878 id: commit.id().into(),
89− }
90− .into());
79+ });
9180 }
9281 return Err(Error::CommitsOutOfOrder {
9382 pos: commit.position(),
9483 id: commit.id().into(),
9584 predecessor_id: prev_id.into(),
96− }
97− .into());
85+ });
9886 }
9987 if commit.root_tree_id() == null_id {
10088 return Err(Error::RootTreeId {
10189 id: commit.id().into(),
10290 root_tree_id: commit.root_tree_id().into(),
103− }
104− .into());
91+ });
10592 }
10693 if commit.generation() > GENERATION_NUMBER_MAX {
10794 return Err(Error::Generation {
10895 generation: commit.generation(),
10996 id: commit.id().into(),
110− }
111− .into());
97+ });
11298 }
11399
114− processor(&commit).map_err(EitherError::Processor)?;
100+ processor(&commit).map_err(Error::Processor)?;
115101
116102 stats.max_generation = max(stats.max_generation, commit.generation());
117103 stats.min_generation = min(stats.min_generation, commit.generation());
@@ -130,7 +116,7 @@ impl File { · 12 unmodified lines
130116 Ok(stats)
131117 }
132118
133− pub fn verify_checksum(&self) -> Result<owned::Id, Error> {
119+ pub fn verify_checksum(&self) -> Result<owned::Id, (owned::Id, owned::Id)> {
134120 // TODO: Use/copy git_odb::hash::bytes_of_file.
135121 let data_len_without_trailer = self.data.len() - SHA1_SIZE;
136122 let mut hasher = git_features::hash::Sha1::default();
@@ -141,17 +127,14 @@ impl File { · 4 unmodified lines
141127 if actual.to_borrowed() == expected {
142128 Ok(actual)
143129 } else {
144− Err(Error::Mismatch {
145− actual,
146− expected: expected.into(),
147− })
130+ Err((actual, expected.into()))
148131 }
149132 }
150133 }
151134
152135 /// If the given path's filename matches "graph-{hash}.graph", check that `hash` matches the
153136 /// expected hash.
154−fn verify_split_chain_filename_hash(path: impl AsRef<Path>, expected: borrowed::Id<'_>) -> Result<(), Error> {
137+fn verify_split_chain_filename_hash(path: impl AsRef<Path>, expected: borrowed::Id<'_>) -> Result<(), String> {
155138 let path = path.as_ref();
156139 path.file_name()
157140 .and_then(|filename| filename.to_str())
@@ -159,9 +142,6 @@ fn verify_split_chain_filename_hash(path: impl AsRef<Path>, expected: borrowed:: · 1 unmodified line
159142 .and_then(|stem| stem.strip_prefix("graph-"))
160143 .map_or(Ok(()), |hex| match owned::Id::from_40_bytes_in_hex(hex.as_bytes()) {
161144 Ok(actual) if actual.to_borrowed() == expected => Ok(()),
162− _ => Err(Error::Filename(format!(
163− "graph-{}.graph",
164− expected.to_sha1_hex().as_bstr()
165− ))),
145+ _ => Err(format!("graph-{}.graph", expected.to_sha1_hex().as_bstr())),
166146 })
167147 }