Preserve .git suffixes and casing in Git dependencies (#2789)

## Summary

I noticed in #2769 that I was now stripping `.git` suffixes from Git
URLs after resolving to a precise commit. This PR cleans up the internal
caching to use a better canonical representation: a `RepositoryUrl`
along with a `GitReference`, instead of a `GitUrl` which can contain
non-canonical data. This gives us both better fidelity (preserving the
`.git`, along with any casing that the user provided when defining the
URL) and is overall cleaner and more robust.
This commit is contained in:
Charlie Marsh 2024-04-02 20:24:29 -04:00 committed by GitHub
parent c30a65ee0c
commit 684f790d5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 104 additions and 54 deletions

View file

@ -24,7 +24,7 @@ const CHECKOUT_READY_LOCK: &str = ".ok";
/// A reference to commit or commit-ish.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) enum GitReference {
pub enum GitReference {
/// From a branch.
#[allow(unused)]
Branch(String),
@ -66,8 +66,29 @@ impl GitReference {
}
}
/// Views the short ID as a `str`.
pub(crate) fn as_str(&self) -> &str {
pub fn precise(&self) -> Option<&str> {
match self {
Self::FullCommit(rev) => Some(rev),
Self::ShortCommit(rev) => Some(rev),
_ => None,
}
}
/// Converts the [`GitReference`] to a `str`.
pub fn as_str(&self) -> Option<&str> {
match self {
Self::Branch(rev) => Some(rev),
Self::Tag(rev) => Some(rev),
Self::BranchOrTag(rev) => Some(rev),
Self::FullCommit(rev) => Some(rev),
Self::ShortCommit(rev) => Some(rev),
Self::Ref(rev) => Some(rev),
Self::DefaultBranch => None,
}
}
/// Converts the [`GitReference`] to a `str` that can be used as a revision.
pub(crate) fn as_rev(&self) -> &str {
match self {
Self::Branch(rev)
| Self::Tag(rev)
@ -79,6 +100,7 @@ impl GitReference {
}
}
/// Returns the kind of this reference.
pub(crate) fn kind_str(&self) -> &str {
match self {
Self::Branch(_) => "branch",
@ -1034,7 +1056,7 @@ pub(crate) fn fetch(
format!(
"failed to fetch {} `{}`",
reference.kind_str(),
reference.as_str()
reference.as_rev()
)
}),
}

View file

@ -1,7 +1,7 @@
use std::str::FromStr;
use url::Url;
use crate::git::GitReference;
pub use crate::git::GitReference;
pub use crate::sha::GitSha;
pub use crate::source::{Fetch, GitSource, Reporter};
@ -24,7 +24,7 @@ pub struct GitUrl {
impl GitUrl {
#[must_use]
pub(crate) fn with_precise(mut self, precise: GitSha) -> Self {
pub fn with_precise(mut self, precise: GitSha) -> Self {
self.precise = Some(precise);
self
}
@ -35,16 +35,8 @@ impl GitUrl {
}
/// Return the reference to the commit to use, which could be a branch, tag or revision.
pub fn reference(&self) -> Option<&str> {
match &self.reference {
GitReference::Branch(rev)
| GitReference::Tag(rev)
| GitReference::BranchOrTag(rev)
| GitReference::Ref(rev)
| GitReference::FullCommit(rev)
| GitReference::ShortCommit(rev) => Some(rev),
GitReference::DefaultBranch => None,
}
pub fn reference(&self) -> &GitReference {
&self.reference
}
/// Returns `true` if the reference is a full commit.

View file

@ -70,7 +70,7 @@ impl GitSource {
// Report the checkout operation to the reporter.
let task = self.reporter.as_ref().map(|reporter| {
reporter.on_checkout_start(remote.url(), self.git.reference.as_str())
reporter.on_checkout_start(remote.url(), self.git.reference.as_rev())
});
let (db, actual_rev) = remote.checkout(