Show More
@@ -5,7 +5,9 b'' | |||||
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
6 | // GNU General Public License version 2 or any later version. |
|
6 | // GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
|
8 | use crate::DirstateParseError; | |||
8 | use std::collections::HashMap; |
|
9 | use std::collections::HashMap; | |
|
10 | use std::convert::TryFrom; | |||
9 |
|
11 | |||
10 | pub mod dirs_multiset; |
|
12 | pub mod dirs_multiset; | |
11 | pub mod parsers; |
|
13 | pub mod parsers; | |
@@ -21,7 +23,7 b' pub struct DirstateParents {' | |||||
21 | /// comes first. |
|
23 | /// comes first. | |
22 | #[derive(Debug, PartialEq, Copy, Clone)] |
|
24 | #[derive(Debug, PartialEq, Copy, Clone)] | |
23 | pub struct DirstateEntry { |
|
25 | pub struct DirstateEntry { | |
24 |
pub state: |
|
26 | pub state: EntryState, | |
25 | pub mode: i32, |
|
27 | pub mode: i32, | |
26 | pub mtime: i32, |
|
28 | pub mtime: i32, | |
27 | pub size: i32, |
|
29 | pub size: i32, | |
@@ -36,3 +38,42 b" pub enum DirsIterable<'a> {" | |||||
36 | Dirstate(&'a HashMap<Vec<u8>, DirstateEntry>), |
|
38 | Dirstate(&'a HashMap<Vec<u8>, DirstateEntry>), | |
37 | Manifest(&'a Vec<Vec<u8>>), |
|
39 | Manifest(&'a Vec<Vec<u8>>), | |
38 | } |
|
40 | } | |
|
41 | ||||
|
42 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |||
|
43 | pub enum EntryState { | |||
|
44 | Normal, | |||
|
45 | Added, | |||
|
46 | Removed, | |||
|
47 | Merged, | |||
|
48 | Unknown, | |||
|
49 | } | |||
|
50 | ||||
|
51 | impl TryFrom<u8> for EntryState { | |||
|
52 | type Error = DirstateParseError; | |||
|
53 | ||||
|
54 | fn try_from(value: u8) -> Result<Self, Self::Error> { | |||
|
55 | match value { | |||
|
56 | b'n' => Ok(EntryState::Normal), | |||
|
57 | b'a' => Ok(EntryState::Added), | |||
|
58 | b'r' => Ok(EntryState::Removed), | |||
|
59 | b'm' => Ok(EntryState::Merged), | |||
|
60 | b'?' => Ok(EntryState::Unknown), | |||
|
61 | _ => Err(DirstateParseError::CorruptedEntry(format!( | |||
|
62 | "Incorrect entry state {}", | |||
|
63 | value | |||
|
64 | ))), | |||
|
65 | } | |||
|
66 | } | |||
|
67 | } | |||
|
68 | ||||
|
69 | impl Into<u8> for EntryState { | |||
|
70 | fn into(self) -> u8 { | |||
|
71 | match self { | |||
|
72 | EntryState::Normal => b'n', | |||
|
73 | EntryState::Added => b'a', | |||
|
74 | EntryState::Removed => b'r', | |||
|
75 | EntryState::Merged => b'm', | |||
|
76 | EntryState::Unknown => b'?', | |||
|
77 | } | |||
|
78 | } | |||
|
79 | } |
@@ -8,7 +8,10 b'' | |||||
8 | //! A multiset of directory names. |
|
8 | //! A multiset of directory names. | |
9 | //! |
|
9 | //! | |
10 | //! Used to counts the references to directories in a manifest or dirstate. |
|
10 | //! Used to counts the references to directories in a manifest or dirstate. | |
11 | use crate::{utils::files, DirsIterable, DirstateEntry, DirstateMapError}; |
|
11 | use crate::{ | |
|
12 | dirstate::EntryState, utils::files, DirsIterable, DirstateEntry, | |||
|
13 | DirstateMapError, | |||
|
14 | }; | |||
12 | use std::collections::hash_map::{Entry, Iter}; |
|
15 | use std::collections::hash_map::{Entry, Iter}; | |
13 | use std::collections::HashMap; |
|
16 | use std::collections::HashMap; | |
14 |
|
17 | |||
@@ -21,7 +24,10 b' impl DirsMultiset {' | |||||
21 | /// Initializes the multiset from a dirstate or a manifest. |
|
24 | /// Initializes the multiset from a dirstate or a manifest. | |
22 | /// |
|
25 | /// | |
23 | /// If `skip_state` is provided, skips dirstate entries with equal state. |
|
26 | /// If `skip_state` is provided, skips dirstate entries with equal state. | |
24 | pub fn new(iterable: DirsIterable, skip_state: Option<i8>) -> Self { |
|
27 | pub fn new( | |
|
28 | iterable: DirsIterable, | |||
|
29 | skip_state: Option<EntryState>, | |||
|
30 | ) -> Self { | |||
25 | let mut multiset = DirsMultiset { |
|
31 | let mut multiset = DirsMultiset { | |
26 | inner: HashMap::new(), |
|
32 | inner: HashMap::new(), | |
27 | }; |
|
33 | }; | |
@@ -257,7 +263,7 b' mod tests {' | |||||
257 | ( |
|
263 | ( | |
258 | f.as_bytes().to_vec(), |
|
264 | f.as_bytes().to_vec(), | |
259 | DirstateEntry { |
|
265 | DirstateEntry { | |
260 |
state: |
|
266 | state: EntryState::Normal, | |
261 | mode: 0, |
|
267 | mode: 0, | |
262 | mtime: 0, |
|
268 | mtime: 0, | |
263 | size: 0, |
|
269 | size: 0, | |
@@ -290,28 +296,33 b' mod tests {' | |||||
290 | .map(|(k, v)| (k.as_bytes().to_vec(), *v)) |
|
296 | .map(|(k, v)| (k.as_bytes().to_vec(), *v)) | |
291 | .collect(); |
|
297 | .collect(); | |
292 |
|
298 | |||
293 | let new = DirsMultiset::new(Manifest(&input_vec), Some('n' as i8)); |
|
299 | let new = | |
|
300 | DirsMultiset::new(Manifest(&input_vec), Some(EntryState::Normal)); | |||
294 | let expected = DirsMultiset { |
|
301 | let expected = DirsMultiset { | |
295 | inner: expected_inner, |
|
302 | inner: expected_inner, | |
296 | }; |
|
303 | }; | |
297 | // Skip does not affect a manifest |
|
304 | // Skip does not affect a manifest | |
298 | assert_eq!(expected, new); |
|
305 | assert_eq!(expected, new); | |
299 |
|
306 | |||
300 | let input_map = |
|
307 | let input_map = [ | |
301 | [("a/", 'n'), ("a/b/", 'n'), ("a/c", 'r'), ("a/d/", 'm')] |
|
308 | ("a/", EntryState::Normal), | |
302 | .iter() |
|
309 | ("a/b/", EntryState::Normal), | |
303 | .map(|(f, state)| { |
|
310 | ("a/c", EntryState::Removed), | |
304 | ( |
|
311 | ("a/d/", EntryState::Merged), | |
305 | f.as_bytes().to_vec(), |
|
312 | ] | |
306 | DirstateEntry { |
|
313 | .iter() | |
307 | state: *state as i8, |
|
314 | .map(|(f, state)| { | |
308 | mode: 0, |
|
315 | ( | |
309 | mtime: 0, |
|
316 | f.as_bytes().to_vec(), | |
310 | size: 0, |
|
317 | DirstateEntry { | |
311 |
|
|
318 | state: *state, | |
312 |
|
|
319 | mode: 0, | |
313 |
|
|
320 | mtime: 0, | |
314 |
|
|
321 | size: 0, | |
|
322 | }, | |||
|
323 | ) | |||
|
324 | }) | |||
|
325 | .collect(); | |||
315 |
|
326 | |||
316 | // "a" incremented with "a/c" and "a/d/" |
|
327 | // "a" incremented with "a/c" and "a/d/" | |
317 | let expected_inner = [("", 1), ("a", 2), ("a/d", 1)] |
|
328 | let expected_inner = [("", 1), ("a", 2), ("a/d", 1)] | |
@@ -319,10 +330,12 b' mod tests {' | |||||
319 | .map(|(k, v)| (k.as_bytes().to_vec(), *v)) |
|
330 | .map(|(k, v)| (k.as_bytes().to_vec(), *v)) | |
320 | .collect(); |
|
331 | .collect(); | |
321 |
|
332 | |||
322 | let new = DirsMultiset::new(Dirstate(&input_map), Some('n' as i8)); |
|
333 | let new = | |
|
334 | DirsMultiset::new(Dirstate(&input_map), Some(EntryState::Normal)); | |||
323 | let expected = DirsMultiset { |
|
335 | let expected = DirsMultiset { | |
324 | inner: expected_inner, |
|
336 | inner: expected_inner, | |
325 | }; |
|
337 | }; | |
326 | assert_eq!(expected, new); |
|
338 | assert_eq!(expected, new); | |
327 | } |
|
339 | } | |
|
340 | ||||
328 | } |
|
341 | } |
@@ -4,12 +4,12 b'' | |||||
4 | // GNU General Public License version 2 or any later version. |
|
4 | // GNU General Public License version 2 or any later version. | |
5 |
|
5 | |||
6 | use crate::{ |
|
6 | use crate::{ | |
7 | dirstate::{CopyMap, StateMap}, |
|
7 | dirstate::{CopyMap, EntryState, StateMap}, | |
8 | utils::copy_into_array, |
|
8 | utils::copy_into_array, | |
9 | DirstateEntry, DirstatePackError, DirstateParents, DirstateParseError, |
|
9 | DirstateEntry, DirstatePackError, DirstateParents, DirstateParseError, | |
10 | }; |
|
10 | }; | |
11 | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; |
|
11 | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; | |
12 | use std::convert::TryInto; |
|
12 | use std::convert::{TryFrom, TryInto}; | |
13 | use std::io::Cursor; |
|
13 | use std::io::Cursor; | |
14 | use std::time::Duration; |
|
14 | use std::time::Duration; | |
15 |
|
15 | |||
@@ -42,7 +42,7 b' pub fn parse_dirstate(' | |||||
42 | let entry_bytes = &contents[curr_pos..]; |
|
42 | let entry_bytes = &contents[curr_pos..]; | |
43 |
|
43 | |||
44 | let mut cursor = Cursor::new(entry_bytes); |
|
44 | let mut cursor = Cursor::new(entry_bytes); | |
45 |
let state = cursor.read_ |
|
45 | let state = EntryState::try_from(cursor.read_u8()?)?; | |
46 | let mode = cursor.read_i32::<BigEndian>()?; |
|
46 | let mode = cursor.read_i32::<BigEndian>()?; | |
47 | let size = cursor.read_i32::<BigEndian>()?; |
|
47 | let size = cursor.read_i32::<BigEndian>()?; | |
48 | let mtime = cursor.read_i32::<BigEndian>()?; |
|
48 | let mtime = cursor.read_i32::<BigEndian>()?; | |
@@ -109,7 +109,7 b' pub fn pack_dirstate(' | |||||
109 | for (ref filename, entry) in state_map.iter() { |
|
109 | for (ref filename, entry) in state_map.iter() { | |
110 | let mut new_filename: Vec<u8> = filename.to_vec(); |
|
110 | let mut new_filename: Vec<u8> = filename.to_vec(); | |
111 | let mut new_mtime: i32 = entry.mtime; |
|
111 | let mut new_mtime: i32 = entry.mtime; | |
112 |
if entry.state == |
|
112 | if entry.state == EntryState::Normal && entry.mtime == now { | |
113 | // The file was last modified "simultaneously" with the current |
|
113 | // The file was last modified "simultaneously" with the current | |
114 | // write to dirstate (i.e. within the same second for file- |
|
114 | // write to dirstate (i.e. within the same second for file- | |
115 | // systems with a granularity of 1 sec). This commonly happens |
|
115 | // systems with a granularity of 1 sec). This commonly happens | |
@@ -134,7 +134,7 b' pub fn pack_dirstate(' | |||||
134 | new_filename.extend(copy); |
|
134 | new_filename.extend(copy); | |
135 | } |
|
135 | } | |
136 |
|
136 | |||
137 |
packed.write_ |
|
137 | packed.write_u8(entry.state.into())?; | |
138 | packed.write_i32::<BigEndian>(entry.mode)?; |
|
138 | packed.write_i32::<BigEndian>(entry.mode)?; | |
139 | packed.write_i32::<BigEndian>(entry.size)?; |
|
139 | packed.write_i32::<BigEndian>(entry.size)?; | |
140 | packed.write_i32::<BigEndian>(new_mtime)?; |
|
140 | packed.write_i32::<BigEndian>(new_mtime)?; | |
@@ -150,6 +150,7 b' pub fn pack_dirstate(' | |||||
150 |
|
150 | |||
151 | Ok(packed) |
|
151 | Ok(packed) | |
152 | } |
|
152 | } | |
|
153 | ||||
153 | #[cfg(test)] |
|
154 | #[cfg(test)] | |
154 | mod tests { |
|
155 | mod tests { | |
155 | use super::*; |
|
156 | use super::*; | |
@@ -178,7 +179,7 b' mod tests {' | |||||
178 | let expected_state_map: StateMap = [( |
|
179 | let expected_state_map: StateMap = [( | |
179 | b"f1".to_vec(), |
|
180 | b"f1".to_vec(), | |
180 | DirstateEntry { |
|
181 | DirstateEntry { | |
181 |
state: |
|
182 | state: EntryState::Normal, | |
182 | mode: 0o644, |
|
183 | mode: 0o644, | |
183 | size: 0, |
|
184 | size: 0, | |
184 | mtime: 791231220, |
|
185 | mtime: 791231220, | |
@@ -215,7 +216,7 b' mod tests {' | |||||
215 | let expected_state_map: StateMap = [( |
|
216 | let expected_state_map: StateMap = [( | |
216 | b"f1".to_vec(), |
|
217 | b"f1".to_vec(), | |
217 | DirstateEntry { |
|
218 | DirstateEntry { | |
218 |
state: |
|
219 | state: EntryState::Normal, | |
219 | mode: 0o644, |
|
220 | mode: 0o644, | |
220 | size: 0, |
|
221 | size: 0, | |
221 | mtime: 791231220, |
|
222 | mtime: 791231220, | |
@@ -253,7 +254,7 b' mod tests {' | |||||
253 | let mut state_map: StateMap = [( |
|
254 | let mut state_map: StateMap = [( | |
254 | b"f1".to_vec(), |
|
255 | b"f1".to_vec(), | |
255 | DirstateEntry { |
|
256 | DirstateEntry { | |
256 |
state: |
|
257 | state: EntryState::Normal, | |
257 | mode: 0o644, |
|
258 | mode: 0o644, | |
258 | size: 0, |
|
259 | size: 0, | |
259 | mtime: 791231220, |
|
260 | mtime: 791231220, | |
@@ -293,7 +294,7 b' mod tests {' | |||||
293 | ( |
|
294 | ( | |
294 | b"f1".to_vec(), |
|
295 | b"f1".to_vec(), | |
295 | DirstateEntry { |
|
296 | DirstateEntry { | |
296 |
state: |
|
297 | state: EntryState::Normal, | |
297 | mode: 0o644, |
|
298 | mode: 0o644, | |
298 | size: 0, |
|
299 | size: 0, | |
299 | mtime: 791231220, |
|
300 | mtime: 791231220, | |
@@ -302,7 +303,7 b' mod tests {' | |||||
302 | ( |
|
303 | ( | |
303 | b"f2".to_vec(), |
|
304 | b"f2".to_vec(), | |
304 | DirstateEntry { |
|
305 | DirstateEntry { | |
305 |
state: |
|
306 | state: EntryState::Merged, | |
306 | mode: 0o777, |
|
307 | mode: 0o777, | |
307 | size: 1000, |
|
308 | size: 1000, | |
308 | mtime: 791231220, |
|
309 | mtime: 791231220, | |
@@ -311,7 +312,7 b' mod tests {' | |||||
311 | ( |
|
312 | ( | |
312 | b"f3".to_vec(), |
|
313 | b"f3".to_vec(), | |
313 | DirstateEntry { |
|
314 | DirstateEntry { | |
314 |
state: |
|
315 | state: EntryState::Removed, | |
315 | mode: 0o644, |
|
316 | mode: 0o644, | |
316 | size: 234553, |
|
317 | size: 234553, | |
317 | mtime: 791231220, |
|
318 | mtime: 791231220, | |
@@ -320,7 +321,7 b' mod tests {' | |||||
320 | ( |
|
321 | ( | |
321 | b"f4\xF6".to_vec(), |
|
322 | b"f4\xF6".to_vec(), | |
322 | DirstateEntry { |
|
323 | DirstateEntry { | |
323 |
state: |
|
324 | state: EntryState::Added, | |
324 | mode: 0o644, |
|
325 | mode: 0o644, | |
325 | size: -1, |
|
326 | size: -1, | |
326 | mtime: -1, |
|
327 | mtime: -1, | |
@@ -362,7 +363,7 b' mod tests {' | |||||
362 | let mut state_map: StateMap = [( |
|
363 | let mut state_map: StateMap = [( | |
363 | b"f1".to_vec(), |
|
364 | b"f1".to_vec(), | |
364 | DirstateEntry { |
|
365 | DirstateEntry { | |
365 |
state: |
|
366 | state: EntryState::Normal, | |
366 | mode: 0o644, |
|
367 | mode: 0o644, | |
367 | size: 0, |
|
368 | size: 0, | |
368 | mtime: 15000000, |
|
369 | mtime: 15000000, | |
@@ -397,7 +398,7 b' mod tests {' | |||||
397 | [( |
|
398 | [( | |
398 | b"f1".to_vec(), |
|
399 | b"f1".to_vec(), | |
399 | DirstateEntry { |
|
400 | DirstateEntry { | |
400 |
state: |
|
401 | state: EntryState::Normal, | |
401 | mode: 0o644, |
|
402 | mode: 0o644, | |
402 | size: 0, |
|
403 | size: 0, | |
403 | mtime: -1 |
|
404 | mtime: -1 |
@@ -11,7 +11,8 b' pub mod testing; // unconditionally buil' | |||||
11 | pub use dirstate::{ |
|
11 | pub use dirstate::{ | |
12 | dirs_multiset::DirsMultiset, |
|
12 | dirs_multiset::DirsMultiset, | |
13 | parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE}, |
|
13 | parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE}, | |
14 |
CopyMap, DirsIterable, DirstateEntry, DirstateParents, State |
|
14 | CopyMap, DirsIterable, DirstateEntry, DirstateParents, EntryState, | |
|
15 | StateMap, | |||
15 | }; |
|
16 | }; | |
16 | mod filepatterns; |
|
17 | mod filepatterns; | |
17 | pub mod utils; |
|
18 | pub mod utils; | |
@@ -62,6 +63,24 b' pub enum DirstateParseError {' | |||||
62 | Damaged, |
|
63 | Damaged, | |
63 | } |
|
64 | } | |
64 |
|
65 | |||
|
66 | impl From<std::io::Error> for DirstateParseError { | |||
|
67 | fn from(e: std::io::Error) -> Self { | |||
|
68 | DirstateParseError::CorruptedEntry(e.to_string()) | |||
|
69 | } | |||
|
70 | } | |||
|
71 | ||||
|
72 | impl ToString for DirstateParseError { | |||
|
73 | fn to_string(&self) -> String { | |||
|
74 | use crate::DirstateParseError::*; | |||
|
75 | match self { | |||
|
76 | TooLittleData => "Too little data for dirstate.".to_string(), | |||
|
77 | Overflow => "Overflow in dirstate.".to_string(), | |||
|
78 | CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e), | |||
|
79 | Damaged => "Dirstate appears to be damaged.".to_string(), | |||
|
80 | } | |||
|
81 | } | |||
|
82 | } | |||
|
83 | ||||
65 | #[derive(Debug, PartialEq)] |
|
84 | #[derive(Debug, PartialEq)] | |
66 | pub enum DirstatePackError { |
|
85 | pub enum DirstatePackError { | |
67 | CorruptedEntry(String), |
|
86 | CorruptedEntry(String), | |
@@ -69,21 +88,33 b' pub enum DirstatePackError {' | |||||
69 | BadSize(usize, usize), |
|
88 | BadSize(usize, usize), | |
70 | } |
|
89 | } | |
71 |
|
90 | |||
|
91 | impl From<std::io::Error> for DirstatePackError { | |||
|
92 | fn from(e: std::io::Error) -> Self { | |||
|
93 | DirstatePackError::CorruptedEntry(e.to_string()) | |||
|
94 | } | |||
|
95 | } | |||
72 | #[derive(Debug, PartialEq)] |
|
96 | #[derive(Debug, PartialEq)] | |
73 | pub enum DirstateMapError { |
|
97 | pub enum DirstateMapError { | |
74 | PathNotFound(Vec<u8>), |
|
98 | PathNotFound(Vec<u8>), | |
75 | EmptyPath, |
|
99 | EmptyPath, | |
76 | } |
|
100 | } | |
77 |
|
101 | |||
78 | impl From<std::io::Error> for DirstatePackError { |
|
102 | pub enum DirstateError { | |
79 | fn from(e: std::io::Error) -> Self { |
|
103 | Parse(DirstateParseError), | |
80 | DirstatePackError::CorruptedEntry(e.to_string()) |
|
104 | Pack(DirstatePackError), | |
|
105 | Map(DirstateMapError), | |||
|
106 | IO(std::io::Error), | |||
|
107 | } | |||
|
108 | ||||
|
109 | impl From<DirstateParseError> for DirstateError { | |||
|
110 | fn from(e: DirstateParseError) -> Self { | |||
|
111 | DirstateError::Parse(e) | |||
81 | } |
|
112 | } | |
82 | } |
|
113 | } | |
83 |
|
114 | |||
84 |
impl From< |
|
115 | impl From<DirstatePackError> for DirstateError { | |
85 |
fn from(e: |
|
116 | fn from(e: DirstatePackError) -> Self { | |
86 | DirstateParseError::CorruptedEntry(e.to_string()) |
|
117 | DirstateError::Pack(e) | |
87 | } |
|
118 | } | |
88 | } |
|
119 | } | |
89 |
|
120 | |||
@@ -103,3 +134,15 b' impl From<std::io::Error> for PatternFil' | |||||
103 | PatternFileError::IO(e) |
|
134 | PatternFileError::IO(e) | |
104 | } |
|
135 | } | |
105 | } |
|
136 | } | |
|
137 | ||||
|
138 | impl From<DirstateMapError> for DirstateError { | |||
|
139 | fn from(e: DirstateMapError) -> Self { | |||
|
140 | DirstateError::Map(e) | |||
|
141 | } | |||
|
142 | } | |||
|
143 | ||||
|
144 | impl From<std::io::Error> for DirstateError { | |||
|
145 | fn from(e: std::io::Error) -> Self { | |||
|
146 | DirstateError::IO(e) | |||
|
147 | } | |||
|
148 | } |
@@ -12,14 +12,16 b'' | |||||
12 | mod dirs_multiset; |
|
12 | mod dirs_multiset; | |
13 | use crate::dirstate::dirs_multiset::Dirs; |
|
13 | use crate::dirstate::dirs_multiset::Dirs; | |
14 | use cpython::{ |
|
14 | use cpython::{ | |
15 |
PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, |
|
15 | exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, | |
|
16 | Python, | |||
16 | }; |
|
17 | }; | |
17 | use hg::{DirstateEntry, StateMap}; |
|
18 | use hg::{DirstateEntry, DirstateParseError, EntryState, StateMap}; | |
18 | use libc::{c_char, c_int}; |
|
19 | use libc::{c_char, c_int}; | |
19 | #[cfg(feature = "python27")] |
|
20 | #[cfg(feature = "python27")] | |
20 | use python27_sys::PyCapsule_Import; |
|
21 | use python27_sys::PyCapsule_Import; | |
21 | #[cfg(feature = "python3")] |
|
22 | #[cfg(feature = "python3")] | |
22 | use python3_sys::PyCapsule_Import; |
|
23 | use python3_sys::PyCapsule_Import; | |
|
24 | use std::convert::TryFrom; | |||
23 | use std::ffi::CStr; |
|
25 | use std::ffi::CStr; | |
24 | use std::mem::transmute; |
|
26 | use std::mem::transmute; | |
25 |
|
27 | |||
@@ -60,7 +62,11 b' pub fn extract_dirstate(py: Python, dmap' | |||||
60 | .map(|(filename, stats)| { |
|
62 | .map(|(filename, stats)| { | |
61 | let stats = stats.extract::<PySequence>(py)?; |
|
63 | let stats = stats.extract::<PySequence>(py)?; | |
62 | let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?; |
|
64 | let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?; | |
63 |
let state = state.data(py)[0] |
|
65 | let state = EntryState::try_from(state.data(py)[0]).map_err( | |
|
66 | |e: DirstateParseError| { | |||
|
67 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
68 | }, | |||
|
69 | )?; | |||
64 | let mode = stats.get_item(py, 1)?.extract(py)?; |
|
70 | let mode = stats.get_item(py, 1)?.extract(py)?; | |
65 | let size = stats.get_item(py, 2)?.extract(py)?; |
|
71 | let size = stats.get_item(py, 2)?.extract(py)?; | |
66 | let mtime = stats.get_item(py, 3)?.extract(py)?; |
|
72 | let mtime = stats.get_item(py, 3)?.extract(py)?; |
@@ -16,7 +16,11 b' use cpython::{' | |||||
16 | }; |
|
16 | }; | |
17 |
|
17 | |||
18 | use crate::dirstate::extract_dirstate; |
|
18 | use crate::dirstate::extract_dirstate; | |
19 | use hg::{DirsIterable, DirsMultiset, DirstateMapError}; |
|
19 | use hg::{ | |
|
20 | DirsIterable, DirsMultiset, DirstateMapError, DirstateParseError, | |||
|
21 | EntryState, | |||
|
22 | }; | |||
|
23 | use std::convert::TryInto; | |||
20 |
|
24 | |||
21 | py_class!(pub class Dirs |py| { |
|
25 | py_class!(pub class Dirs |py| { | |
22 | data dirs_map: RefCell<DirsMultiset>; |
|
26 | data dirs_map: RefCell<DirsMultiset>; | |
@@ -28,9 +32,15 b' py_class!(pub class Dirs |py| {' | |||||
28 | map: PyObject, |
|
32 | map: PyObject, | |
29 | skip: Option<PyObject> = None |
|
33 | skip: Option<PyObject> = None | |
30 | ) -> PyResult<Self> { |
|
34 | ) -> PyResult<Self> { | |
31 |
let mut skip_state: Option< |
|
35 | let mut skip_state: Option<EntryState> = None; | |
32 | if let Some(skip) = skip { |
|
36 | if let Some(skip) = skip { | |
33 | skip_state = Some(skip.extract::<PyBytes>(py)?.data(py)[0] as i8); |
|
37 | skip_state = Some( | |
|
38 | skip.extract::<PyBytes>(py)?.data(py)[0] | |||
|
39 | .try_into() | |||
|
40 | .map_err(|e: DirstateParseError| { | |||
|
41 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |||
|
42 | })?, | |||
|
43 | ); | |||
34 | } |
|
44 | } | |
35 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { |
|
45 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | |
36 | let dirstate = extract_dirstate(py, &map)?; |
|
46 | let dirstate = extract_dirstate(py, &map)?; |
@@ -37,11 +37,17 b' fn parse_dirstate_wrapper(' | |||||
37 | match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) { |
|
37 | match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) { | |
38 | Ok(parents) => { |
|
38 | Ok(parents) => { | |
39 | for (filename, entry) in dirstate_map { |
|
39 | for (filename, entry) in dirstate_map { | |
|
40 | // Explicitly go through u8 first, then cast to | |||
|
41 | // platform-specific `c_char` because Into<u8> has a specific | |||
|
42 | // implementation while `as c_char` would just do a naive enum | |||
|
43 | // cast. | |||
|
44 | let state: u8 = entry.state.into(); | |||
|
45 | ||||
40 | dmap.set_item( |
|
46 | dmap.set_item( | |
41 | py, |
|
47 | py, | |
42 | PyBytes::new(py, &filename), |
|
48 | PyBytes::new(py, &filename), | |
43 | decapsule_make_dirstate_tuple(py)?( |
|
49 | decapsule_make_dirstate_tuple(py)?( | |
44 |
|
|
50 | state as c_char, | |
45 | entry.mode, |
|
51 | entry.mode, | |
46 | entry.size, |
|
52 | entry.size, | |
47 | entry.mtime, |
|
53 | entry.mtime, | |
@@ -130,6 +136,11 b' fn pack_dirstate_wrapper(' | |||||
130 | }, |
|
136 | }, | |
131 | ) in dirstate_map |
|
137 | ) in dirstate_map | |
132 | { |
|
138 | { | |
|
139 | // Explicitly go through u8 first, then cast to | |||
|
140 | // platform-specific `c_char` because Into<u8> has a specific | |||
|
141 | // implementation while `as c_char` would just do a naive enum | |||
|
142 | // cast. | |||
|
143 | let state: u8 = state.into(); | |||
133 | dmap.set_item( |
|
144 | dmap.set_item( | |
134 | py, |
|
145 | py, | |
135 | PyBytes::new(py, &filename[..]), |
|
146 | PyBytes::new(py, &filename[..]), |
General Comments 0
You need to be logged in to leave comments.
Login now