annotate rust/hg-core/src/revlog/revlog.rs @ 46167:8a4914397d02

rust: introduce Repo and Vfs types for filesystem abstraction This is similar to the corresponding Python classes. Repo represents a repository and knows the path to the `.hg` directory, the `store` directory, and the working directory. Separating these will enable supporting the share extension. A Vfs is created from a Repo for one of these three directories. It has filesystem access APIs that take a relative std::path::Path as a parameter. Differential Revision: https://phab.mercurial-scm.org/D9596
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 14 Dec 2020 16:33:15 +0100
parents 9eb07ab3f2d4
children 0800aa42bb4c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45532
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::io::Read;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
3 use std::ops::Deref;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
4 use std::path::Path;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
5
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
6 use byteorder::{BigEndian, ByteOrder};
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
7 use crypto::digest::Digest;
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
8 use crypto::sha1::Sha1;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
9 use flate2::read::ZlibDecoder;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
10 use micro_timer::timed;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
11 use zstd;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
12
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
13 use super::index::Index;
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
14 use super::node::{NodePrefixRef, NODE_BYTES_LENGTH, NULL_NODE};
46091
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
15 use super::nodemap;
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
16 use super::nodemap::NodeMap;
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
17 use super::nodemap_docket::NodeMapDocket;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
18 use super::patch;
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
19 use crate::repo::Repo;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
20 use crate::revlog::Revision;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
21
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
22 pub enum RevlogError {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
23 IoError(std::io::Error),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
24 UnsuportedVersion(u16),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
25 InvalidRevision,
46036
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
26 /// Found more than one entry whose ID match the requested prefix
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
27 AmbiguousPrefix,
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
28 Corrupted,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
29 UnknowDataFormat(u8),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
30 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
31
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
32 /// Read only implementation of revlog.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
33 pub struct Revlog {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
34 /// 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
35 /// 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
36 /// data.
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
37 index: Index,
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
38 /// 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
39 data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>,
46091
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
40 /// When present on disk: the persistent nodemap for this revlog
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
41 nodemap: Option<nodemap::NodeTree>,
45532
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]
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
50 pub fn open(
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
51 repo: &Repo,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
52 index_path: impl AsRef<Path>,
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
53 data_path: Option<&Path>,
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
54 ) -> Result<Self, RevlogError> {
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
55 let index_path = index_path.as_ref();
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
56 let index_mmap = repo
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
57 .store_vfs()
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
58 .mmap_open(&index_path)
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
59 .map_err(RevlogError::IoError)?;
45532
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 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
62 if version != 1 {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
63 return Err(RevlogError::UnsuportedVersion(version));
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
64 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
65
45605
1cef583541c0 hg-core: return Err if `offset != bytes.len()`
Antoine cezar<acezar@chwitlabs.fr>
parents: 45604
diff changeset
66 let index = Index::new(Box::new(index_mmap))?;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
67
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
68 let default_data_path = index_path.with_extension("d");
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
69
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
70 // type annotation required
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
71 // 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
72 let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> =
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
73 if index.is_inline() {
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
74 None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
75 } else {
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45606
diff changeset
76 let data_path = data_path.unwrap_or(&default_data_path);
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
77 let data_mmap = repo
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
78 .store_vfs()
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
79 .mmap_open(data_path)
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
80 .map_err(RevlogError::IoError)?;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
81 Some(Box::new(data_mmap))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
82 };
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
83
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46091
diff changeset
84 let nodemap = NodeMapDocket::read_from_file(repo, index_path)?.map(
46091
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
85 |(docket, data)| {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
86 nodemap::NodeTree::load_bytes(
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
87 Box::new(data),
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
88 docket.data_length,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
89 )
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
90 },
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
91 );
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
92
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
93 Ok(Revlog {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
94 index,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
95 data_bytes,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
96 nodemap,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
97 })
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
98 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
99
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
100 /// Return number of entries of the `Revlog`.
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
101 pub fn len(&self) -> usize {
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
102 self.index.len()
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
103 }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
104
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
105 /// Returns `true` if the `Revlog` has zero `entries`.
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
106 pub fn is_empty(&self) -> bool {
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
107 self.index.is_empty()
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
108 }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
109
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
110 /// Return the full data associated to a node.
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
111 #[timed]
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
112 pub fn get_node_rev(
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
113 &self,
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
114 node: NodePrefixRef,
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
115 ) -> Result<Revision, RevlogError> {
46091
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
116 if let Some(nodemap) = &self.nodemap {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
117 return nodemap
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
118 .find_bin(&self.index, node)
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
119 // TODO: propagate details of this error:
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
120 .map_err(|_| RevlogError::Corrupted)?
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
121 .ok_or(RevlogError::InvalidRevision);
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
122 }
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
123
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
124 // Fallback to linear scan when a persistent nodemap is not present.
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
125 // This happens when the persistent-nodemap experimental feature is not
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
126 // enabled, or for small revlogs.
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
127 //
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
128 // TODO: consider building a non-persistent nodemap in memory to
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46037
diff changeset
129 // optimize these cases.
46036
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
130 let mut found_by_prefix = None;
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
131 for rev in (0..self.len() as Revision).rev() {
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
132 let index_entry =
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
133 self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
134 if node == *index_entry.hash() {
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
135 return Ok(rev);
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
136 }
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
137 if node.is_prefix_of(index_entry.hash()) {
46036
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
138 if found_by_prefix.is_some() {
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
139 return Err(RevlogError::AmbiguousPrefix);
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
140 }
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
141 found_by_prefix = Some(rev)
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
142 }
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
143 }
46036
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45825
diff changeset
144 found_by_prefix.ok_or(RevlogError::InvalidRevision)
45540
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
145 }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45537
diff changeset
146
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
147 /// 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
148 ///
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
149 /// 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
150 /// 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
151 /// 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
152 #[timed]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
153 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
154 // Todo return -> Cow
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
155 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
156 let mut delta_chain = vec![];
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
157 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
158 delta_chain.push(entry);
45606
be951ca95b08 hg-core: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45605
diff changeset
159 entry =
be951ca95b08 hg-core: use `.or(Err(Error))` not `.map_err(|_| Error)` (D9100#inline-15067)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45605
diff changeset
160 self.get_entry(base_rev).or(Err(RevlogError::Corrupted))?;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
161 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
162
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
163 // TODO do not look twice in the index
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
164 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: 45598
diff changeset
165 .index
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
166 .get_entry(rev)
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
167 .ok_or(RevlogError::InvalidRevision)?;
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
168
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
169 let data: Vec<u8> = if delta_chain.is_empty() {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
170 entry.data()?.into()
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
171 } else {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
172 Revlog::build_data_from_deltas(entry, &delta_chain)?
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
173 };
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
174
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
175 if self.check_hash(
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
176 index_entry.p1(),
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
177 index_entry.p2(),
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
178 index_entry.hash().as_bytes(),
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
179 &data,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
180 ) {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
181 Ok(data)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
182 } else {
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
183 Err(RevlogError::Corrupted)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
184 }
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
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
187 /// 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: 45532
diff changeset
188 pub fn check_hash(
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
189 &self,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
190 p1: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
191 p2: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
192 expected: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
193 data: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
194 ) -> bool {
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
195 let e1 = self.index.get_entry(p1);
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
196 let h1 = match e1 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
197 Some(ref entry) => entry.hash(),
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
198 None => &NULL_NODE,
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
199 };
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
200 let e2 = self.index.get_entry(p2);
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
201 let h2 = match e2 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
202 Some(ref entry) => entry.hash(),
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
203 None => &NULL_NODE,
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
204 };
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
205
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
206 hash(data, h1.as_bytes(), h2.as_bytes()).as_slice() == expected
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
207 }
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
208
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
209 /// 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
210 /// and its deltas.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
211 #[timed]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
212 fn build_data_from_deltas(
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
213 snapshot: RevlogEntry,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
214 deltas: &[RevlogEntry],
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
215 ) -> Result<Vec<u8>, RevlogError> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
216 let snapshot = snapshot.data()?;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
217 let deltas = deltas
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
218 .iter()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
219 .rev()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
220 .map(RevlogEntry::data)
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
221 .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
222 let patches: Vec<_> =
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
223 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
224 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
225 Ok(patch.apply(&snapshot))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
226 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
227
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
228 /// Return the revlog data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
229 fn data(&self) -> &[u8] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
230 match self.data_bytes {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
231 Some(ref data_bytes) => &data_bytes,
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
232 None => panic!(
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
233 "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: 45598
diff changeset
234 ),
45532
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 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
237
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
238 /// 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
239 fn get_entry(&self, rev: Revision) -> Result<RevlogEntry, RevlogError> {
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
240 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: 45598
diff changeset
241 .index
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
242 .get_entry(rev)
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
243 .ok_or(RevlogError::InvalidRevision)?;
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
244 let start = index_entry.offset();
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
245 let end = start + index_entry.compressed_len();
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
246 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: 45598
diff changeset
247 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: 45598
diff changeset
248 } else {
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
249 &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: 45598
diff changeset
250 };
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
251 let entry = RevlogEntry {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
252 rev,
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
253 bytes: data,
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
254 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
255 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
256 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
257 None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
258 } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
259 Some(index_entry.base_revision())
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
260 },
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
261 };
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
262 Ok(entry)
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
263 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
264 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
265
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
266 /// 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
267 /// the entry's data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
268 #[derive(Debug)]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
269 pub struct RevlogEntry<'a> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
270 rev: Revision,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
271 bytes: &'a [u8],
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
272 compressed_len: usize,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
273 uncompressed_len: usize,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
274 base_rev: Option<Revision>,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
275 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
276
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
277 impl<'a> RevlogEntry<'a> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
278 /// 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
279 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
280 if self.bytes.is_empty() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
281 return Ok(Cow::Borrowed(&[]));
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
282 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
283 match self.bytes[0] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
284 // 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
285 // header.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
286 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
287 // Raw revision data follows.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
288 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
289 // zlib (RFC 1950) data.
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
290 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
291 // zstd data.
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
292 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
293 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
294 }
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
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
297 fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, RevlogError> {
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
298 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
299 if self.is_delta() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
300 let mut buf = Vec::with_capacity(self.compressed_len);
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
301 decoder
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
302 .read_to_end(&mut buf)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
303 .or(Err(RevlogError::Corrupted))?;
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
304 Ok(buf)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
305 } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
306 let mut buf = vec![0; self.uncompressed_len];
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
307 decoder
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
308 .read_exact(&mut buf)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
309 .or(Err(RevlogError::Corrupted))?;
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
310 Ok(buf)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
311 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
312 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
313
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
314 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, RevlogError> {
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
315 if self.is_delta() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
316 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
317 zstd::stream::copy_decode(self.bytes, &mut buf)
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
318 .or(Err(RevlogError::Corrupted))?;
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
319 Ok(buf)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
320 } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
321 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
322 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
45598
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
323 .or(Err(RevlogError::Corrupted))?;
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
324 if len != self.uncompressed_len {
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
325 Err(RevlogError::Corrupted)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
326 } else {
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
327 Ok(buf)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45542
diff changeset
328 }
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
329 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
330 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
331
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
332 /// 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
333 /// (influences on decompression).
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
334 fn is_delta(&self) -> bool {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
335 self.base_rev.is_some()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
336 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
337 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
338
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
339 /// Format version of the revlog.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
340 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
341 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
342 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
343
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
344 /// 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: 45532
diff changeset
345 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: 45532
diff changeset
346 let mut hasher = Sha1::new();
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
347 let (a, b) = (p1_hash, p2_hash);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
348 if a > b {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
349 hasher.input(b);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
350 hasher.input(a);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
351 } else {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
352 hasher.input(a);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
353 hasher.input(b);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
354 }
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
355 hasher.input(data);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
356 let mut hash = vec![0; NODE_BYTES_LENGTH];
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
357 hasher.result(&mut hash);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
358 hash
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
359 }
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45532
diff changeset
360
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
361 #[cfg(test)]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
362 mod tests {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
363 use super::*;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
364
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
365 use super::super::index::IndexEntryBuilder;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
366
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
367 #[test]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
368 fn version_test() {
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
369 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: 45598
diff changeset
370 .is_first(true)
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
371 .with_version(1)
45604
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45598
diff changeset
372 .build();
45532
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
373
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
374 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
375 }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
376 }