Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/revlog/revlog.rs @ 48546:e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
When status is unsure based on `stat()` and the dirstate if a file is clean
or modified, we need to compare it against the filelog.
This comparison can skip looking at contents if the lengths differ.
This changeset optimize this further to deduce what we can about the length
if the filelog without decompressing it or resolving deltas.
Differential Revision: https://phab.mercurial-scm.org/D11965
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Fri, 07 Jan 2022 14:40:21 +0100 |
parents | faa243f345cc |
children | 5d205e476057 cc92ad0e8185 |
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; |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
2 use std::convert::TryFrom; |
45526
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 flate2::read::ZlibDecoder; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
8 use micro_timer::timed; |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
9 use sha1::{Digest, Sha1}; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 use zstd; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
12 use super::index::Index; |
46431
645ee7225fab
rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents:
46390
diff
changeset
|
13 use super::node::{NodePrefix, NODE_BYTES_LENGTH, NULL_NODE}; |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
14 use super::nodemap; |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
15 use super::nodemap::{NodeMap, NodeMapError}; |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
16 use super::nodemap_docket::NodeMapDocket; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
17 use super::patch; |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
18 use crate::errors::HgError; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46090
diff
changeset
|
19 use crate::repo::Repo; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
20 use crate::revlog::Revision; |
47967
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
21 use crate::{Node, NULL_REVISION}; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
22 |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
23 const REVISION_FLAG_CENSORED: u16 = 1 << 15; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
24 const REVISION_FLAG_ELLIPSIS: u16 = 1 << 14; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
25 const REVISION_FLAG_EXTSTORED: u16 = 1 << 13; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
26 const REVISION_FLAG_HASCOPIESINFO: u16 = 1 << 12; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
27 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
28 // Keep this in sync with REVIDX_KNOWN_FLAGS in |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
29 // mercurial/revlogutils/flagutil.py |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
30 const REVIDX_KNOWN_FLAGS: u16 = REVISION_FLAG_CENSORED |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
31 | REVISION_FLAG_ELLIPSIS |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
32 | REVISION_FLAG_EXTSTORED |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
33 | REVISION_FLAG_HASCOPIESINFO; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
34 |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
35 #[derive(derive_more::From)] |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
36 pub enum RevlogError { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
37 InvalidRevision, |
46821
e8ae91b1a63d
rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46744
diff
changeset
|
38 /// Working directory is not supported |
e8ae91b1a63d
rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents:
46744
diff
changeset
|
39 WDirUnsupported, |
46032
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
40 /// 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:
45806
diff
changeset
|
41 AmbiguousPrefix, |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
42 #[from] |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
43 Other(HgError), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
44 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
45 |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
46 impl From<NodeMapError> for RevlogError { |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
47 fn from(error: NodeMapError) -> Self { |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
48 match error { |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
49 NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix, |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
50 NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(), |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
51 } |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
52 } |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
53 } |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
54 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
55 fn corrupted() -> HgError { |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
56 HgError::corrupted("corrupted revlog") |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
57 } |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
58 |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
59 impl RevlogError { |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
60 fn corrupted() -> Self { |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
61 RevlogError::Other(corrupted()) |
46390
0800aa42bb4c
rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents:
46167
diff
changeset
|
62 } |
0800aa42bb4c
rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents:
46167
diff
changeset
|
63 } |
0800aa42bb4c
rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents:
46167
diff
changeset
|
64 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
65 /// Read only implementation of revlog. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
66 pub struct Revlog { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
67 /// 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
|
68 /// 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
|
69 /// data. |
47967
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
70 index: Index, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
71 /// 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
|
72 data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>, |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
73 /// When present on disk: the persistent nodemap for this revlog |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
74 nodemap: Option<nodemap::NodeTree>, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
75 } |
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 impl Revlog { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
78 /// Open a revlog index file. |
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 /// 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
|
81 /// interleaved. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
82 #[timed] |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
83 pub fn open( |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46090
diff
changeset
|
84 repo: &Repo, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46090
diff
changeset
|
85 index_path: impl AsRef<Path>, |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
86 data_path: Option<&Path>, |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47962
diff
changeset
|
87 ) -> Result<Self, HgError> { |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46090
diff
changeset
|
88 let index_path = index_path.as_ref(); |
48199
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
89 let index = { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
90 match repo.store_vfs().mmap_open_opt(&index_path)? { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
91 None => Index::new(Box::new(vec![])), |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
92 Some(index_mmap) => { |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
93 let index = Index::new(Box::new(index_mmap))?; |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
94 Ok(index) |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
95 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
96 } |
9d0e5629cfbf
rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48198
diff
changeset
|
97 }?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
98 |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
99 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
|
100 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
101 // type annotation required |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
102 // 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
|
103 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
|
104 if index.is_inline() { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
105 None |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
106 } else { |
45806
7252f5237352
hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents:
45603
diff
changeset
|
107 let data_path = data_path.unwrap_or(&default_data_path); |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
108 let data_mmap = repo.store_vfs().mmap_open(data_path)?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
109 Some(Box::new(data_mmap)) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
110 }; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
111 |
48226
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
112 let nodemap = if index.is_inline() { |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
113 None |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
114 } else { |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
115 NodeMapDocket::read_from_file(repo, index_path)?.map( |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
116 |(docket, data)| { |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
117 nodemap::NodeTree::load_bytes( |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
118 Box::new(data), |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
119 docket.data_length, |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
120 ) |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
121 }, |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
122 ) |
5e77bdc29d56
rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48199
diff
changeset
|
123 }; |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
124 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
125 Ok(Revlog { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
126 index, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
127 data_bytes, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
128 nodemap, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
129 }) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
130 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
131 |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
132 /// 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
|
133 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
|
134 self.index.len() |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
135 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
136 |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
137 /// 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
|
138 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
|
139 self.index.is_empty() |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
140 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
141 |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47968
diff
changeset
|
142 /// Returns the node ID for the given revision number, if it exists in this |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47968
diff
changeset
|
143 /// revlog |
47967
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
144 pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> { |
48236
f8dc78716ad2
rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48227
diff
changeset
|
145 if rev == NULL_REVISION { |
f8dc78716ad2
rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48227
diff
changeset
|
146 return Some(&NULL_NODE); |
f8dc78716ad2
rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48227
diff
changeset
|
147 } |
47967
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
148 Some(self.index.get_entry(rev)?.hash()) |
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
149 } |
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
150 |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47968
diff
changeset
|
151 /// Return the revision number for the given node ID, if it exists in this |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47968
diff
changeset
|
152 /// revlog |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
153 #[timed] |
47968
6f579618ea7b
rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents:
47967
diff
changeset
|
154 pub fn rev_from_node( |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
155 &self, |
46431
645ee7225fab
rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents:
46390
diff
changeset
|
156 node: NodePrefix, |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
157 ) -> Result<Revision, RevlogError> { |
47962
8c29af0f6d6e
rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents:
47380
diff
changeset
|
158 if node.is_prefix_of(&NULL_NODE) { |
8c29af0f6d6e
rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents:
47380
diff
changeset
|
159 return Ok(NULL_REVISION); |
8c29af0f6d6e
rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents:
47380
diff
changeset
|
160 } |
8c29af0f6d6e
rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents:
47380
diff
changeset
|
161 |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
162 if let Some(nodemap) = &self.nodemap { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
163 return nodemap |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
164 .find_bin(&self.index, node)? |
46090
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
165 .ok_or(RevlogError::InvalidRevision); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
166 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
167 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
168 // 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:
46033
diff
changeset
|
169 // This happens when the persistent-nodemap experimental feature is not |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
170 // enabled, or for small revlogs. |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
171 // |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
172 // TODO: consider building a non-persistent nodemap in memory to |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
46033
diff
changeset
|
173 // optimize these cases. |
46032
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
174 let mut found_by_prefix = None; |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
175 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
|
176 let index_entry = |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
177 self.index.get_entry(rev).ok_or(HgError::corrupted( |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
178 "revlog references a revision not in the index", |
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
179 ))?; |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
180 if node == *index_entry.hash() { |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
181 return Ok(rev); |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
182 } |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
183 if node.is_prefix_of(index_entry.hash()) { |
46032
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
184 if found_by_prefix.is_some() { |
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
185 return Err(RevlogError::AmbiguousPrefix); |
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
186 } |
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
187 found_by_prefix = Some(rev) |
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
188 } |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
189 } |
46032
8d6164098782
rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents:
45806
diff
changeset
|
190 found_by_prefix.ok_or(RevlogError::InvalidRevision) |
45534
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
191 } |
4f11a67a12fb
hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45531
diff
changeset
|
192 |
46433
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
193 /// Returns whether the given revision exists in this revlog. |
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
194 pub fn has_rev(&self, rev: Revision) -> bool { |
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
195 self.index.get_entry(rev).is_some() |
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
196 } |
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
197 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
198 /// 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
|
199 /// |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
200 /// 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
|
201 /// 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
|
202 /// 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
|
203 #[timed] |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
204 pub fn get_rev_data( |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
205 &self, |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
206 rev: Revision, |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
207 ) -> Result<Cow<[u8]>, RevlogError> { |
48198
61ce70fd420e
rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48083
diff
changeset
|
208 if rev == NULL_REVISION { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
209 return Ok(Cow::Borrowed(&[])); |
48198
61ce70fd420e
rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48083
diff
changeset
|
210 }; |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
211 Ok(self.get_entry(rev)?.data()?) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
212 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
213 |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
214 /// 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
|
215 pub fn check_hash( |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
216 &self, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
217 p1: Revision, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
218 p2: Revision, |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
219 expected: &[u8], |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
220 data: &[u8], |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
221 ) -> 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
|
222 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
|
223 let h1 = match e1 { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
224 Some(ref entry) => entry.hash(), |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
225 None => &NULL_NODE, |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
226 }; |
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
|
227 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
|
228 let h2 = match e2 { |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
229 Some(ref entry) => entry.hash(), |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
230 None => &NULL_NODE, |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
231 }; |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
232 |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
233 &hash(data, h1.as_bytes(), h2.as_bytes()) == expected |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
234 } |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
235 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
236 /// 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
|
237 /// and its deltas. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
238 #[timed] |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
239 fn build_data_from_deltas( |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
240 snapshot: RevlogEntry, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
241 deltas: &[RevlogEntry], |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
242 ) -> Result<Vec<u8>, HgError> { |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48458
diff
changeset
|
243 let snapshot = snapshot.data_chunk()?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
244 let deltas = deltas |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
245 .iter() |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
246 .rev() |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48458
diff
changeset
|
247 .map(RevlogEntry::data_chunk) |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
248 .collect::<Result<Vec<_>, _>>()?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
249 let patches: Vec<_> = |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
250 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
|
251 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
|
252 Ok(patch.apply(&snapshot)) |
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 /// Return the revlog data. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
256 fn data(&self) -> &[u8] { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
257 match self.data_bytes { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
258 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
|
259 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
|
260 "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
|
261 ), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
262 } |
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 /// Get an entry of the revlog. |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
266 pub fn get_entry( |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
267 &self, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
268 rev: Revision, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
269 ) -> 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
|
270 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
|
271 .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
|
272 .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
|
273 .ok_or(RevlogError::InvalidRevision)?; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
274 let start = index_entry.offset(); |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
275 let end = start + index_entry.compressed_len() as 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
|
276 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
|
277 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
|
278 } 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
|
279 &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
|
280 }; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
281 let entry = RevlogEntry { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
282 revlog: self, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
283 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
|
284 bytes: data, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
285 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
|
286 uncompressed_len: index_entry.uncompressed_len(), |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
287 base_rev_or_base_of_delta_chain: if index_entry |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
288 .base_revision_or_base_of_delta_chain() |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
289 == rev |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
290 { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
291 None |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
292 } else { |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
293 Some(index_entry.base_revision_or_base_of_delta_chain()) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
294 }, |
48544
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
295 p1: index_entry.p1(), |
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
296 p2: index_entry.p2(), |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
297 flags: index_entry.flags(), |
48544
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
298 hash: *index_entry.hash(), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
299 }; |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
300 Ok(entry) |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
301 } |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
302 |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
303 /// when resolving internal references within revlog, any errors |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
304 /// should be reported as corruption, instead of e.g. "invalid revision" |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
305 fn get_entry_internal( |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
306 &self, |
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
307 rev: Revision, |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
308 ) -> Result<RevlogEntry, HgError> { |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
309 return self.get_entry(rev).map_err(|_| corrupted()); |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
310 } |
45526
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 /// 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
|
314 /// the entry's data. |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
315 #[derive(Clone)] |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
316 pub struct RevlogEntry<'a> { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
317 revlog: &'a Revlog, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
318 rev: Revision, |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
319 bytes: &'a [u8], |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
320 compressed_len: u32, |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
321 uncompressed_len: i32, |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
322 base_rev_or_base_of_delta_chain: Option<Revision>, |
48544
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
323 p1: Revision, |
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
324 p2: Revision, |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
325 flags: u16, |
48544
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
326 hash: Node, |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
327 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
328 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
329 impl<'a> RevlogEntry<'a> { |
48083
fecfea658127
hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents:
47969
diff
changeset
|
330 pub fn revision(&self) -> Revision { |
fecfea658127
hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents:
47969
diff
changeset
|
331 self.rev |
fecfea658127
hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents:
47969
diff
changeset
|
332 } |
fecfea658127
hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents:
47969
diff
changeset
|
333 |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
334 pub fn uncompressed_len(&self) -> Option<u32> { |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
335 u32::try_from(self.uncompressed_len).ok() |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
336 } |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
337 |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
338 pub fn has_p1(&self) -> bool { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
339 self.p1 != NULL_REVISION |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
340 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
341 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
342 pub fn is_cencored(&self) -> bool { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
343 (self.flags & REVISION_FLAG_CENSORED) != 0 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
344 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
345 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
346 pub fn has_length_affecting_flag_processor(&self) -> bool { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
347 // Relevant Python code: revlog.size() |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
348 // note: ELLIPSIS is known to not change the content |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
349 (self.flags & (REVIDX_KNOWN_FLAGS ^ REVISION_FLAG_ELLIPSIS)) != 0 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
350 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48544
diff
changeset
|
351 |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
352 /// The data for this entry, after resolving deltas if any. |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
353 pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
354 let mut entry = self.clone(); |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
355 let mut delta_chain = vec![]; |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
356 |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
357 // The meaning of `base_rev_or_base_of_delta_chain` depends on |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
358 // generaldelta. See the doc on `ENTRY_DELTA_BASE` in |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
359 // `mercurial/revlogutils/constants.py` and the code in |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
360 // [_chaininfo] and in [index_deltachain]. |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
361 let uses_generaldelta = self.revlog.index.uses_generaldelta(); |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
362 while let Some(base_rev) = entry.base_rev_or_base_of_delta_chain { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
363 let base_rev = if uses_generaldelta { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
364 base_rev |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
365 } else { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
366 entry.rev - 1 |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
367 }; |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
368 delta_chain.push(entry); |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
369 entry = self.revlog.get_entry_internal(base_rev)?; |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
370 } |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
371 |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
372 let data = if delta_chain.is_empty() { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
373 entry.data_chunk()? |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
374 } else { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
375 Revlog::build_data_from_deltas(entry, &delta_chain)?.into() |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
376 }; |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
377 |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
378 if self.revlog.check_hash( |
48544
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
379 self.p1, |
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
380 self.p2, |
faa243f345cc
rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48543
diff
changeset
|
381 self.hash.as_bytes(), |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
382 &data, |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
383 ) { |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
384 Ok(data) |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
385 } else { |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
386 Err(corrupted()) |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
387 } |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
388 } |
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
389 |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
390 /// Extract the data contained in the entry. |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48458
diff
changeset
|
391 /// This may be a delta. (See `is_delta`.) |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
392 fn data_chunk(&self) -> Result<Cow<'a, [u8]>, HgError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
393 if self.bytes.is_empty() { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
394 return Ok(Cow::Borrowed(&[])); |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
395 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
396 match self.bytes[0] { |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
397 // 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
|
398 // header. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
399 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
|
400 // Raw revision data follows. |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
401 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
|
402 // 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
|
403 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
|
404 // zstd data. |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
405 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)), |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
406 // A proper new format should have had a repo/store requirement. |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
407 _format_type => Err(corrupted()), |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
408 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
409 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
410 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
411 fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
412 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
|
413 if self.is_delta() { |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
414 let mut buf = Vec::with_capacity(self.compressed_len as usize); |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
415 decoder.read_to_end(&mut buf).map_err(|_| corrupted())?; |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
416 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
417 } else { |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
418 let cap = self.uncompressed_len.max(0) as usize; |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
419 let mut buf = vec![0; cap]; |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
420 decoder.read_exact(&mut buf).map_err(|_| corrupted())?; |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
421 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
422 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
423 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
424 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
425 fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> { |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
426 if self.is_delta() { |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
427 let mut buf = Vec::with_capacity(self.compressed_len as usize); |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
428 zstd::stream::copy_decode(self.bytes, &mut buf) |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
429 .map_err(|_| corrupted())?; |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
430 Ok(buf) |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
431 } else { |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
432 let cap = self.uncompressed_len.max(0) as usize; |
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
433 let mut buf = vec![0; cap]; |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
434 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf) |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
435 .map_err(|_| corrupted())?; |
48543
0a4ac916673e
rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
436 if len != self.uncompressed_len as usize { |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
437 Err(corrupted()) |
45595
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
438 } else { |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
439 Ok(buf) |
497657895b54
hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents:
45536
diff
changeset
|
440 } |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
441 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
442 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
443 |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
444 /// 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
|
445 /// (influences on decompression). |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
446 fn is_delta(&self) -> bool { |
48458
96ea4db4741b
rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48457
diff
changeset
|
447 self.base_rev_or_base_of_delta_chain.is_some() |
45526
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
448 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
449 } |
26c53ee51c68
hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
450 |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
451 /// Calculate the hash of a revision given its data and its parents. |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
452 fn hash( |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
453 data: &[u8], |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
454 p1_hash: &[u8], |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
455 p2_hash: &[u8], |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
456 ) -> [u8; NODE_BYTES_LENGTH] { |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
457 let mut hasher = Sha1::new(); |
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
458 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
|
459 if a > b { |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
460 hasher.update(b); |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
461 hasher.update(a); |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
462 } else { |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
463 hasher.update(a); |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
464 hasher.update(b); |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
465 } |
47380
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
466 hasher.update(data); |
fad504cfc94b
rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents:
46821
diff
changeset
|
467 *hasher.finalize().as_ref() |
45531
b0d6309ff50c
hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45526
diff
changeset
|
468 } |