diff --git a/rust/rhgitaly/src/gitlab/revision.rs b/rust/rhgitaly/src/gitlab/revision.rs index 65ced17df56fd683d7929cd7330dc2260e9eacf6_cnVzdC9yaGdpdGFseS9zcmMvZ2l0bGFiL3JldmlzaW9uLnJz..6b1e19b408fe568b7c5d727cfc79d8a8d3f30828_cnVzdC9yaGdpdGFseS9zcmMvZ2l0bGFiL3JldmlzaW9uLnJz 100644 --- a/rust/rhgitaly/src/gitlab/revision.rs +++ b/rust/rhgitaly/src/gitlab/revision.rs @@ -17,6 +17,8 @@ //! the hlpers to handle them are in particular provided by this module. use std::path::Path; -use hg::revlog::node::Node; +use tracing::{info, warn}; + +use hg::revlog::node::{Node, NodePrefix}; use super::state::{ @@ -21,7 +23,8 @@ use super::state::{ - has_keep_around, map_lookup_typed_ref, stream_gitlab_branches, stream_gitlab_special_refs, - stream_gitlab_tags, StateFileError, TypedRef, + get_gitlab_default_branch, has_keep_around, lookup_typed_ref_as_node, map_lookup_typed_ref, + stream_gitlab_branches, stream_gitlab_special_refs, stream_gitlab_tags, StateFileError, + TypedRef, }; #[derive(Debug, derive_more::From)] @@ -102,6 +105,65 @@ .await??) } +pub async fn gitlab_revision_node_prefix( + store_path: &Path, + revision: &[u8], +) -> Result<Option<NodePrefix>, RefError> { + if revision == b"HEAD" { + match get_gitlab_default_branch(store_path).await? { + None => { + info!("No GitLab default branch"); + return Ok(None); + } + Some(branch) => { + match lookup_typed_ref_as_node(stream_gitlab_branches(store_path).await?, &branch) + .await? + { + None => { + warn!("GitLab default branch not found in state file"); + return Ok(None); + } + Some(node) => { + return Ok(Some(node.into())); + } + } + } + } + } + + // Full nodes have the highest precedence in Gitaly. + // They also are frequently used and cheap to check (no I/O). + if let Ok(node) = Node::from_hex(revision) { + return Ok(Some(node.into())); + } + + // Full refs are well qualified, hence have high precedence + if let Ok(node) = full_ref_node(store_path, revision).await { + return Ok(Some(node.into())); + } + + // Tags have the highest precedence amongst potentially ambiguous revisions + if let Some(node) = + lookup_typed_ref_as_node(stream_gitlab_tags(store_path).await?, revision).await? + { + return Ok(Some(node.into())); + } + + // Branches. TODO duplication, maybe chain the streams if not None + if let Some(node) = + lookup_typed_ref_as_node(stream_gitlab_branches(store_path).await?, revision).await? + { + return Ok(Some(node.into())); + } + + // Last case: Node Prefix + if let Ok(prefix) = NodePrefix::from_hex(revision) { + return Ok(Some(prefix)); + } + + Ok(None) +} + #[cfg(test)] mod tests { use super::*;