Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/revlog/filelog.rs @ 49174:3f86ee422095
censor: make rhg fall back to python when encountering a censored node
This is to make it support censor.policy=ignore without having
to duplicate that logic.
Also, change the censor test in such a way that it uses rhg now,
because extensions are disabled except when we call [hg censor].
Differential Revision: https://phab.mercurial-scm.org/D12607
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Thu, 05 May 2022 15:38:29 +0100 |
parents | 399439c12223 |
children | 52464a20add0 |
rev | line source |
---|---|
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
1 use crate::errors::HgError; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
2 use crate::repo::Repo; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
3 use crate::revlog::path_encode::path_encode; |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
4 use crate::revlog::revlog::RevlogEntry; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
5 use crate::revlog::revlog::{Revlog, RevlogError}; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
6 use crate::revlog::NodePrefix; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
7 use crate::revlog::Revision; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
8 use crate::utils::files::get_path_from_bytes; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
9 use crate::utils::hg_path::HgPath; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
10 use crate::utils::SliceExt; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
11 use std::path::PathBuf; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
12 |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
13 /// A specialized `Revlog` to work with file data logs. |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
14 pub struct Filelog { |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
15 /// The generic `revlog` format. |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
16 revlog: Revlog, |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
17 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
18 |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
19 impl Filelog { |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
20 pub fn open(repo: &Repo, file_path: &HgPath) -> Result<Self, HgError> { |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 let index_path = store_path(file_path, b".i"); |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
22 let data_path = store_path(file_path, b".d"); |
49089
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
23 let revlog = Revlog::open( |
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
24 &repo.store_vfs(), |
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
25 index_path, |
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
26 Some(&data_path), |
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
27 false, |
399439c12223
rust-revlog: make unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49088
diff
changeset
|
28 )?; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
29 Ok(Self { revlog }) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
30 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
31 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
32 /// The given node ID is that of the file as found in a filelog, not of a |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
33 /// changeset. |
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
|
34 pub fn data_for_node( |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
35 &self, |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
36 file_node: impl Into<NodePrefix>, |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
37 ) -> Result<FilelogRevisionData, RevlogError> { |
47968
6f579618ea7b
rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
38 let file_rev = self.revlog.rev_from_node(file_node.into())?; |
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
|
39 self.data_for_rev(file_rev) |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
40 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
41 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
42 /// The given revision is that of the file as found in a filelog, not of a |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
43 /// changeset. |
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
|
44 pub fn data_for_rev( |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
45 &self, |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
46 file_rev: Revision, |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
47 ) -> Result<FilelogRevisionData, RevlogError> { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48540
diff
changeset
|
48 let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?.into_owned(); |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
49 Ok(FilelogRevisionData(data.into())) |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
50 } |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
51 |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
52 /// The given node ID is that of the file as found in a filelog, not of a |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
53 /// changeset. |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
54 pub fn entry_for_node( |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
55 &self, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
56 file_node: impl Into<NodePrefix>, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
57 ) -> Result<FilelogEntry, RevlogError> { |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
58 let file_rev = self.revlog.rev_from_node(file_node.into())?; |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
59 self.entry_for_rev(file_rev) |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
60 } |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
61 |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
62 /// The given revision is that of the file as found in a filelog, not of a |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
63 /// changeset. |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
64 pub fn entry_for_rev( |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
65 &self, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
66 file_rev: Revision, |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
67 ) -> Result<FilelogEntry, RevlogError> { |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
68 Ok(FilelogEntry(self.revlog.get_entry(file_rev)?)) |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
69 } |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
70 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
71 |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
72 fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf { |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
73 let encoded_bytes = |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
74 path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat()); |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
75 get_path_from_bytes(&encoded_bytes).into() |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
76 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
77 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
78 pub struct FilelogEntry<'a>(RevlogEntry<'a>); |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
79 |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
80 impl FilelogEntry<'_> { |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
81 /// `self.data()` can be expensive, with decompression and delta |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
82 /// resolution. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
83 /// |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
84 /// *Without* paying this cost, based on revlog index information |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
85 /// including `RevlogEntry::uncompressed_len`: |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
86 /// |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
87 /// * Returns `true` if the length that `self.data().file_data().len()` |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
88 /// would return is definitely **not equal** to `other_len`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
89 /// * Returns `false` if available information is inconclusive. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
90 pub fn file_data_len_not_equal_to(&self, other_len: u64) -> bool { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
91 // Relevant code that implement this behavior in Python code: |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
92 // basefilectx.cmp, filelog.size, storageutil.filerevisioncopied, |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
93 // revlog.size, revlog.rawsize |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
94 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
95 // Let’s call `file_data_len` what would be returned by |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
96 // `self.data().file_data().len()`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
97 |
49174
3f86ee422095
censor: make rhg fall back to python when encountering a censored node
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49089
diff
changeset
|
98 if self.0.is_censored() { |
48546
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
99 let file_data_len = 0; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
100 return other_len != file_data_len; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
101 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
102 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
103 if self.0.has_length_affecting_flag_processor() { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
104 // We can’t conclude anything about `file_data_len`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
105 return false; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
106 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
107 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
108 // Revlog revisions (usually) have metadata for the size of |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
109 // their data after decompression and delta resolution |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
110 // as would be returned by `Revlog::get_rev_data`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
111 // |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
112 // For filelogs this is the file’s contents preceded by an optional |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
113 // metadata block. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
114 let uncompressed_len = if let Some(l) = self.0.uncompressed_len() { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
115 l as u64 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
116 } else { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
117 // The field was set to -1, the actual uncompressed len is unknown. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
118 // We need to decompress to say more. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
119 return false; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
120 }; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
121 // `uncompressed_len = file_data_len + optional_metadata_len`, |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
122 // so `file_data_len <= uncompressed_len`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
123 if uncompressed_len < other_len { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
124 // Transitively, `file_data_len < other_len`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
125 // So `other_len != file_data_len` definitely. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
126 return true; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
127 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
128 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
129 if uncompressed_len == other_len + 4 { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
130 // It’s possible that `file_data_len == other_len` with an empty |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
131 // metadata block (2 start marker bytes + 2 end marker bytes). |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
132 // This happens when there wouldn’t otherwise be metadata, but |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
133 // the first 2 bytes of file data happen to match a start marker |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
134 // and would be ambiguous. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
135 return false; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
136 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
137 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
138 if !self.0.has_p1() { |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
139 // There may or may not be copy metadata, so we can’t deduce more |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
140 // about `file_data_len` without computing file data. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
141 return false; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
142 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
143 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
144 // Filelog ancestry is not meaningful in the way changelog ancestry is. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
145 // It only provides hints to delta generation. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
146 // p1 and p2 are set to null when making a copy or rename since |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
147 // contents are likely unrelatedto what might have previously existed |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
148 // at the destination path. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
149 // |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
150 // Conversely, since here p1 is non-null, there is no copy metadata. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
151 // Note that this reasoning may be invalidated in the presence of |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
152 // merges made by some previous versions of Mercurial that |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
153 // swapped p1 and p2. See <https://bz.mercurial-scm.org/show_bug.cgi?id=6528> |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
154 // and `tests/test-issue6528.t`. |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
155 // |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
156 // Since copy metadata is currently the only kind of metadata |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
157 // kept in revlog data of filelogs, |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
158 // this `FilelogEntry` does not have such metadata: |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
159 let file_data_len = uncompressed_len; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
160 |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
161 return file_data_len != other_len; |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
162 } |
e91aa800ae5b
rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents:
48542
diff
changeset
|
163 |
48542
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
164 pub fn data(&self) -> Result<FilelogRevisionData, HgError> { |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
165 Ok(FilelogRevisionData(self.0.data()?.into_owned())) |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
166 } |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
167 } |
35c47015b9b7
rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents:
48541
diff
changeset
|
168 |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
169 /// The data for one revision in a filelog, uncompressed and delta-resolved. |
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
170 pub struct FilelogRevisionData(Vec<u8>); |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
171 |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
172 impl FilelogRevisionData { |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
173 /// Split into metadata and data |
48249
e9faae0f445c
rhg: simplify split_metadata
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
174 pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> { |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
175 const DELIMITER: &[u8; 2] = &[b'\x01', b'\n']; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
176 |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
177 if let Some(rest) = self.0.drop_prefix(DELIMITER) { |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
178 if let Some((metadata, data)) = rest.split_2_by_slice(DELIMITER) { |
48249
e9faae0f445c
rhg: simplify split_metadata
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
179 Ok((Some(metadata), data)) |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
180 } else { |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
181 Err(HgError::corrupted( |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
182 "Missing metadata end delimiter in filelog entry", |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
183 )) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
184 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
185 } else { |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
186 Ok((None, &self.0)) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
187 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
188 } |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
189 |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
190 /// Returns the file contents at this revision, stripped of any metadata |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
191 pub fn file_data(&self) -> Result<&[u8], HgError> { |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
192 let (_metadata, data) = self.split()?; |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
193 Ok(data) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
194 } |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
195 |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
196 /// Consume the entry, and convert it into data, discarding any metadata, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
197 /// if present. |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48249
diff
changeset
|
198 pub fn into_file_data(self) -> Result<Vec<u8>, HgError> { |
48249
e9faae0f445c
rhg: simplify split_metadata
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
199 if let (Some(_metadata), data) = self.split()? { |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
200 Ok(data.to_owned()) |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
201 } else { |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
202 Ok(self.0) |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
203 } |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
204 } |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
205 } |