Mercurial > hg
annotate rust/hg-core/src/revlog/revlog.rs @ 45806:7252f5237352
hg-core: fix path encoding usage
1. Hash encoded path are in `.hg/store/dh` instead of `.hg/store/data`.
2. Path encoded index and data files may not have the same parent path.
It is not just about replacing `.i` by `.d`
Differential Revision: https://phab.mercurial-scm.org/D9121
author | Antoine cezar<acezar@chwitlabs.fr> |
---|---|
date | Mon, 28 Sep 2020 17:13:15 +0200 |
parents | be951ca95b08 |
children | 8d6164098782 |
rev | line source |
---|---|
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
1 use std::borrow::Cow; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
2 use std::fs::File; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
3 use std::io::Read; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
4 use std::ops::Deref; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
5 use std::path::Path; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
6 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
7 use byteorder::{BigEndian, ByteOrder}; |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
8 use crypto::digest::Digest; |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
9 use crypto::sha1::Sha1; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 use flate2::read::ZlibDecoder; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 use memmap::{Mmap, MmapOptions}; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
12 use micro_timer::timed; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
13 use zstd; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
14 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
15 use super::index::Index; |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
16 use super::node::{NODE_BYTES_LENGTH, NULL_NODE_ID}; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
17 use super::patch; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
18 use crate::revlog::Revision; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
19 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
20 pub enum RevlogError { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
21 IoError(std::io::Error), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
22 UnsuportedVersion(u16), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
23 InvalidRevision, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
24 Corrupted, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
25 UnknowDataFormat(u8), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
26 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
27 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
28 fn mmap_open(path: &Path) -> Result<Mmap, std::io::Error> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
29 let file = File::open(path)?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
30 let mmap = unsafe { MmapOptions::new().map(&file) }?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
31 Ok(mmap) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
32 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
33 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
34 /// Read only implementation of revlog. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
35 pub struct Revlog { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
36 /// When index and data are not interleaved: bytes of the revlog index. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
37 /// When index and data are interleaved: bytes of the revlog index and |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
38 /// data. |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
39 index: Index, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
40 /// When index and data are not interleaved: bytes of the revlog data |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
41 data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
42 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
43 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
44 impl Revlog { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
45 /// Open a revlog index file. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
46 /// |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
47 /// It will also open the associated data file if index and data are not |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
48 /// interleaved. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
49 #[timed] |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
50 pub fn open( |
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
51 index_path: &Path, |
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
52 data_path: Option<&Path>, |
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
53 ) -> Result<Self, RevlogError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
54 let index_mmap = |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
55 mmap_open(&index_path).map_err(RevlogError::IoError)?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
56 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
57 let version = get_version(&index_mmap); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
58 if version != 1 { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
59 return Err(RevlogError::UnsuportedVersion(version)); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
60 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
61 |
45602
1cef583541c0
hg-core: return Err if `offset != bytes.len()`
Antoine cezar<acezar@chwitlabs.fr>
parents:
45601
diff
changeset
|
62 let index = Index::new(Box::new(index_mmap))?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
63 |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
64 let default_data_path = index_path.with_extension("d"); |
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
65 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
66 // type annotation required |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
67 // won't recognize Mmap as Deref<Target = [u8]> |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
68 let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> = |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
69 if index.is_inline() { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
70 None |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
71 } else { |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
72 let data_path = data_path.unwrap_or(&default_data_path); |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
73 let data_mmap = |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
74 mmap_open(data_path).map_err(RevlogError::IoError)?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
75 Some(Box::new(data_mmap)) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
76 }; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
77 |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
78 Ok(Revlog { index, data_bytes }) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
79 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
80 |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
81 /// Return number of entries of the `Revlog`. |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
82 pub fn len(&self) -> usize { |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
83 self.index.len() |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
84 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
85 |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
86 /// Returns `true` if the `Revlog` has zero `entries`. |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
87 pub fn is_empty(&self) -> bool { |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
88 self.index.is_empty() |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
89 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
90 |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
91 /// Return the full data associated to a node. |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
92 #[timed] |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
93 pub fn get_node_rev(&self, node: &[u8]) -> Result<Revision, RevlogError> { |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
94 // This is brute force. But it is fast enough for now. |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
95 // Optimization will come later. |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
96 for rev in (0..self.len() as Revision).rev() { |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
97 let index_entry = |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
98 self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?; |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
99 if node == index_entry.hash() { |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
100 return Ok(rev); |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
101 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
102 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
103 Err(RevlogError::InvalidRevision) |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
104 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
105 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
106 /// Return the full data associated to a revision. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
107 /// |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
108 /// All entries required to build the final data out of deltas will be |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
109 /// retrieved as needed, and the deltas will be applied to the inital |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
110 /// snapshot to rebuild the final data. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
111 #[timed] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
112 pub fn get_rev_data(&self, rev: Revision) -> Result<Vec<u8>, RevlogError> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
113 // Todo return -> Cow |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
114 let mut entry = self.get_entry(rev)?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
115 let mut delta_chain = vec![]; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
116 while let Some(base_rev) = entry.base_rev { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
117 delta_chain.push(entry); |
45603
be951ca95b08
hg-core: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45602
diff
changeset
|
118 entry = |
be951ca95b08
hg-core: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45602
diff
changeset
|
119 self.get_entry(base_rev).or(Err(RevlogError::Corrupted))?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
120 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
121 |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
122 // TODO do not look twice in the index |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
123 let index_entry = self |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
124 .index |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
125 .get_entry(rev) |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
126 .ok_or(RevlogError::InvalidRevision)?; |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
127 |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
128 let data: Vec<u8> = if delta_chain.is_empty() { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
129 entry.data()?.into() |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
130 } else { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
131 Revlog::build_data_from_deltas(entry, &delta_chain)? |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
132 }; |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
133 |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
134 if self.check_hash( |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
135 index_entry.p1(), |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
136 index_entry.p2(), |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
137 index_entry.hash(), |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
138 &data, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
139 ) { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
140 Ok(data) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
141 } else { |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
142 Err(RevlogError::Corrupted) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
143 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
144 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
145 |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
146 /// Check the hash of some given data against the recorded hash. |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
147 pub fn check_hash( |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
148 &self, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
149 p1: Revision, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
150 p2: Revision, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
151 expected: &[u8], |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
152 data: &[u8], |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
153 ) -> bool { |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
154 let e1 = self.index.get_entry(p1); |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
155 let h1 = match e1 { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
156 Some(ref entry) => entry.hash(), |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
157 None => &NULL_NODE_ID, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
158 }; |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
159 let e2 = self.index.get_entry(p2); |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
160 let h2 = match e2 { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
161 Some(ref entry) => entry.hash(), |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
162 None => &NULL_NODE_ID, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
163 }; |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
164 |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
165 hash(data, &h1, &h2).as_slice() == expected |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
166 } |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
167 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
168 /// Build the full data of a revision out its snapshot |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
169 /// and its deltas. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
170 #[timed] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
171 fn build_data_from_deltas( |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
172 snapshot: RevlogEntry, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
173 deltas: &[RevlogEntry], |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
174 ) -> Result<Vec<u8>, RevlogError> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
175 let snapshot = snapshot.data()?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
176 let deltas = deltas |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
177 .iter() |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
178 .rev() |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
179 .map(RevlogEntry::data) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
180 .collect::<Result<Vec<Cow<'_, [u8]>>, RevlogError>>()?; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
181 let patches: Vec<_> = |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
182 deltas.iter().map(|d| patch::PatchList::new(d)).collect(); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
183 let patch = patch::fold_patch_lists(&patches); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
184 Ok(patch.apply(&snapshot)) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
185 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
186 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
187 /// Return the revlog data. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
188 fn data(&self) -> &[u8] { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
189 match self.data_bytes { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
190 Some(ref data_bytes) => &data_bytes, |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
191 None => panic!( |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
192 "forgot to load the data or trying to access inline data" |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
193 ), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
194 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
195 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
196 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
197 /// Get an entry of the revlog. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
198 fn get_entry(&self, rev: Revision) -> Result<RevlogEntry, RevlogError> { |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
199 let index_entry = self |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
200 .index |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
201 .get_entry(rev) |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
202 .ok_or(RevlogError::InvalidRevision)?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
203 let start = index_entry.offset(); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
204 let end = start + index_entry.compressed_len(); |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
205 let data = if self.index.is_inline() { |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
206 self.index.data(start, end) |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
207 } else { |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
208 &self.data()[start..end] |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
209 }; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
210 let entry = RevlogEntry { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
211 rev, |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
212 bytes: data, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
213 compressed_len: index_entry.compressed_len(), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
214 uncompressed_len: index_entry.uncompressed_len(), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
215 base_rev: if index_entry.base_revision() == rev { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
216 None |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
217 } else { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
218 Some(index_entry.base_revision()) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
219 }, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
220 }; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
221 Ok(entry) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
222 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
223 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
224 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
225 /// The revlog entry's bytes and the necessary informations to extract |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
226 /// the entry's data. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
227 #[derive(Debug)] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
228 pub struct RevlogEntry<'a> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
229 rev: Revision, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
230 bytes: &'a [u8], |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
231 compressed_len: usize, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
232 uncompressed_len: usize, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
233 base_rev: Option<Revision>, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
234 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
235 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
236 impl<'a> RevlogEntry<'a> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
237 /// Extract the data contained in the entry. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
238 pub fn data(&self) -> Result<Cow<'_, [u8]>, RevlogError> { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
239 if self.bytes.is_empty() { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
240 return Ok(Cow::Borrowed(&[])); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
241 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
242 match self.bytes[0] { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
243 // Revision data is the entirety of the entry, including this |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
244 // header. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
245 b'\0' => Ok(Cow::Borrowed(self.bytes)), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
246 // Raw revision data follows. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
247 b'u' => Ok(Cow::Borrowed(&self.bytes[1..])), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
248 // zlib (RFC 1950) data. |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
249 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
250 // zstd data. |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
251 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
252 format_type => Err(RevlogError::UnknowDataFormat(format_type)), |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
253 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
254 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
255 |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
256 fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, RevlogError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
257 let mut decoder = ZlibDecoder::new(self.bytes); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
258 if self.is_delta() { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
259 let mut buf = Vec::with_capacity(self.compressed_len); |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
260 decoder |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
261 .read_to_end(&mut buf) |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
262 .or(Err(RevlogError::Corrupted))?; |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
263 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
264 } else { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
265 let mut buf = vec![0; self.uncompressed_len]; |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
266 decoder |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
267 .read_exact(&mut buf) |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
268 .or(Err(RevlogError::Corrupted))?; |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
269 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
270 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
271 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
272 |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
273 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, RevlogError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
274 if self.is_delta() { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
275 let mut buf = Vec::with_capacity(self.compressed_len); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
276 zstd::stream::copy_decode(self.bytes, &mut buf) |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
277 .or(Err(RevlogError::Corrupted))?; |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
278 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
279 } else { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
280 let mut buf = vec![0; self.uncompressed_len]; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
281 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf) |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
282 .or(Err(RevlogError::Corrupted))?; |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
283 if len != self.uncompressed_len { |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
284 Err(RevlogError::Corrupted) |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
285 } else { |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
286 Ok(buf) |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
287 } |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
288 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
289 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
290 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
291 /// Tell if the entry is a snapshot or a delta |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
292 /// (influences on decompression). |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
293 fn is_delta(&self) -> bool { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
294 self.base_rev.is_some() |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
295 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
296 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
297 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
298 /// Format version of the revlog. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
299 pub fn get_version(index_bytes: &[u8]) -> u16 { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
300 BigEndian::read_u16(&index_bytes[2..=3]) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
301 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
302 |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
303 /// Calculate the hash of a revision given its data and its parents. |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
304 fn hash(data: &[u8], p1_hash: &[u8], p2_hash: &[u8]) -> Vec<u8> { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
305 let mut hasher = Sha1::new(); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
306 let (a, b) = (p1_hash, p2_hash); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
307 if a > b { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
308 hasher.input(b); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
309 hasher.input(a); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
310 } else { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
311 hasher.input(a); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
312 hasher.input(b); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
313 } |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
314 hasher.input(data); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
315 let mut hash = vec![0; NODE_BYTES_LENGTH]; |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
316 hasher.result(&mut hash); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
317 hash |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
318 } |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
319 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
320 #[cfg(test)] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
321 mod tests { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
322 use super::*; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
323 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
324 use super::super::index::IndexEntryBuilder; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
325 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
326 #[test] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
327 fn version_test() { |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
328 let bytes = IndexEntryBuilder::new() |
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
329 .is_first(true) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
330 .with_version(1) |
45601
900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45595
diff
changeset
|
331 .build(); |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
332 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
333 assert_eq!(get_version(&bytes), 1) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
334 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
335 } |