Mercurial > hg
comparison rust/hg-core/src/revlog/mod.rs @ 50985:363620b934aa stable
revlog: fix a bug where NULL_NODE failed to be resolved to NULL_REV
The problem is that nodemap already takes care about NULL_NODE
resolution (in `validate_candidate` in `nodemap.rs`), so the special
handling in `rev_from_node` is unnecessary and incorrect.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Wed, 13 Sep 2023 18:28:51 +0100 |
parents | 124c44b5cfad |
children | eccf7dc7c91e |
comparison
equal
deleted
inserted
replaced
50984:2dcb6a6c7540 | 50985:363620b934aa |
---|---|
223 /// revlog | 223 /// revlog |
224 pub fn rev_from_node( | 224 pub fn rev_from_node( |
225 &self, | 225 &self, |
226 node: NodePrefix, | 226 node: NodePrefix, |
227 ) -> Result<Revision, RevlogError> { | 227 ) -> Result<Revision, RevlogError> { |
228 let looked_up = if let Some(nodemap) = &self.nodemap { | 228 if let Some(nodemap) = &self.nodemap { |
229 nodemap | 229 nodemap |
230 .find_bin(&self.index, node)? | 230 .find_bin(&self.index, node)? |
231 .ok_or(RevlogError::InvalidRevision) | 231 .ok_or(RevlogError::InvalidRevision) |
232 } else { | 232 } else { |
233 self.rev_from_node_no_persistent_nodemap(node) | 233 self.rev_from_node_no_persistent_nodemap(node) |
234 }; | 234 } |
235 | |
236 if node.is_prefix_of(&NULL_NODE) { | |
237 return match looked_up { | |
238 Ok(_) => Err(RevlogError::AmbiguousPrefix), | |
239 Err(RevlogError::InvalidRevision) => Ok(NULL_REVISION), | |
240 res => res, | |
241 }; | |
242 }; | |
243 | |
244 looked_up | |
245 } | 235 } |
246 | 236 |
247 /// Same as `rev_from_node`, without using a persistent nodemap | 237 /// Same as `rev_from_node`, without using a persistent nodemap |
248 /// | 238 /// |
249 /// This is used as fallback when a persistent nodemap is not present. | 239 /// This is used as fallback when a persistent nodemap is not present. |
255 ) -> Result<Revision, RevlogError> { | 245 ) -> Result<Revision, RevlogError> { |
256 // Linear scan of the revlog | 246 // Linear scan of the revlog |
257 // TODO: consider building a non-persistent nodemap in memory to | 247 // TODO: consider building a non-persistent nodemap in memory to |
258 // optimize these cases. | 248 // optimize these cases. |
259 let mut found_by_prefix = None; | 249 let mut found_by_prefix = None; |
260 for rev in (0..self.len() as Revision).rev() { | 250 for rev in (-1..self.len() as Revision).rev() { |
261 let index_entry = self.index.get_entry(rev).ok_or_else(|| { | 251 let candidate_node = if rev == -1 { |
262 HgError::corrupted( | 252 NULL_NODE |
263 "revlog references a revision not in the index", | 253 } else { |
264 ) | 254 let index_entry = |
265 })?; | 255 self.index.get_entry(rev).ok_or_else(|| { |
266 if node == *index_entry.hash() { | 256 HgError::corrupted( |
257 "revlog references a revision not in the index", | |
258 ) | |
259 })?; | |
260 *index_entry.hash() | |
261 }; | |
262 if node == candidate_node { | |
267 return Ok(rev); | 263 return Ok(rev); |
268 } | 264 } |
269 if node.is_prefix_of(index_entry.hash()) { | 265 if node.is_prefix_of(&candidate_node) { |
270 if found_by_prefix.is_some() { | 266 if found_by_prefix.is_some() { |
271 return Err(RevlogError::AmbiguousPrefix); | 267 return Err(RevlogError::AmbiguousPrefix); |
272 } | 268 } |
273 found_by_prefix = Some(rev) | 269 found_by_prefix = Some(rev) |
274 } | 270 } |