diff --git a/src/cargo/sources/git/mod.rs b/src/cargo/sources/git/mod.rs index 4c01016c249..0b2cb9908e1 100644 --- a/src/cargo/sources/git/mod.rs +++ b/src/cargo/sources/git/mod.rs @@ -8,7 +8,7 @@ //! [CVE-2022-46176]: https://blog.rust-lang.org/2023/01/10/cve-2022-46176.html pub use self::source::GitSource; -pub use self::utils::{fetch, GitCheckout, GitDatabase, GitRemote}; +pub use self::utils::{fetch, resolve_ref, GitCheckout, GitDatabase, GitRemote}; mod known_hosts; mod oxide; mod source; diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 74690d30c7b..7ce43d9bd1f 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -123,7 +123,7 @@ impl GitRemote { let resolved_commit_hash = match locked_rev { Some(rev) => db.contains(rev).then_some(rev), - None => reference.resolve(&db.repo).ok(), + None => resolve_ref(reference, &db.repo).ok(), }; if let Some(rev) = resolved_commit_hash { return Ok((db, rev)); @@ -148,7 +148,7 @@ impl GitRemote { .with_context(|| format!("failed to clone into: {}", into.display()))?; let rev = match locked_rev { Some(rev) => rev, - None => reference.resolve(&repo)?, + None => resolve_ref(reference, &repo)?, }; Ok(( @@ -207,56 +207,54 @@ impl GitDatabase { self.repo.revparse_single(&oid.to_string()).is_ok() } - /// [`GitReference::resolve`]s this reference with this database. + /// [`resolve_ref`]s this reference with this database. pub fn resolve(&self, r: &GitReference) -> CargoResult { - r.resolve(&self.repo) + resolve_ref(r, &self.repo) } } -impl GitReference { - /// Resolves self to an object ID with objects the `repo` currently has. - pub fn resolve(&self, repo: &git2::Repository) -> CargoResult { - let id = match self { - // Note that we resolve the named tag here in sync with where it's - // fetched into via `fetch` below. - GitReference::Tag(s) => (|| -> CargoResult { - let refname = format!("refs/remotes/origin/tags/{}", s); - let id = repo.refname_to_id(&refname)?; - let obj = repo.find_object(id, None)?; - let obj = obj.peel(ObjectType::Commit)?; - Ok(obj.id()) - })() - .with_context(|| format!("failed to find tag `{}`", s))?, - - // Resolve the remote name since that's all we're configuring in - // `fetch` below. - GitReference::Branch(s) => { - let name = format!("origin/{}", s); - let b = repo - .find_branch(&name, git2::BranchType::Remote) - .with_context(|| format!("failed to find branch `{}`", s))?; - b.get() - .target() - .ok_or_else(|| anyhow::format_err!("branch `{}` did not have a target", s))? - } +/// Resolves [`GitReference`] to an object ID with objects the `repo` currently has. +pub fn resolve_ref(gitref: &GitReference, repo: &git2::Repository) -> CargoResult { + let id = match gitref { + // Note that we resolve the named tag here in sync with where it's + // fetched into via `fetch` below. + GitReference::Tag(s) => (|| -> CargoResult { + let refname = format!("refs/remotes/origin/tags/{}", s); + let id = repo.refname_to_id(&refname)?; + let obj = repo.find_object(id, None)?; + let obj = obj.peel(ObjectType::Commit)?; + Ok(obj.id()) + })() + .with_context(|| format!("failed to find tag `{}`", s))?, + + // Resolve the remote name since that's all we're configuring in + // `fetch` below. + GitReference::Branch(s) => { + let name = format!("origin/{}", s); + let b = repo + .find_branch(&name, git2::BranchType::Remote) + .with_context(|| format!("failed to find branch `{}`", s))?; + b.get() + .target() + .ok_or_else(|| anyhow::format_err!("branch `{}` did not have a target", s))? + } - // We'll be using the HEAD commit - GitReference::DefaultBranch => { - let head_id = repo.refname_to_id("refs/remotes/origin/HEAD")?; - let head = repo.find_object(head_id, None)?; - head.peel(ObjectType::Commit)?.id() - } + // We'll be using the HEAD commit + GitReference::DefaultBranch => { + let head_id = repo.refname_to_id("refs/remotes/origin/HEAD")?; + let head = repo.find_object(head_id, None)?; + head.peel(ObjectType::Commit)?.id() + } - GitReference::Rev(s) => { - let obj = repo.revparse_single(s)?; - match obj.as_tag() { - Some(tag) => tag.target_id(), - None => obj.id(), - } + GitReference::Rev(s) => { + let obj = repo.revparse_single(s)?; + match obj.as_tag() { + Some(tag) => tag.target_id(), + None => obj.id(), } - }; - Ok(id) - } + } + }; + Ok(id) } impl<'a> GitCheckout<'a> { @@ -1404,7 +1402,7 @@ fn github_fast_path( return Ok(FastPathRev::Indeterminate); } - let local_object = reference.resolve(repo).ok(); + let local_object = resolve_ref(reference, repo).ok(); let github_branch_name = match reference { GitReference::Branch(branch) => branch, diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 841ee3683d9..34df41ffa9b 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -4,6 +4,7 @@ use crate::core::global_cache_tracker; use crate::core::{GitReference, PackageId, SourceId}; use crate::sources::git; use crate::sources::git::fetch::RemoteKind; +use crate::sources::git::resolve_ref; use crate::sources::registry::download; use crate::sources::registry::MaybeLock; use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData}; @@ -149,7 +150,7 @@ impl<'cfg> RemoteRegistry<'cfg> { fn head(&self) -> CargoResult { if self.head.get().is_none() { let repo = self.repo()?; - let oid = self.index_git_ref.resolve(repo)?; + let oid = resolve_ref(&self.index_git_ref, repo)?; self.head.set(Some(oid)); } Ok(self.head.get().unwrap())