rust/hg-cpython/src/parsers.rs
changeset 42748 7cae6bc29ff9
parent 42747 760a7851e9ba
child 42749 7ceded4419a3
--- a/rust/hg-cpython/src/parsers.rs	Wed Jul 10 10:16:28 2019 +0200
+++ b/rust/hg-cpython/src/parsers.rs	Tue Jul 09 11:49:49 2019 +0200
@@ -12,17 +12,18 @@
 //!
 use cpython::{
     exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
-    PythonObject, ToPyObject,
+    ToPyObject,
 };
 use hg::{
-    pack_dirstate, parse_dirstate, CopyVecEntry, DirstateEntry,
-    DirstatePackError, DirstateParents, DirstateParseError,
+    pack_dirstate, parse_dirstate, utils::copy_into_array, DirstateEntry,
+    DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE,
 };
 use std::collections::HashMap;
 
 use libc::c_char;
 
-use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate_vec};
+use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate};
+use std::time::Duration;
 
 fn parse_dirstate_wrapper(
     py: Python,
@@ -30,12 +31,15 @@
     copymap: PyDict,
     st: PyBytes,
 ) -> PyResult<PyTuple> {
-    match parse_dirstate(st.data(py)) {
-        Ok((parents, dirstate_vec, copies)) => {
-            for (filename, entry) in dirstate_vec {
+    let mut dirstate_map = HashMap::new();
+    let mut copies = HashMap::new();
+
+    match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) {
+        Ok(parents) => {
+            for (filename, entry) in dirstate_map {
                 dmap.set_item(
                     py,
-                    PyBytes::new(py, &filename[..]),
+                    PyBytes::new(py, &filename),
                     decapsule_make_dirstate_tuple(py)?(
                         entry.state as c_char,
                         entry.mode,
@@ -44,15 +48,17 @@
                     ),
                 )?;
             }
-            for CopyVecEntry { path, copy_path } in copies {
+            for (path, copy_path) in copies {
                 copymap.set_item(
                     py,
-                    PyBytes::new(py, path),
-                    PyBytes::new(py, copy_path),
+                    PyBytes::new(py, &path),
+                    PyBytes::new(py, &copy_path),
                 )?;
             }
-            Ok((PyBytes::new(py, parents.p1), PyBytes::new(py, parents.p2))
-                .to_py_object(py))
+            Ok(
+                (PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2))
+                    .to_py_object(py),
+            )
         }
         Err(e) => Err(PyErr::new::<exc::ValueError, _>(
             py,
@@ -64,6 +70,9 @@
                     "overflow in dirstate".to_string()
                 }
                 DirstateParseError::CorruptedEntry(e) => e,
+                DirstateParseError::Damaged => {
+                    "dirstate appears to be damaged".to_string()
+                }
             },
         )),
     }
@@ -81,7 +90,7 @@
     let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?;
     let p2: &[u8] = p2.data(py);
 
-    let dirstate_vec = extract_dirstate_vec(py, &dmap)?;
+    let mut dirstate_map = extract_dirstate(py, &dmap)?;
 
     let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap
         .items(py)
@@ -94,13 +103,23 @@
         })
         .collect();
 
+    if p1.len() != PARENT_SIZE || p2.len() != PARENT_SIZE {
+        return Err(PyErr::new::<exc::ValueError, _>(
+            py,
+            "expected a 20-byte hash".to_string(),
+        ));
+    }
+
     match pack_dirstate(
-        &dirstate_vec,
+        &mut dirstate_map,
         &copies?,
-        DirstateParents { p1, p2 },
-        now.as_object().extract::<i32>(py)?,
+        DirstateParents {
+            p1: copy_into_array(&p1),
+            p2: copy_into_array(&p2),
+        },
+        Duration::from_secs(now.value(py) as u64),
     ) {
-        Ok((packed, new_dirstate_vec)) => {
+        Ok(packed) => {
             for (
                 filename,
                 DirstateEntry {
@@ -109,7 +128,7 @@
                     size,
                     mtime,
                 },
-            ) in new_dirstate_vec
+            ) in dirstate_map
             {
                 dmap.set_item(
                     py,