Mercurial > public > mercurial-scm > hg
comparison rust/hg-cpython/src/parsers.rs @ 42748: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 |
comparison
equal
deleted
inserted
replaced
42747:760a7851e9ba | 42748:7cae6bc29ff9 |
---|---|
10 //! | 10 //! |
11 //! From Python, this will be seen as `mercurial.rustext.parsers` | 11 //! From Python, this will be seen as `mercurial.rustext.parsers` |
12 //! | 12 //! |
13 use cpython::{ | 13 use cpython::{ |
14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python, | 14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python, |
15 PythonObject, ToPyObject, | 15 ToPyObject, |
16 }; | 16 }; |
17 use hg::{ | 17 use hg::{ |
18 pack_dirstate, parse_dirstate, CopyVecEntry, DirstateEntry, | 18 pack_dirstate, parse_dirstate, utils::copy_into_array, DirstateEntry, |
19 DirstatePackError, DirstateParents, DirstateParseError, | 19 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE, |
20 }; | 20 }; |
21 use std::collections::HashMap; | 21 use std::collections::HashMap; |
22 | 22 |
23 use libc::c_char; | 23 use libc::c_char; |
24 | 24 |
25 use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate_vec}; | 25 use crate::dirstate::{decapsule_make_dirstate_tuple, extract_dirstate}; |
26 use std::time::Duration; | |
26 | 27 |
27 fn parse_dirstate_wrapper( | 28 fn parse_dirstate_wrapper( |
28 py: Python, | 29 py: Python, |
29 dmap: PyDict, | 30 dmap: PyDict, |
30 copymap: PyDict, | 31 copymap: PyDict, |
31 st: PyBytes, | 32 st: PyBytes, |
32 ) -> PyResult<PyTuple> { | 33 ) -> PyResult<PyTuple> { |
33 match parse_dirstate(st.data(py)) { | 34 let mut dirstate_map = HashMap::new(); |
34 Ok((parents, dirstate_vec, copies)) => { | 35 let mut copies = HashMap::new(); |
35 for (filename, entry) in dirstate_vec { | 36 |
37 match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) { | |
38 Ok(parents) => { | |
39 for (filename, entry) in dirstate_map { | |
36 dmap.set_item( | 40 dmap.set_item( |
37 py, | 41 py, |
38 PyBytes::new(py, &filename[..]), | 42 PyBytes::new(py, &filename), |
39 decapsule_make_dirstate_tuple(py)?( | 43 decapsule_make_dirstate_tuple(py)?( |
40 entry.state as c_char, | 44 entry.state as c_char, |
41 entry.mode, | 45 entry.mode, |
42 entry.size, | 46 entry.size, |
43 entry.mtime, | 47 entry.mtime, |
44 ), | 48 ), |
45 )?; | 49 )?; |
46 } | 50 } |
47 for CopyVecEntry { path, copy_path } in copies { | 51 for (path, copy_path) in copies { |
48 copymap.set_item( | 52 copymap.set_item( |
49 py, | 53 py, |
50 PyBytes::new(py, path), | 54 PyBytes::new(py, &path), |
51 PyBytes::new(py, copy_path), | 55 PyBytes::new(py, ©_path), |
52 )?; | 56 )?; |
53 } | 57 } |
54 Ok((PyBytes::new(py, parents.p1), PyBytes::new(py, parents.p2)) | 58 Ok( |
55 .to_py_object(py)) | 59 (PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2)) |
60 .to_py_object(py), | |
61 ) | |
56 } | 62 } |
57 Err(e) => Err(PyErr::new::<exc::ValueError, _>( | 63 Err(e) => Err(PyErr::new::<exc::ValueError, _>( |
58 py, | 64 py, |
59 match e { | 65 match e { |
60 DirstateParseError::TooLittleData => { | 66 DirstateParseError::TooLittleData => { |
62 } | 68 } |
63 DirstateParseError::Overflow => { | 69 DirstateParseError::Overflow => { |
64 "overflow in dirstate".to_string() | 70 "overflow in dirstate".to_string() |
65 } | 71 } |
66 DirstateParseError::CorruptedEntry(e) => e, | 72 DirstateParseError::CorruptedEntry(e) => e, |
73 DirstateParseError::Damaged => { | |
74 "dirstate appears to be damaged".to_string() | |
75 } | |
67 }, | 76 }, |
68 )), | 77 )), |
69 } | 78 } |
70 } | 79 } |
71 | 80 |
79 let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?; | 88 let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?; |
80 let p1: &[u8] = p1.data(py); | 89 let p1: &[u8] = p1.data(py); |
81 let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?; | 90 let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?; |
82 let p2: &[u8] = p2.data(py); | 91 let p2: &[u8] = p2.data(py); |
83 | 92 |
84 let dirstate_vec = extract_dirstate_vec(py, &dmap)?; | 93 let mut dirstate_map = extract_dirstate(py, &dmap)?; |
85 | 94 |
86 let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap | 95 let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap |
87 .items(py) | 96 .items(py) |
88 .iter() | 97 .iter() |
89 .map(|(key, value)| { | 98 .map(|(key, value)| { |
92 value.extract::<PyBytes>(py)?.data(py).to_owned(), | 101 value.extract::<PyBytes>(py)?.data(py).to_owned(), |
93 )) | 102 )) |
94 }) | 103 }) |
95 .collect(); | 104 .collect(); |
96 | 105 |
106 if p1.len() != PARENT_SIZE || p2.len() != PARENT_SIZE { | |
107 return Err(PyErr::new::<exc::ValueError, _>( | |
108 py, | |
109 "expected a 20-byte hash".to_string(), | |
110 )); | |
111 } | |
112 | |
97 match pack_dirstate( | 113 match pack_dirstate( |
98 &dirstate_vec, | 114 &mut dirstate_map, |
99 &copies?, | 115 &copies?, |
100 DirstateParents { p1, p2 }, | 116 DirstateParents { |
101 now.as_object().extract::<i32>(py)?, | 117 p1: copy_into_array(&p1), |
118 p2: copy_into_array(&p2), | |
119 }, | |
120 Duration::from_secs(now.value(py) as u64), | |
102 ) { | 121 ) { |
103 Ok((packed, new_dirstate_vec)) => { | 122 Ok(packed) => { |
104 for ( | 123 for ( |
105 filename, | 124 filename, |
106 DirstateEntry { | 125 DirstateEntry { |
107 state, | 126 state, |
108 mode, | 127 mode, |
109 size, | 128 size, |
110 mtime, | 129 mtime, |
111 }, | 130 }, |
112 ) in new_dirstate_vec | 131 ) in dirstate_map |
113 { | 132 { |
114 dmap.set_item( | 133 dmap.set_item( |
115 py, | 134 py, |
116 PyBytes::new(py, &filename[..]), | 135 PyBytes::new(py, &filename[..]), |
117 decapsule_make_dirstate_tuple(py)?( | 136 decapsule_make_dirstate_tuple(py)?( |