Show More
@@ -29,5 +29,5 b' pub fn debug_data(' | |||||
29 | let rev = |
|
29 | let rev = | |
30 | crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?; |
|
30 | crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?; | |
31 | let data = revlog.get_rev_data(rev)?; |
|
31 | let data = revlog.get_rev_data(rev)?; | |
32 | Ok(data) |
|
32 | Ok(data.into_owned()) | |
33 | } |
|
33 | } |
@@ -32,7 +32,7 b' impl Changelog {' | |||||
32 | &self, |
|
32 | &self, | |
33 | rev: Revision, |
|
33 | rev: Revision, | |
34 | ) -> Result<ChangelogRevisionData, RevlogError> { |
|
34 | ) -> Result<ChangelogRevisionData, RevlogError> { | |
35 | let bytes = self.revlog.get_rev_data(rev)?; |
|
35 | let bytes = self.revlog.get_rev_data(rev)?.into_owned(); | |
36 | Ok(ChangelogRevisionData { bytes }) |
|
36 | Ok(ChangelogRevisionData { bytes }) | |
37 | } |
|
37 | } | |
38 |
|
38 |
@@ -39,7 +39,7 b' impl Filelog {' | |||||
39 | &self, |
|
39 | &self, | |
40 | file_rev: Revision, |
|
40 | file_rev: Revision, | |
41 | ) -> Result<FilelogRevisionData, RevlogError> { |
|
41 | ) -> Result<FilelogRevisionData, RevlogError> { | |
42 | let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?; |
|
42 | let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?.into_owned(); | |
43 | Ok(FilelogRevisionData(data.into())) |
|
43 | Ok(FilelogRevisionData(data.into())) | |
44 | } |
|
44 | } | |
45 | } |
|
45 | } |
@@ -44,7 +44,7 b' impl Manifestlog {' | |||||
44 | &self, |
|
44 | &self, | |
45 | rev: Revision, |
|
45 | rev: Revision, | |
46 | ) -> Result<Manifest, RevlogError> { |
|
46 | ) -> Result<Manifest, RevlogError> { | |
47 | let bytes = self.revlog.get_rev_data(rev)?; |
|
47 | let bytes = self.revlog.get_rev_data(rev)?.into_owned(); | |
48 | Ok(Manifest { bytes }) |
|
48 | Ok(Manifest { bytes }) | |
49 | } |
|
49 | } | |
50 | } |
|
50 | } |
@@ -184,51 +184,14 b' impl Revlog {' | |||||
184 | /// retrieved as needed, and the deltas will be applied to the inital |
|
184 | /// retrieved as needed, and the deltas will be applied to the inital | |
185 | /// snapshot to rebuild the final data. |
|
185 | /// snapshot to rebuild the final data. | |
186 | #[timed] |
|
186 | #[timed] | |
187 | pub fn get_rev_data(&self, rev: Revision) -> Result<Vec<u8>, RevlogError> { |
|
187 | pub fn get_rev_data( | |
|
188 | &self, | |||
|
189 | rev: Revision, | |||
|
190 | ) -> Result<Cow<[u8]>, RevlogError> { | |||
188 | if rev == NULL_REVISION { |
|
191 | if rev == NULL_REVISION { | |
189 |
return Ok( |
|
192 | return Ok(Cow::Borrowed(&[])); | |
190 | }; |
|
193 | }; | |
191 | // Todo return -> Cow |
|
194 | self.get_entry(rev)?.data() | |
192 | let mut entry = self.get_entry(rev)?; |
|
|||
193 | let mut delta_chain = vec![]; |
|
|||
194 |
|
||||
195 | // The meaning of `base_rev_or_base_of_delta_chain` depends on |
|
|||
196 | // generaldelta. See the doc on `ENTRY_DELTA_BASE` in |
|
|||
197 | // `mercurial/revlogutils/constants.py` and the code in |
|
|||
198 | // [_chaininfo] and in [index_deltachain]. |
|
|||
199 | let uses_generaldelta = self.index.uses_generaldelta(); |
|
|||
200 | while let Some(base_rev) = entry.base_rev_or_base_of_delta_chain { |
|
|||
201 | let base_rev = if uses_generaldelta { |
|
|||
202 | base_rev |
|
|||
203 | } else { |
|
|||
204 | entry.rev - 1 |
|
|||
205 | }; |
|
|||
206 | delta_chain.push(entry); |
|
|||
207 | entry = self.get_entry_internal(base_rev)?; |
|
|||
208 | } |
|
|||
209 |
|
||||
210 | // TODO do not look twice in the index |
|
|||
211 | let index_entry = self |
|
|||
212 | .index |
|
|||
213 | .get_entry(rev) |
|
|||
214 | .ok_or(RevlogError::InvalidRevision)?; |
|
|||
215 |
|
||||
216 | let data: Vec<u8> = if delta_chain.is_empty() { |
|
|||
217 | entry.data_chunk()?.into() |
|
|||
218 | } else { |
|
|||
219 | Revlog::build_data_from_deltas(entry, &delta_chain)? |
|
|||
220 | }; |
|
|||
221 |
|
||||
222 | if self.check_hash( |
|
|||
223 | index_entry.p1(), |
|
|||
224 | index_entry.p2(), |
|
|||
225 | index_entry.hash().as_bytes(), |
|
|||
226 | &data, |
|
|||
227 | ) { |
|
|||
228 | Ok(data) |
|
|||
229 | } else { |
|
|||
230 | Err(RevlogError::corrupted()) |
|
|||
231 | } |
|
|||
232 | } |
|
195 | } | |
233 |
|
196 | |||
234 | /// Check the hash of some given data against the recorded hash. |
|
197 | /// Check the hash of some given data against the recorded hash. | |
@@ -296,6 +259,7 b' impl Revlog {' | |||||
296 | &self.data()[start..end] |
|
259 | &self.data()[start..end] | |
297 | }; |
|
260 | }; | |
298 | let entry = RevlogEntry { |
|
261 | let entry = RevlogEntry { | |
|
262 | revlog: self, | |||
299 | rev, |
|
263 | rev, | |
300 | bytes: data, |
|
264 | bytes: data, | |
301 | compressed_len: index_entry.compressed_len(), |
|
265 | compressed_len: index_entry.compressed_len(), | |
@@ -324,8 +288,9 b' impl Revlog {' | |||||
324 |
|
288 | |||
325 | /// The revlog entry's bytes and the necessary informations to extract |
|
289 | /// The revlog entry's bytes and the necessary informations to extract | |
326 | /// the entry's data. |
|
290 | /// the entry's data. | |
327 |
#[derive( |
|
291 | #[derive(Clone)] | |
328 | pub struct RevlogEntry<'a> { |
|
292 | pub struct RevlogEntry<'a> { | |
|
293 | revlog: &'a Revlog, | |||
329 | rev: Revision, |
|
294 | rev: Revision, | |
330 | bytes: &'a [u8], |
|
295 | bytes: &'a [u8], | |
331 | compressed_len: usize, |
|
296 | compressed_len: usize, | |
@@ -338,9 +303,54 b" impl<'a> RevlogEntry<'a> {" | |||||
338 | self.rev |
|
303 | self.rev | |
339 | } |
|
304 | } | |
340 |
|
305 | |||
|
306 | /// The data for this entry, after resolving deltas if any. | |||
|
307 | pub fn data(&self) -> Result<Cow<'a, [u8]>, RevlogError> { | |||
|
308 | let mut entry = self.clone(); | |||
|
309 | let mut delta_chain = vec![]; | |||
|
310 | ||||
|
311 | // The meaning of `base_rev_or_base_of_delta_chain` depends on | |||
|
312 | // generaldelta. See the doc on `ENTRY_DELTA_BASE` in | |||
|
313 | // `mercurial/revlogutils/constants.py` and the code in | |||
|
314 | // [_chaininfo] and in [index_deltachain]. | |||
|
315 | let uses_generaldelta = self.revlog.index.uses_generaldelta(); | |||
|
316 | while let Some(base_rev) = entry.base_rev_or_base_of_delta_chain { | |||
|
317 | let base_rev = if uses_generaldelta { | |||
|
318 | base_rev | |||
|
319 | } else { | |||
|
320 | entry.rev - 1 | |||
|
321 | }; | |||
|
322 | delta_chain.push(entry); | |||
|
323 | entry = self.revlog.get_entry_internal(base_rev)?; | |||
|
324 | } | |||
|
325 | ||||
|
326 | // TODO do not look twice in the index | |||
|
327 | let index_entry = self | |||
|
328 | .revlog | |||
|
329 | .index | |||
|
330 | .get_entry(self.rev) | |||
|
331 | .ok_or(RevlogError::InvalidRevision)?; | |||
|
332 | ||||
|
333 | let data = if delta_chain.is_empty() { | |||
|
334 | entry.data_chunk()? | |||
|
335 | } else { | |||
|
336 | Revlog::build_data_from_deltas(entry, &delta_chain)?.into() | |||
|
337 | }; | |||
|
338 | ||||
|
339 | if self.revlog.check_hash( | |||
|
340 | index_entry.p1(), | |||
|
341 | index_entry.p2(), | |||
|
342 | index_entry.hash().as_bytes(), | |||
|
343 | &data, | |||
|
344 | ) { | |||
|
345 | Ok(data) | |||
|
346 | } else { | |||
|
347 | Err(RevlogError::corrupted()) | |||
|
348 | } | |||
|
349 | } | |||
|
350 | ||||
341 | /// Extract the data contained in the entry. |
|
351 | /// Extract the data contained in the entry. | |
342 | /// This may be a delta. (See `is_delta`.) |
|
352 | /// This may be a delta. (See `is_delta`.) | |
343 |
fn data_chunk(&self) -> Result<Cow<' |
|
353 | fn data_chunk(&self) -> Result<Cow<'a, [u8]>, RevlogError> { | |
344 | if self.bytes.is_empty() { |
|
354 | if self.bytes.is_empty() { | |
345 | return Ok(Cow::Borrowed(&[])); |
|
355 | return Ok(Cow::Borrowed(&[])); | |
346 | } |
|
356 | } |
General Comments 0
You need to be logged in to leave comments.
Login now