361 if let Some(nodemap) = &self.nodemap { |
361 if let Some(nodemap) = &self.nodemap { |
362 nodemap |
362 nodemap |
363 .find_bin(self.index(), node)? |
363 .find_bin(self.index(), node)? |
364 .ok_or(RevlogError::InvalidRevision(format!("{:x}", node))) |
364 .ok_or(RevlogError::InvalidRevision(format!("{:x}", node))) |
365 } else { |
365 } else { |
366 self.rev_from_node_no_persistent_nodemap(node) |
366 self.index().rev_from_node_no_persistent_nodemap(node) |
367 } |
367 } |
368 } |
|
369 |
|
370 /// Same as `rev_from_node`, without using a persistent nodemap |
|
371 /// |
|
372 /// This is used as fallback when a persistent nodemap is not present. |
|
373 /// This happens when the persistent-nodemap experimental feature is not |
|
374 /// enabled, or for small revlogs. |
|
375 fn rev_from_node_no_persistent_nodemap( |
|
376 &self, |
|
377 node: NodePrefix, |
|
378 ) -> Result<Revision, RevlogError> { |
|
379 // Linear scan of the revlog |
|
380 // TODO: consider building a non-persistent nodemap in memory to |
|
381 // optimize these cases. |
|
382 let mut found_by_prefix = None; |
|
383 for rev in (-1..self.len() as BaseRevision).rev() { |
|
384 let rev = Revision(rev as BaseRevision); |
|
385 let candidate_node = if rev == Revision(-1) { |
|
386 NULL_NODE |
|
387 } else { |
|
388 let index_entry = |
|
389 self.index().get_entry(rev).ok_or_else(|| { |
|
390 HgError::corrupted( |
|
391 "revlog references a revision not in the index", |
|
392 ) |
|
393 })?; |
|
394 *index_entry.hash() |
|
395 }; |
|
396 if node == candidate_node { |
|
397 return Ok(rev); |
|
398 } |
|
399 if node.is_prefix_of(&candidate_node) { |
|
400 if found_by_prefix.is_some() { |
|
401 return Err(RevlogError::AmbiguousPrefix); |
|
402 } |
|
403 found_by_prefix = Some(rev) |
|
404 } |
|
405 } |
|
406 found_by_prefix |
|
407 .ok_or(RevlogError::InvalidRevision(format!("{:x}", node))) |
|
408 } |
368 } |
409 |
369 |
410 /// Returns whether the given revision exists in this revlog. |
370 /// Returns whether the given revision exists in this revlog. |
411 pub fn has_rev(&self, rev: UncheckedRevision) -> bool { |
371 pub fn has_rev(&self, rev: UncheckedRevision) -> bool { |
412 self.index().check_revision(rev).is_some() |
372 self.index().check_revision(rev).is_some() |