rust-index: check that the entry bytes are the same in both indexes
authorRaphaël Gomès <rgomes@octobus.net>
Thu, 02 Nov 2023 11:16:13 +0100
changeset 51224 7434747343ab
parent 51223 16d477bb0078
child 51225 297fa956b6c4
rust-index: check that the entry bytes are the same in both indexes This is a temporary measure to show that both the Rust and C indexes are kept in sync. Comes with some related documentation precisions. For comparison of error cases, see `index_entry_binary()` in `revlog.c`.
rust/hg-core/src/revlog/index.rs
rust/hg-core/src/revlog/mod.rs
rust/hg-cpython/src/revlog.rs
--- a/rust/hg-core/src/revlog/index.rs	Sat Sep 30 16:15:56 2023 +0200
+++ b/rust/hg-core/src/revlog/index.rs	Thu Nov 02 11:16:13 2023 +0100
@@ -366,8 +366,11 @@
         self.len() == 0
     }
 
-    /// Return the index entry corresponding to the given revision if it
-    /// exists.
+    /// Return the index entry corresponding to the given revision or `None`
+    /// for [`NULL_REVISION`]
+    ///
+    /// The specified revision being of the checked type, it always exists
+    /// if it was validated by this index.
     pub fn get_entry(&self, rev: Revision) -> Option<IndexEntry> {
         if rev == NULL_REVISION {
             return None;
@@ -379,6 +382,21 @@
         })
     }
 
+    /// Return the binary content of the index entry for the given revision
+    ///
+    /// See [get_entry()](`Self::get_entry()`) for cases when `None` is
+    /// returned.
+    pub fn entry_binary(&self, rev: Revision) -> Option<&[u8]> {
+        self.get_entry(rev).map(|e| {
+            let bytes = e.as_bytes();
+            if rev.0 == 0 {
+                &bytes[4..]
+            } else {
+                bytes
+            }
+        })
+    }
+
     fn get_entry_inline(
         &self,
         rev: Revision,
@@ -543,6 +561,10 @@
     pub fn hash(&self) -> &'a Node {
         (&self.bytes[32..52]).try_into().unwrap()
     }
+
+    pub fn as_bytes(&self) -> &'a [u8] {
+        self.bytes
+    }
 }
 
 #[cfg(test)]
--- a/rust/hg-core/src/revlog/mod.rs	Sat Sep 30 16:15:56 2023 +0200
+++ b/rust/hg-core/src/revlog/mod.rs	Thu Nov 02 11:16:13 2023 +0100
@@ -148,7 +148,9 @@
     fn node(&self, rev: Revision) -> Option<&Node>;
 
     /// Return a [`Revision`] if `rev` is a valid revision number for this
-    /// index
+    /// index.
+    ///
+    /// [`NULL_REVISION`] is considered to be valid.
     fn check_revision(&self, rev: UncheckedRevision) -> Option<Revision> {
         let rev = rev.0;
 
--- a/rust/hg-cpython/src/revlog.rs	Sat Sep 30 16:15:56 2023 +0200
+++ b/rust/hg-cpython/src/revlog.rs	Thu Nov 02 11:16:13 2023 +0100
@@ -211,7 +211,16 @@
 
     /// return the raw binary string representing a revision
     def entry_binary(&self, *args, **kw) -> PyResult<PyObject> {
-        self.call_cindex(py, "entry_binary", args, kw)
+        let rindex = self.index(py).borrow();
+        let rev = UncheckedRevision(args.get_item(py, 0).extract(py)?);
+        let rust_bytes = rindex.check_revision(rev).and_then(
+            |r| rindex.entry_binary(r))
+            .ok_or_else(|| rev_not_in_index(py, rev))?;
+        let rust_res = PyBytes::new(py, rust_bytes).into_object();
+
+        let c_res = self.call_cindex(py, "entry_binary", args, kw)?;
+        assert_py_eq(py, "entry_binary", &rust_res, &c_res)?;
+        Ok(rust_res)
     }
 
     /// return a binary packed version of the header
@@ -615,7 +624,6 @@
     )
 }
 
-#[allow(dead_code)]
 fn rev_not_in_index(py: Python, rev: UncheckedRevision) -> PyErr {
     PyErr::new::<ValueError, _>(
         py,