rust/hg-core/src/revlog/revlog.rs
branchstable
changeset 49373 455fce57e89e
parent 49238 13dfad0f9f7a
child 49375 6b04f702c501
equal deleted inserted replaced
49372:f8ec7b16c98f 49373:455fce57e89e
    47 
    47 
    48 impl From<NodeMapError> for RevlogError {
    48 impl From<NodeMapError> for RevlogError {
    49     fn from(error: NodeMapError) -> Self {
    49     fn from(error: NodeMapError) -> Self {
    50         match error {
    50         match error {
    51             NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
    51             NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
    52             NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(),
    52             NodeMapError::RevisionNotInIndex(rev) => RevlogError::corrupted(
    53         }
    53                 format!("nodemap point to revision {} not in index", rev),
    54     }
    54             ),
    55 }
    55         }
    56 
    56     }
    57 fn corrupted() -> HgError {
    57 }
    58     HgError::corrupted("corrupted revlog")
    58 
       
    59 fn corrupted<S: AsRef<str>>(context: S) -> HgError {
       
    60     HgError::corrupted(format!("corrupted revlog, {}", context.as_ref()))
    59 }
    61 }
    60 
    62 
    61 impl RevlogError {
    63 impl RevlogError {
    62     fn corrupted() -> Self {
    64     fn corrupted<S: AsRef<str>>(context: S) -> Self {
    63         RevlogError::Other(corrupted())
    65         RevlogError::Other(corrupted(context))
    64     }
    66     }
    65 }
    67 }
    66 
    68 
    67 /// Read only implementation of revlog.
    69 /// Read only implementation of revlog.
    68 pub struct Revlog {
    70 pub struct Revlog {
   327     /// should be reported as corruption, instead of e.g. "invalid revision"
   329     /// should be reported as corruption, instead of e.g. "invalid revision"
   328     fn get_entry_internal(
   330     fn get_entry_internal(
   329         &self,
   331         &self,
   330         rev: Revision,
   332         rev: Revision,
   331     ) -> Result<RevlogEntry, HgError> {
   333     ) -> Result<RevlogEntry, HgError> {
   332         return self.get_entry(rev).map_err(|_| corrupted());
   334         self.get_entry(rev)
       
   335             .map_err(|_| corrupted(format!("revision {} out of range", rev)))
   333     }
   336     }
   334 }
   337 }
   335 
   338 
   336 /// The revlog entry's bytes and the necessary informations to extract
   339 /// The revlog entry's bytes and the necessary informations to extract
   337 /// the entry's data.
   340 /// the entry's data.
   447             self.hash.as_bytes(),
   450             self.hash.as_bytes(),
   448             &data,
   451             &data,
   449         ) {
   452         ) {
   450             Ok(data)
   453             Ok(data)
   451         } else {
   454         } else {
   452             Err(corrupted())
   455             Err(corrupted(format!(
       
   456                 "hash check failed for revision {}",
       
   457                 self.rev
       
   458             )))
   453         }
   459         }
   454     }
   460     }
   455 
   461 
   456     pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> {
   462     pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> {
   457         let data = self.rawdata()?;
   463         let data = self.rawdata()?;
   476             // zlib (RFC 1950) data.
   482             // zlib (RFC 1950) data.
   477             b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
   483             b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
   478             // zstd data.
   484             // zstd data.
   479             b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
   485             b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
   480             // A proper new format should have had a repo/store requirement.
   486             // A proper new format should have had a repo/store requirement.
   481             _format_type => Err(corrupted()),
   487             format_type => Err(corrupted(format!(
       
   488                 "unknown compression header '{}'",
       
   489                 format_type
       
   490             ))),
   482         }
   491         }
   483     }
   492     }
   484 
   493 
   485     fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> {
   494     fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> {
   486         let mut decoder = ZlibDecoder::new(self.bytes);
   495         let mut decoder = ZlibDecoder::new(self.bytes);
   487         if self.is_delta() {
   496         if self.is_delta() {
   488             let mut buf = Vec::with_capacity(self.compressed_len as usize);
   497             let mut buf = Vec::with_capacity(self.compressed_len as usize);
   489             decoder.read_to_end(&mut buf).map_err(|_| corrupted())?;
   498             decoder
       
   499                 .read_to_end(&mut buf)
       
   500                 .map_err(|e| corrupted(e.to_string()))?;
   490             Ok(buf)
   501             Ok(buf)
   491         } else {
   502         } else {
   492             let cap = self.uncompressed_len.max(0) as usize;
   503             let cap = self.uncompressed_len.max(0) as usize;
   493             let mut buf = vec![0; cap];
   504             let mut buf = vec![0; cap];
   494             decoder.read_exact(&mut buf).map_err(|_| corrupted())?;
   505             decoder
       
   506                 .read_exact(&mut buf)
       
   507                 .map_err(|e| corrupted(e.to_string()))?;
   495             Ok(buf)
   508             Ok(buf)
   496         }
   509         }
   497     }
   510     }
   498 
   511 
   499     fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> {
   512     fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> {
   500         if self.is_delta() {
   513         if self.is_delta() {
   501             let mut buf = Vec::with_capacity(self.compressed_len as usize);
   514             let mut buf = Vec::with_capacity(self.compressed_len as usize);
   502             zstd::stream::copy_decode(self.bytes, &mut buf)
   515             zstd::stream::copy_decode(self.bytes, &mut buf)
   503                 .map_err(|_| corrupted())?;
   516                 .map_err(|e| corrupted(e.to_string()))?;
   504             Ok(buf)
   517             Ok(buf)
   505         } else {
   518         } else {
   506             let cap = self.uncompressed_len.max(0) as usize;
   519             let cap = self.uncompressed_len.max(0) as usize;
   507             let mut buf = vec![0; cap];
   520             let mut buf = vec![0; cap];
   508             let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
   521             let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
   509                 .map_err(|_| corrupted())?;
   522                 .map_err(|e| corrupted(e.to_string()))?;
   510             if len != self.uncompressed_len as usize {
   523             if len != self.uncompressed_len as usize {
   511                 Err(corrupted())
   524                 Err(corrupted("uncompressed length does not match"))
   512             } else {
   525             } else {
   513                 Ok(buf)
   526                 Ok(buf)
   514             }
   527             }
   515         }
   528         }
   516     }
   529     }