59 &'a HgPath, |
59 &'a HgPath, |
60 &DirstateEntry, |
60 &DirstateEntry, |
61 Option<&'a HgPath>, |
61 Option<&'a HgPath>, |
62 ) -> Result<(), HgError>, |
62 ) -> Result<(), HgError>, |
63 ) -> Result<&'a DirstateParents, HgError> { |
63 ) -> Result<&'a DirstateParents, HgError> { |
64 let (parents, rest) = DirstateParents::from_bytes(contents) |
64 let mut entry_idx = 0; |
65 .map_err(|_| HgError::corrupted("Too little data for dirstate."))?; |
65 let original_len = contents.len(); |
|
66 let (parents, rest) = |
|
67 DirstateParents::from_bytes(contents).map_err(|_| { |
|
68 HgError::corrupted(format!( |
|
69 "Too little data for dirstate: {} bytes.", |
|
70 original_len |
|
71 )) |
|
72 })?; |
66 contents = rest; |
73 contents = rest; |
67 while !contents.is_empty() { |
74 while !contents.is_empty() { |
68 let (raw_entry, rest) = RawEntry::from_bytes(contents) |
75 let (raw_entry, rest) = RawEntry::from_bytes(contents) |
69 .map_err(|_| HgError::corrupted("Overflow in dirstate."))?; |
76 .map_err(|_| HgError::corrupted(format!( |
|
77 "dirstate corrupted: ran out of bytes at entry header {}, offset {}.", |
|
78 entry_idx, original_len-contents.len())))?; |
70 |
79 |
71 let entry = DirstateEntry::from_v1_data( |
80 let entry = DirstateEntry::from_v1_data( |
72 EntryState::try_from(raw_entry.state)?, |
81 EntryState::try_from(raw_entry.state)?, |
73 raw_entry.mode.get(), |
82 raw_entry.mode.get(), |
74 raw_entry.size.get(), |
83 raw_entry.size.get(), |
75 raw_entry.mtime.get(), |
84 raw_entry.mtime.get(), |
76 ); |
85 ); |
|
86 let filename_len = raw_entry.length.get() as usize; |
77 let (paths, rest) = |
87 let (paths, rest) = |
78 u8::slice_from_bytes(rest, raw_entry.length.get() as usize) |
88 u8::slice_from_bytes(rest, filename_len) |
79 .map_err(|_| HgError::corrupted("Overflow in dirstate."))?; |
89 .map_err(|_| |
|
90 HgError::corrupted(format!( |
|
91 "dirstate corrupted: ran out of bytes at entry {}, offset {} (expected {} bytes).", |
|
92 entry_idx, original_len-contents.len(), filename_len)) |
|
93 )?; |
80 |
94 |
81 // `paths` is either a single path, or two paths separated by a NULL |
95 // `paths` is either a single path, or two paths separated by a NULL |
82 // byte |
96 // byte |
83 let mut iter = paths.splitn(2, |&byte| byte == b'\0'); |
97 let mut iter = paths.splitn(2, |&byte| byte == b'\0'); |
84 let path = HgPath::new( |
98 let path = HgPath::new( |
85 iter.next().expect("splitn always yields at least one item"), |
99 iter.next().expect("splitn always yields at least one item"), |
86 ); |
100 ); |
87 let copy_source = iter.next().map(HgPath::new); |
101 let copy_source = iter.next().map(HgPath::new); |
88 each_entry(path, &entry, copy_source)?; |
102 each_entry(path, &entry, copy_source)?; |
89 |
103 |
|
104 entry_idx += 1; |
90 contents = rest; |
105 contents = rest; |
91 } |
106 } |
92 Ok(parents) |
107 Ok(parents) |
93 } |
108 } |
94 |
109 |