##// END OF EJS Templates
rhg: Add RevlogEntry::data that does delta resolution...
Simon Sapin -
r49373:f2f57724 default
parent child Browse files
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(vec![]);
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(Debug)]
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<'_, [u8]>, RevlogError> {
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