From 26c88db05117aea52caedf0fd045bdf8a92dd783 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Mon, 27 May 2024 09:56:49 -0400 Subject: [PATCH] fix: check if rev is full commit sha for github fast path --- src/cargo/sources/git/source.rs | 12 ++++-------- src/cargo/sources/git/utils.rs | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 9f92ab2c14e..8beacdd456d 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -4,6 +4,7 @@ use crate::core::global_cache_tracker; use crate::core::GitReference; use crate::core::SourceId; use crate::core::{Dependency, Package, PackageId}; +use crate::sources::git::utils::rev_to_oid; use crate::sources::git::utils::GitRemote; use crate::sources::source::MaybePackage; use crate::sources::source::QueryKind; @@ -171,14 +172,9 @@ enum Revision { impl Revision { fn new(rev: &str) -> Revision { - let oid = git2::Oid::from_str(rev).ok(); - match oid { - // Git object ID is supposed to be a hex string of 20 (SHA1) or 32 (SHA256) bytes. - // Its length must be double to the underlying bytes (40 or 64), - // otherwise libgit2 would happily zero-pad the returned oid. - // See rust-lang/cargo#13188 - Some(oid) if oid.as_bytes().len() * 2 == rev.len() => Revision::Locked(oid), - _ => Revision::Deferred(GitReference::Rev(rev.to_string())), + match rev_to_oid(rev) { + Some(oid) => Revision::Locked(oid), + None => Revision::Deferred(GitReference::Rev(rev.to_string())), } } } diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 66fb11a3079..6117266559a 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -1421,7 +1421,7 @@ fn github_fast_path( // to is itself. Don't bother talking to GitHub in that case // either. (This ensures that we always attempt to fetch the // commit directly even if we can't reach the GitHub API.) - if let Ok(oid) = rev.parse() { + if let Some(oid) = rev_to_oid(rev) { debug!("github fast path is already a full commit hash {rev}"); return Ok(FastPathRev::NeedsFetch(oid)); } @@ -1614,3 +1614,19 @@ mod tests { } } } + +/// Turns a full commit hash revision into an oid. +/// +/// Git object ID is supposed to be a hex string of 20 (SHA1) or 32 (SHA256) bytes. +/// Its length must be double to the underlying bytes (40 or 64), +/// otherwise libgit2 would happily zero-pad the returned oid. +/// +/// See: +/// +/// * +/// * +pub(super) fn rev_to_oid(rev: &str) -> Option { + Oid::from_str(rev) + .ok() + .filter(|oid| oid.as_bytes().len() * 2 == rev.len()) +}