Mercurial > public > mercurial-scm > hg-stable
diff rust/hg-cpython/src/parsers.rs @ 42764:7cae6bc29ff9
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop
Both `parse_dirstate` and `pack_dirstate` can operate directly on the data
they're passed, which prevents the creation of intermediate data structures,
simplifies the function signatures and reduces boilerplate. They are exposed
directly to the Python for now, but a later patch will make use of them inside
`hg-core`.
Differential Revision: https://phab.mercurial-scm.org/D6628
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 09 Jul 2019 11:49:49 +0200 |
parents | 760a7851e9ba |
children | 7ceded4419a3 |
line wrap: on
line diff
--- 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, ©_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,