Show More
@@ -83,7 +83,7 b' impl TruncatedTimestamp {' | |||
|
83 | 83 | second_ambiguous, |
|
84 | 84 | }) |
|
85 | 85 | } else { |
|
86 | Err(DirstateV2ParseError) | |
|
86 | Err(DirstateV2ParseError::new("when reading datetime")) | |
|
87 | 87 | } |
|
88 | 88 | } |
|
89 | 89 |
@@ -463,7 +463,7 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||
|
463 | 463 | if let Some(data) = on_disk.get(..data_size) { |
|
464 | 464 | Ok(on_disk::read(data, metadata)?) |
|
465 | 465 | } else { |
|
466 | Err(DirstateV2ParseError.into()) | |
|
466 | Err(DirstateV2ParseError::new("not enough bytes on disk").into()) | |
|
467 | 467 | } |
|
468 | 468 | } |
|
469 | 469 |
@@ -175,11 +175,21 b' type OptPathSlice = PathSlice;' | |||
|
175 | 175 | /// |
|
176 | 176 | /// This should only happen if Mercurial is buggy or a repository is corrupted. |
|
177 | 177 | #[derive(Debug)] |
|
178 |
pub struct DirstateV2ParseError |
|
|
178 | pub struct DirstateV2ParseError { | |
|
179 | message: String, | |
|
180 | } | |
|
181 | ||
|
182 | impl DirstateV2ParseError { | |
|
183 | pub fn new<S: Into<String>>(message: S) -> Self { | |
|
184 | Self { | |
|
185 | message: message.into(), | |
|
186 | } | |
|
187 | } | |
|
188 | } | |
|
179 | 189 | |
|
180 | 190 | impl From<DirstateV2ParseError> for HgError { |
|
181 |
fn from( |
|
|
182 | HgError::corrupted("dirstate-v2 parse error") | |
|
191 | fn from(e: DirstateV2ParseError) -> Self { | |
|
192 | HgError::corrupted(format!("dirstate-v2 parse error: {}", e.message)) | |
|
183 | 193 | } |
|
184 | 194 | } |
|
185 | 195 | |
@@ -262,13 +272,16 b" impl<'on_disk> Docket<'on_disk> {" | |||
|
262 | 272 | pub fn read_docket( |
|
263 | 273 | on_disk: &[u8], |
|
264 | 274 | ) -> Result<Docket<'_>, DirstateV2ParseError> { |
|
265 | let (header, uuid) = | |
|
266 | DocketHeader::from_bytes(on_disk).map_err(|_| DirstateV2ParseError)?; | |
|
275 | let (header, uuid) = DocketHeader::from_bytes(on_disk).map_err(|e| { | |
|
276 | DirstateV2ParseError::new(format!("when reading docket, {}", e)) | |
|
277 | })?; | |
|
267 | 278 | let uuid_size = header.uuid_size as usize; |
|
268 | 279 | if header.marker == *V2_FORMAT_MARKER && uuid.len() == uuid_size { |
|
269 | 280 | Ok(Docket { header, uuid }) |
|
270 | 281 | } else { |
|
271 |
Err(DirstateV2ParseError |
|
|
282 | Err(DirstateV2ParseError::new( | |
|
283 | "invalid format marker or uuid size", | |
|
284 | )) | |
|
272 | 285 | } |
|
273 | 286 | } |
|
274 | 287 | |
@@ -281,14 +294,17 b" pub(super) fn read<'on_disk>(" | |||
|
281 | 294 | map.dirstate_version = DirstateVersion::V2; |
|
282 | 295 | return Ok(map); |
|
283 | 296 | } |
|
284 | let (meta, _) = TreeMetadata::from_bytes(metadata) | |
|
285 | .map_err(|_| DirstateV2ParseError)?; | |
|
297 | let (meta, _) = TreeMetadata::from_bytes(metadata).map_err(|e| { | |
|
298 | DirstateV2ParseError::new(format!("when parsing tree metadata, {}", e)) | |
|
299 | })?; | |
|
286 | 300 | let dirstate_map = DirstateMap { |
|
287 | 301 | on_disk, |
|
288 |
root: dirstate_map::ChildNodes::OnDisk( |
|
|
289 | on_disk, | |
|
290 | meta.root_nodes, | |
|
291 | )?), | |
|
302 | root: dirstate_map::ChildNodes::OnDisk( | |
|
303 | read_nodes(on_disk, meta.root_nodes).map_err(|mut e| { | |
|
304 | e.message = format!("{}, when reading root notes", e.message); | |
|
305 | e | |
|
306 | })?, | |
|
307 | ), | |
|
292 | 308 | nodes_with_entry_count: meta.nodes_with_entry_count.get(), |
|
293 | 309 | nodes_with_copy_source_count: meta.nodes_with_copy_source_count.get(), |
|
294 | 310 | ignore_patterns_hash: meta.ignore_patterns_hash, |
@@ -317,7 +333,7 b' impl Node {' | |||
|
317 | 333 | .expect("dirstate-v2 base_name_start out of bounds"); |
|
318 | 334 | Ok(start) |
|
319 | 335 | } else { |
|
320 | Err(DirstateV2ParseError) | |
|
336 | Err(DirstateV2ParseError::new("not enough bytes for base name")) | |
|
321 | 337 | } |
|
322 | 338 | } |
|
323 | 339 | |
@@ -571,11 +587,19 b' where' | |||
|
571 | 587 | // `&[u8]` cannot occupy the entire addess space. |
|
572 | 588 | let start = start.get().try_into().unwrap_or(std::usize::MAX); |
|
573 | 589 | let len = len.try_into().unwrap_or(std::usize::MAX); |
|
574 | on_disk | |
|
575 | .get(start..) | |
|
576 | .and_then(|bytes| T::slice_from_bytes(bytes, len).ok()) | |
|
590 | let bytes = match on_disk.get(start..) { | |
|
591 | Some(bytes) => bytes, | |
|
592 | None => { | |
|
593 | return Err(DirstateV2ParseError::new( | |
|
594 | "not enough bytes from disk", | |
|
595 | )) | |
|
596 | } | |
|
597 | }; | |
|
598 | T::slice_from_bytes(bytes, len) | |
|
599 | .map_err(|e| { | |
|
600 | DirstateV2ParseError::new(format!("when reading a slice, {}", e)) | |
|
601 | }) | |
|
577 | 602 | .map(|(slice, _rest)| slice) |
|
578 | .ok_or_else(|| DirstateV2ParseError) | |
|
579 | 603 | } |
|
580 | 604 | |
|
581 | 605 | pub(crate) fn for_each_tracked_path<'on_disk>( |
@@ -583,8 +607,9 b" pub(crate) fn for_each_tracked_path<'on_" | |||
|
583 | 607 | metadata: &[u8], |
|
584 | 608 | mut f: impl FnMut(&'on_disk HgPath), |
|
585 | 609 | ) -> Result<(), DirstateV2ParseError> { |
|
586 | let (meta, _) = TreeMetadata::from_bytes(metadata) | |
|
587 | .map_err(|_| DirstateV2ParseError)?; | |
|
610 | let (meta, _) = TreeMetadata::from_bytes(metadata).map_err(|e| { | |
|
611 | DirstateV2ParseError::new(format!("when parsing tree metadata, {}", e)) | |
|
612 | })?; | |
|
588 | 613 | fn recur<'on_disk>( |
|
589 | 614 | on_disk: &'on_disk [u8], |
|
590 | 615 | nodes: ChildNodes, |
General Comments 0
You need to be logged in to leave comments.
Login now