rust/hg-core/src/revlog/revlog.rs
changeset 46443 43d63979a75e
parent 46433 4b381dbbf8b7
child 46744 b1f2c2b336ec
--- a/rust/hg-core/src/revlog/revlog.rs	Wed Jan 27 14:59:09 2021 +0100
+++ b/rust/hg-core/src/revlog/revlog.rs	Wed Jan 27 14:45:25 2021 +0100
@@ -13,25 +13,34 @@
 use super::index::Index;
 use super::node::{NodePrefix, NODE_BYTES_LENGTH, NULL_NODE};
 use super::nodemap;
-use super::nodemap::NodeMap;
+use super::nodemap::{NodeMap, NodeMapError};
 use super::nodemap_docket::NodeMapDocket;
 use super::patch;
+use crate::errors::HgError;
 use crate::repo::Repo;
 use crate::revlog::Revision;
 
+#[derive(derive_more::From)]
 pub enum RevlogError {
-    IoError(std::io::Error),
-    UnsuportedVersion(u16),
     InvalidRevision,
     /// Found more than one entry whose ID match the requested prefix
     AmbiguousPrefix,
-    Corrupted,
-    UnknowDataFormat(u8),
+    #[from]
+    Other(HgError),
 }
 
-impl From<bytes_cast::FromBytesError> for RevlogError {
-    fn from(_: bytes_cast::FromBytesError) -> Self {
-        RevlogError::Corrupted
+impl From<NodeMapError> for RevlogError {
+    fn from(error: NodeMapError) -> Self {
+        match error {
+            NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
+            NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(),
+        }
+    }
+}
+
+impl RevlogError {
+    fn corrupted() -> Self {
+        RevlogError::Other(HgError::corrupted("corrupted revlog"))
     }
 }
 
@@ -59,14 +68,12 @@
         data_path: Option<&Path>,
     ) -> Result<Self, RevlogError> {
         let index_path = index_path.as_ref();
-        let index_mmap = repo
-            .store_vfs()
-            .mmap_open(&index_path)
-            .map_err(RevlogError::IoError)?;
+        let index_mmap = repo.store_vfs().mmap_open(&index_path)?;
 
         let version = get_version(&index_mmap);
         if version != 1 {
-            return Err(RevlogError::UnsuportedVersion(version));
+            // A proper new version should have had a repo/store requirement.
+            return Err(RevlogError::corrupted());
         }
 
         let index = Index::new(Box::new(index_mmap))?;
@@ -80,10 +87,7 @@
                 None
             } else {
                 let data_path = data_path.unwrap_or(&default_data_path);
-                let data_mmap = repo
-                    .store_vfs()
-                    .mmap_open(data_path)
-                    .map_err(RevlogError::IoError)?;
+                let data_mmap = repo.store_vfs().mmap_open(data_path)?;
                 Some(Box::new(data_mmap))
             };
 
@@ -121,9 +125,7 @@
     ) -> Result<Revision, RevlogError> {
         if let Some(nodemap) = &self.nodemap {
             return nodemap
-                .find_bin(&self.index, node)
-                // TODO: propagate details of this error:
-                .map_err(|_| RevlogError::Corrupted)?
+                .find_bin(&self.index, node)?
                 .ok_or(RevlogError::InvalidRevision);
         }
 
@@ -136,7 +138,9 @@
         let mut found_by_prefix = None;
         for rev in (0..self.len() as Revision).rev() {
             let index_entry =
-                self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
+                self.index.get_entry(rev).ok_or(HgError::corrupted(
+                    "revlog references a revision not in the index",
+                ))?;
             if node == *index_entry.hash() {
                 return Ok(rev);
             }
@@ -167,8 +171,9 @@
         let mut delta_chain = vec![];
         while let Some(base_rev) = entry.base_rev {
             delta_chain.push(entry);
-            entry =
-                self.get_entry(base_rev).or(Err(RevlogError::Corrupted))?;
+            entry = self
+                .get_entry(base_rev)
+                .map_err(|_| RevlogError::corrupted())?;
         }
 
         // TODO do not look twice in the index
@@ -191,7 +196,7 @@
         ) {
             Ok(data)
         } else {
-            Err(RevlogError::Corrupted)
+            Err(RevlogError::corrupted())
         }
     }
 
@@ -301,7 +306,8 @@
             b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
             // zstd data.
             b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
-            format_type => Err(RevlogError::UnknowDataFormat(format_type)),
+            // A proper new format should have had a repo/store requirement.
+            _format_type => Err(RevlogError::corrupted()),
         }
     }
 
@@ -311,13 +317,13 @@
             let mut buf = Vec::with_capacity(self.compressed_len);
             decoder
                 .read_to_end(&mut buf)
-                .or(Err(RevlogError::Corrupted))?;
+                .map_err(|_| RevlogError::corrupted())?;
             Ok(buf)
         } else {
             let mut buf = vec![0; self.uncompressed_len];
             decoder
                 .read_exact(&mut buf)
-                .or(Err(RevlogError::Corrupted))?;
+                .map_err(|_| RevlogError::corrupted())?;
             Ok(buf)
         }
     }
@@ -326,14 +332,14 @@
         if self.is_delta() {
             let mut buf = Vec::with_capacity(self.compressed_len);
             zstd::stream::copy_decode(self.bytes, &mut buf)
-                .or(Err(RevlogError::Corrupted))?;
+                .map_err(|_| RevlogError::corrupted())?;
             Ok(buf)
         } else {
             let mut buf = vec![0; self.uncompressed_len];
             let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
-                .or(Err(RevlogError::Corrupted))?;
+                .map_err(|_| RevlogError::corrupted())?;
             if len != self.uncompressed_len {
-                Err(RevlogError::Corrupted)
+                Err(RevlogError::corrupted())
             } else {
                 Ok(buf)
             }