##// END OF EJS Templates
rust: use NodePrefix::from_hex instead of hex::decode directly...
Simon Sapin -
r46647:88e741bf default
parent child Browse files
Show More
@@ -13,6 +13,8 b' use crate::revlog::manifest::{Manifest, '
13 13 use crate::revlog::path_encode::path_encode;
14 14 use crate::revlog::revlog::Revlog;
15 15 use crate::revlog::revlog::RevlogError;
16 use crate::revlog::Node;
17 use crate::revlog::NodePrefix;
16 18 use crate::revlog::Revision;
17 19 use crate::utils::files::get_path_from_bytes;
18 20 use crate::utils::hg_path::{HgPath, HgPathBuf};
@@ -108,15 +110,16 b" impl<'a> CatRev<'a> {"
108 110 let changelog_entry = match self.rev.parse::<Revision>() {
109 111 Ok(rev) => self.changelog.get_rev(rev)?,
110 112 _ => {
111 let changelog_node = hex::decode(&self.rev)
113 let changelog_node = NodePrefix::from_hex(&self.rev)
112 114 .map_err(|_| CatRevErrorKind::InvalidRevision)?;
113 self.changelog.get_node(&changelog_node)?
115 self.changelog.get_node(changelog_node.borrow())?
114 116 }
115 117 };
116 let manifest_node = hex::decode(&changelog_entry.manifest_node()?)
118 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
117 119 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
118 120
119 self.manifest_entry = Some(self.manifest.get_node(&manifest_node)?);
121 self.manifest_entry =
122 Some(self.manifest.get_node((&manifest_node).into())?);
120 123 if let Some(ref manifest_entry) = self.manifest_entry {
121 124 let mut bytes = vec![];
122 125
@@ -132,9 +135,10 b" impl<'a> CatRev<'a> {"
132 135
133 136 let file_log =
134 137 Revlog::open(&index_path, Some(&data_path))?;
135 let file_node = hex::decode(&node_bytes)
138 let file_node = Node::from_hex(node_bytes)
136 139 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
137 let file_rev = file_log.get_node_rev(&file_node)?;
140 let file_rev =
141 file_log.get_node_rev((&file_node).into())?;
138 142 let data = file_log.get_rev_data(file_rev)?;
139 143 if data.starts_with(&METADATA_DELIMITER) {
140 144 let end_delimiter_position = data
@@ -7,6 +7,7 b''
7 7
8 8 use super::find_root;
9 9 use crate::revlog::revlog::{Revlog, RevlogError};
10 use crate::revlog::NodePrefix;
10 11 use crate::revlog::Revision;
11 12
12 13 /// Kind of data to debug
@@ -107,9 +108,9 b" impl<'a> DebugData<'a> {"
107 108 let data = match self.rev.parse::<Revision>() {
108 109 Ok(rev) => revlog.get_rev_data(rev)?,
109 110 _ => {
110 let node = hex::decode(&self.rev)
111 let node = NodePrefix::from_hex(&self.rev)
111 112 .map_err(|_| DebugDataErrorKind::InvalidRevision)?;
112 let rev = revlog.get_node_rev(&node)?;
113 let rev = revlog.get_node_rev(node.borrow())?;
113 114 revlog.get_rev_data(rev)?
114 115 }
115 116 };
@@ -8,6 +8,7 b''
8 8 use crate::dirstate::parsers::parse_dirstate;
9 9 use crate::revlog::changelog::Changelog;
10 10 use crate::revlog::manifest::{Manifest, ManifestEntry};
11 use crate::revlog::node::{Node, NodePrefix};
11 12 use crate::revlog::revlog::RevlogError;
12 13 use crate::revlog::Revision;
13 14 use crate::utils::hg_path::HgPath;
@@ -171,15 +172,16 b" impl<'a> ListRevTrackedFiles<'a> {"
171 172 let changelog_entry = match self.rev.parse::<Revision>() {
172 173 Ok(rev) => self.changelog.get_rev(rev)?,
173 174 _ => {
174 let changelog_node = hex::decode(&self.rev)
175 let changelog_node = NodePrefix::from_hex(&self.rev)
175 176 .or(Err(ListRevTrackedFilesErrorKind::InvalidRevision))?;
176 self.changelog.get_node(&changelog_node)?
177 self.changelog.get_node(changelog_node.borrow())?
177 178 }
178 179 };
179 let manifest_node = hex::decode(&changelog_entry.manifest_node()?)
180 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
180 181 .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?;
181 182
182 self.manifest_entry = Some(self.manifest.get_node(&manifest_node)?);
183 self.manifest_entry =
184 Some(self.manifest.get_node((&manifest_node).into())?);
183 185
184 186 if let Some(ref manifest_entry) = self.manifest_entry {
185 187 Ok(manifest_entry.files())
@@ -1,4 +1,5 b''
1 1 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::NodePrefixRef;
2 3 use crate::revlog::Revision;
3 4 use std::path::PathBuf;
4 5
@@ -19,7 +20,7 b' impl Changelog {'
19 20 /// Return the `ChangelogEntry` a given node id.
20 21 pub fn get_node(
21 22 &self,
22 node: &[u8],
23 node: NodePrefixRef,
23 24 ) -> Result<ChangelogEntry, RevlogError> {
24 25 let rev = self.revlog.get_node_rev(node)?;
25 26 self.get_rev(rev)
@@ -1,7 +1,9 b''
1 use std::convert::TryInto;
1 2 use std::ops::Deref;
2 3
3 4 use byteorder::{BigEndian, ByteOrder};
4 5
6 use crate::revlog::node::Node;
5 7 use crate::revlog::revlog::RevlogError;
6 8 use crate::revlog::{Revision, NULL_REVISION};
7 9
@@ -188,8 +190,8 b" impl<'a> IndexEntry<'a> {"
188 190 ///
189 191 /// Currently, SHA-1 is used and only the first 20 bytes of this field
190 192 /// are used.
191 pub fn hash(&self) -> &[u8] {
192 &self.bytes[32..52]
193 pub fn hash(&self) -> &Node {
194 (&self.bytes[32..52]).try_into().unwrap()
193 195 }
194 196 }
195 197
@@ -1,4 +1,5 b''
1 1 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::NodePrefixRef;
2 3 use crate::revlog::Revision;
3 4 use crate::utils::hg_path::HgPath;
4 5 use std::path::PathBuf;
@@ -18,7 +19,10 b' impl Manifest {'
18 19 }
19 20
20 21 /// Return the `ManifestEntry` of a given node id.
21 pub fn get_node(&self, node: &[u8]) -> Result<ManifestEntry, RevlogError> {
22 pub fn get_node(
23 &self,
24 node: NodePrefixRef,
25 ) -> Result<ManifestEntry, RevlogError> {
22 26 let rev = self.revlog.get_node_rev(node)?;
23 27 self.get_rev(rev)
24 28 }
@@ -9,6 +9,7 b''
9 9 //! of a revision.
10 10
11 11 use hex::{self, FromHex, FromHexError};
12 use std::convert::{TryFrom, TryInto};
12 13
13 14 /// The length in bytes of a `Node`
14 15 ///
@@ -65,6 +66,19 b' impl From<NodeData> for Node {'
65 66 }
66 67 }
67 68
69 /// Return an error if the slice has an unexpected length
70 impl<'a> TryFrom<&'a [u8]> for &'a Node {
71 type Error = std::array::TryFromSliceError;
72
73 #[inline]
74 fn try_from(bytes: &'a [u8]) -> Result<&'a Node, Self::Error> {
75 let data = bytes.try_into()?;
76 // Safety: `#[repr(transparent)]` makes it ok to "wrap" the target
77 // of a reference to the type of the single field.
78 Ok(unsafe { std::mem::transmute::<&NodeData, &Node>(data) })
79 }
80 }
81
68 82 #[derive(Debug, PartialEq)]
69 83 pub enum NodeError {
70 84 ExactLengthRequired(usize, String),
@@ -103,8 +117,8 b' impl Node {'
103 117 ///
104 118 /// To be used in FFI and I/O only, in order to facilitate future
105 119 /// changes of hash format.
106 pub fn from_hex(hex: &str) -> Result<Node, NodeError> {
107 Ok(NodeData::from_hex(hex)
120 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Node, NodeError> {
121 Ok(NodeData::from_hex(hex.as_ref())
108 122 .map_err(|e| NodeError::from((e, hex)))?
109 123 .into())
110 124 }
@@ -126,17 +140,15 b' impl Node {'
126 140 }
127 141 }
128 142
129 impl<T: AsRef<str>> From<(FromHexError, T)> for NodeError {
143 impl<T: AsRef<[u8]>> From<(FromHexError, T)> for NodeError {
130 144 fn from(err_offender: (FromHexError, T)) -> Self {
131 145 let (err, offender) = err_offender;
146 let offender = String::from_utf8_lossy(offender.as_ref()).into_owned();
132 147 match err {
133 148 FromHexError::InvalidStringLength => {
134 NodeError::ExactLengthRequired(
135 NODE_NYBBLES_LENGTH,
136 offender.as_ref().to_owned(),
137 )
149 NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, offender)
138 150 }
139 _ => NodeError::HexError(err, offender.as_ref().to_owned()),
151 _ => NodeError::HexError(err, offender),
140 152 }
141 153 }
142 154 }
@@ -171,8 +183,8 b' impl NodePrefix {'
171 183
172 184 let is_odd = len % 2 == 1;
173 185 let even_part = if is_odd { &hex[..len - 1] } else { hex };
174 let mut buf: Vec<u8> = Vec::from_hex(&even_part)
175 .map_err(|e| (e, String::from_utf8_lossy(hex)))?;
186 let mut buf: Vec<u8> =
187 Vec::from_hex(&even_part).map_err(|e| (e, hex))?;
176 188
177 189 if is_odd {
178 190 let latest_char = char::from(hex[len - 1]);
@@ -182,7 +194,7 b' impl NodePrefix {'
182 194 c: latest_char,
183 195 index: len - 1,
184 196 },
185 String::from_utf8_lossy(hex),
197 hex,
186 198 )
187 199 })? as u8;
188 200 buf.push(latest_nybble << 4);
@@ -278,6 +290,12 b" impl<'a> From<&'a Node> for NodePrefixRe"
278 290 }
279 291 }
280 292
293 impl PartialEq<Node> for NodePrefixRef<'_> {
294 fn eq(&self, other: &Node) -> bool {
295 !self.is_odd && self.buf == other.data
296 }
297 }
298
281 299 #[cfg(test)]
282 300 mod tests {
283 301 use super::*;
@@ -292,7 +310,7 b' mod tests {'
292 310 }
293 311
294 312 /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH`
295 ///
313 ///check_hash
296 314 /// The padding is made with zeros
297 315 pub fn hex_pad_right(hex: &str) -> String {
298 316 let mut res = hex.to_string();
@@ -13,7 +13,7 b' use micro_timer::timed;'
13 13 use zstd;
14 14
15 15 use super::index::Index;
16 use super::node::{NODE_BYTES_LENGTH, NULL_NODE_ID};
16 use super::node::{NodePrefixRef, NODE_BYTES_LENGTH, NULL_NODE};
17 17 use super::patch;
18 18 use crate::revlog::Revision;
19 19
@@ -92,17 +92,20 b' impl Revlog {'
92 92
93 93 /// Return the full data associated to a node.
94 94 #[timed]
95 pub fn get_node_rev(&self, node: &[u8]) -> Result<Revision, RevlogError> {
95 pub fn get_node_rev(
96 &self,
97 node: NodePrefixRef,
98 ) -> Result<Revision, RevlogError> {
96 99 // This is brute force. But it is fast enough for now.
97 100 // Optimization will come later.
98 101 let mut found_by_prefix = None;
99 102 for rev in (0..self.len() as Revision).rev() {
100 103 let index_entry =
101 104 self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
102 if index_entry.hash() == node {
105 if node == *index_entry.hash() {
103 106 return Ok(rev);
104 107 }
105 if index_entry.hash().starts_with(node) {
108 if node.is_prefix_of(index_entry.hash()) {
106 109 if found_by_prefix.is_some() {
107 110 return Err(RevlogError::AmbiguousPrefix);
108 111 }
@@ -143,7 +146,7 b' impl Revlog {'
143 146 if self.check_hash(
144 147 index_entry.p1(),
145 148 index_entry.p2(),
146 index_entry.hash(),
149 index_entry.hash().as_bytes(),
147 150 &data,
148 151 ) {
149 152 Ok(data)
@@ -163,15 +166,15 b' impl Revlog {'
163 166 let e1 = self.index.get_entry(p1);
164 167 let h1 = match e1 {
165 168 Some(ref entry) => entry.hash(),
166 None => &NULL_NODE_ID,
169 None => &NULL_NODE,
167 170 };
168 171 let e2 = self.index.get_entry(p2);
169 172 let h2 = match e2 {
170 173 Some(ref entry) => entry.hash(),
171 None => &NULL_NODE_ID,
174 None => &NULL_NODE,
172 175 };
173 176
174 hash(data, &h1, &h2).as_slice() == expected
177 hash(data, h1.as_bytes(), h2.as_bytes()).as_slice() == expected
175 178 }
176 179
177 180 /// Build the full data of a revision out its snapshot
@@ -115,8 +115,10 b' Specifying revisions by changeset ID'
115 115 $ rhg cat -r cf8b83 file-2
116 116 2
117 117 $ rhg cat -r c file-2
118 abort: invalid revision identifier c
118 abort: ambiguous revision identifier c
119 119 [255]
120 $ rhg cat -r d file-2
121 2
120 122
121 123 Cat files
122 124 $ cd $TESTTMP
General Comments 0
You need to be logged in to leave comments. Login now