Skip to content

Commit 40e6880

Browse files
committed
Remove FullCommit variant
1 parent 3a66fa3 commit 40e6880

File tree

6 files changed

+116
-103
lines changed

6 files changed

+116
-103
lines changed

crates/uv-git/src/git.rs

Lines changed: 108 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ pub static GIT: LazyLock<Result<PathBuf, GitError>> = LazyLock::new(|| {
4040
})
4141
});
4242

43+
/// Strategy when fetching refspecs for a [`GitReference`]
44+
enum RefspecStrategy {
45+
/// All refspecs should be fetched, if any fail then the fetch will fail.
46+
All,
47+
/// Stop after the first successful fetch, if none succeed then the fetch will fail.
48+
First,
49+
}
50+
4351
/// A reference to commit or commit-ish.
4452
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
4553
pub enum GitReference {
@@ -49,24 +57,14 @@ pub enum GitReference {
4957
Tag(String),
5058
/// From a reference that's ambiguously a branch or tag.
5159
BranchOrTag(String),
52-
/// From a reference that's ambiguously a short commit, a branch, or a tag.
60+
/// From a reference that's ambiguously a commit, branch, or tag.
5361
BranchOrTagOrCommit(String),
5462
/// From a named reference, like `refs/pull/493/head`.
5563
NamedRef(String),
56-
/// From a specific revision, using a full 40-character commit hash.
57-
FullCommit(GitOid),
5864
/// The default branch of the repository, the reference named `HEAD`.
5965
DefaultBranch,
6066
}
6167

62-
/// Strategy when fetching refspecs for a [`GitReference`]
63-
enum RefspecStrategy {
64-
// All refspecs should be fetched, if any fail then the fetch will fail
65-
All,
66-
// Stop after the first successful fetch, if none succeed then the fetch will fail
67-
First,
68-
}
69-
7068
impl GitReference {
7169
/// Creates a [`GitReference`] from an arbitrary revision string, which could represent a
7270
/// branch, tag, commit, or named ref.
@@ -87,7 +85,6 @@ impl GitReference {
8785
Self::Branch(rev) => Some(rev),
8886
Self::BranchOrTag(rev) => Some(rev),
8987
Self::BranchOrTagOrCommit(rev) => Some(rev),
90-
Self::FullCommit(rev) => Some(rev.as_str()),
9188
Self::NamedRef(rev) => Some(rev),
9289
Self::DefaultBranch => None,
9390
}
@@ -100,7 +97,6 @@ impl GitReference {
10097
Self::Branch(rev) => rev,
10198
Self::BranchOrTag(rev) => rev,
10299
Self::BranchOrTagOrCommit(rev) => rev,
103-
Self::FullCommit(rev) => rev.as_str(),
104100
Self::NamedRef(rev) => rev,
105101
Self::DefaultBranch => "HEAD",
106102
}
@@ -112,26 +108,93 @@ impl GitReference {
112108
Self::Branch(_) => "branch",
113109
Self::Tag(_) => "tag",
114110
Self::BranchOrTag(_) => "branch or tag",
115-
Self::FullCommit(_) => "commit",
116111
Self::BranchOrTagOrCommit(_) => "branch, tag, or commit",
117112
Self::NamedRef(_) => "ref",
118113
Self::DefaultBranch => "default branch",
119114
}
120115
}
116+
}
121117

122-
/// Returns the precise [`GitOid`] of this reference, if it's a full commit.
123-
pub(crate) fn as_sha(&self) -> Option<GitOid> {
124-
if let Self::FullCommit(rev) = self {
125-
Some(*rev)
126-
} else {
127-
None
118+
impl Display for GitReference {
119+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120+
write!(f, "{}", self.as_str().unwrap_or("HEAD"))
121+
}
122+
}
123+
124+
/// A Git reference (like a tag or branch) or a specific commit.
125+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
126+
enum ReferenceOrOid<'reference> {
127+
/// A Git reference, like a tag or branch.
128+
Reference(&'reference GitReference),
129+
/// A specific commit.
130+
Oid(GitOid),
131+
}
132+
133+
impl ReferenceOrOid<'_> {
134+
/// Resolves the [`ReferenceOrOid`] to an object ID with objects the `repo` currently has.
135+
fn resolve(&self, repo: &GitRepository) -> Result<GitOid> {
136+
let refkind = self.kind_str();
137+
let result = match self {
138+
// Resolve the commit pointed to by the tag.
139+
//
140+
// `^0` recursively peels away from the revision to the underlying commit object.
141+
// This also verifies that the tag indeed refers to a commit.
142+
Self::Reference(GitReference::Tag(s)) => {
143+
repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0"))
144+
}
145+
146+
// Resolve the commit pointed to by the branch.
147+
Self::Reference(GitReference::Branch(s)) => repo.rev_parse(&format!("origin/{s}^0")),
148+
149+
// Attempt to resolve the branch, then the tag.
150+
Self::Reference(GitReference::BranchOrTag(s)) => repo
151+
.rev_parse(&format!("origin/{s}^0"))
152+
.or_else(|_| repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0"))),
153+
154+
// Attempt to resolve the branch, then the tag, then the commit.
155+
Self::Reference(GitReference::BranchOrTagOrCommit(s)) => repo
156+
.rev_parse(&format!("origin/{s}^0"))
157+
.or_else(|_| repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0")))
158+
.or_else(|_| repo.rev_parse(&format!("{s}^0"))),
159+
160+
// We'll be using the HEAD commit.
161+
Self::Reference(GitReference::DefaultBranch) => {
162+
repo.rev_parse("refs/remotes/origin/HEAD")
163+
}
164+
165+
// Resolve a named reference.
166+
Self::Reference(GitReference::NamedRef(s)) => repo.rev_parse(&format!("{s}^0")),
167+
168+
// Resolve a specific commit.
169+
Self::Oid(s) => repo.rev_parse(&format!("{s}^0")),
170+
};
171+
172+
result.with_context(|| anyhow::format_err!("failed to find {refkind} `{self}`"))
173+
}
174+
175+
/// Returns the kind of this [`ReferenceOrOid`].
176+
fn kind_str(&self) -> &str {
177+
match self {
178+
Self::Reference(reference) => reference.kind_str(),
179+
Self::Oid(_) => "commit",
180+
}
181+
}
182+
183+
/// Converts the [`ReferenceOrOid`] to a `str` that can be used as a revision.
184+
fn as_rev(&self) -> &str {
185+
match self {
186+
Self::Reference(r) => r.as_rev(),
187+
Self::Oid(rev) => rev.as_str(),
128188
}
129189
}
130190
}
131191

132-
impl Display for GitReference {
192+
impl Display for ReferenceOrOid<'_> {
133193
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134-
write!(f, "{}", self.as_str().unwrap_or("HEAD"))
194+
match self {
195+
Self::Reference(reference) => write!(f, "{reference}"),
196+
Self::Oid(oid) => write!(f, "{oid}"),
197+
}
135198
}
136199
}
137200

@@ -241,8 +304,9 @@ impl GitRemote {
241304
locked_rev: Option<GitOid>,
242305
client: &ClientWithMiddleware,
243306
) -> Result<(GitDatabase, GitOid)> {
244-
let locked_ref = locked_rev.map(GitReference::FullCommit);
245-
let reference = locked_ref.as_ref().unwrap_or(reference);
307+
let reference = locked_rev
308+
.map(ReferenceOrOid::Oid)
309+
.unwrap_or(ReferenceOrOid::Reference(reference));
246310
let enable_lfs_fetch = env::var(EnvVars::UV_GIT_LFS).is_ok();
247311

248312
if let Some(mut db) = db {
@@ -334,45 +398,6 @@ impl GitDatabase {
334398
}
335399
}
336400

337-
impl GitReference {
338-
/// Resolves self to an object ID with objects the `repo` currently has.
339-
pub(crate) fn resolve(&self, repo: &GitRepository) -> Result<GitOid> {
340-
let refkind = self.kind_str();
341-
let result = match self {
342-
// Resolve the commit pointed to by the tag.
343-
//
344-
// `^0` recursively peels away from the revision to the underlying commit object.
345-
// This also verifies that the tag indeed refers to a commit.
346-
Self::Tag(s) => repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0")),
347-
348-
// Resolve the commit pointed to by the branch.
349-
Self::Branch(s) => repo.rev_parse(&format!("origin/{s}^0")),
350-
351-
// Attempt to resolve the branch, then the tag.
352-
Self::BranchOrTag(s) => repo
353-
.rev_parse(&format!("origin/{s}^0"))
354-
.or_else(|_| repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0"))),
355-
356-
// Attempt to resolve the branch, then the tag, then the commit.
357-
Self::BranchOrTagOrCommit(s) => repo
358-
.rev_parse(&format!("origin/{s}^0"))
359-
.or_else(|_| repo.rev_parse(&format!("refs/remotes/origin/tags/{s}^0")))
360-
.or_else(|_| repo.rev_parse(&format!("{s}^0"))),
361-
362-
// We'll be using the HEAD commit.
363-
Self::DefaultBranch => repo.rev_parse("refs/remotes/origin/HEAD"),
364-
365-
// Resolve a named reference.
366-
Self::NamedRef(s) => repo.rev_parse(&format!("{s}^0")),
367-
368-
// Resolve a direct commit reference.
369-
Self::FullCommit(s) => repo.rev_parse(&format!("{s}^0")),
370-
};
371-
372-
result.with_context(|| anyhow::format_err!("failed to find {refkind} `{self}`"))
373-
}
374-
}
375-
376401
impl GitCheckout {
377402
/// Creates an instance of [`GitCheckout`]. This doesn't imply the checkout
378403
/// is done. Use [`GitCheckout::is_fresh`] to check.
@@ -472,10 +497,10 @@ impl GitCheckout {
472497
/// * Dispatches `git fetch` using the git CLI.
473498
///
474499
/// The `remote_url` argument is the git remote URL where we want to fetch from.
475-
pub(crate) fn fetch(
500+
fn fetch(
476501
repo: &mut GitRepository,
477502
remote_url: &Url,
478-
reference: &GitReference,
503+
reference: ReferenceOrOid<'_>,
479504
client: &ClientWithMiddleware,
480505
) -> Result<()> {
481506
let oid_to_fetch = match github_fast_path(repo, remote_url, reference, client) {
@@ -499,15 +524,15 @@ pub(crate) fn fetch(
499524
match reference {
500525
// For branches and tags we can fetch simply one reference and copy it
501526
// locally, no need to fetch other branches/tags.
502-
GitReference::Branch(branch) => {
527+
ReferenceOrOid::Reference(GitReference::Branch(branch)) => {
503528
refspecs.push(format!("+refs/heads/{branch}:refs/remotes/origin/{branch}"));
504529
}
505530

506-
GitReference::Tag(tag) => {
531+
ReferenceOrOid::Reference(GitReference::Tag(tag)) => {
507532
refspecs.push(format!("+refs/tags/{tag}:refs/remotes/origin/tags/{tag}"));
508533
}
509534

510-
GitReference::BranchOrTag(branch_or_tag) => {
535+
ReferenceOrOid::Reference(GitReference::BranchOrTag(branch_or_tag)) => {
511536
refspecs.push(format!(
512537
"+refs/heads/{branch_or_tag}:refs/remotes/origin/{branch_or_tag}"
513538
));
@@ -519,7 +544,7 @@ pub(crate) fn fetch(
519544

520545
// For ambiguous references, we can fetch the exact commit (if known); otherwise,
521546
// we fetch all branches and tags.
522-
GitReference::BranchOrTagOrCommit(branch_or_tag_or_commit) => {
547+
ReferenceOrOid::Reference(GitReference::BranchOrTagOrCommit(branch_or_tag_or_commit)) => {
523548
// The `oid_to_fetch` is the exact commit we want to fetch. But it could be the exact
524549
// commit of a branch or tag. We should only fetch it directly if it's the exact commit
525550
// of a short commit hash.
@@ -537,15 +562,15 @@ pub(crate) fn fetch(
537562
}
538563
}
539564

540-
GitReference::DefaultBranch => {
565+
ReferenceOrOid::Reference(GitReference::DefaultBranch) => {
541566
refspecs.push(String::from("+HEAD:refs/remotes/origin/HEAD"));
542567
}
543568

544-
GitReference::NamedRef(rev) => {
569+
ReferenceOrOid::Reference(GitReference::NamedRef(rev)) => {
545570
refspecs.push(format!("+{rev}:{rev}"));
546571
}
547572

548-
GitReference::FullCommit(rev) => {
573+
ReferenceOrOid::Oid(rev) => {
549574
refspecs.push(format!("+{rev}:refs/commit/{rev}"));
550575
}
551576
}
@@ -587,7 +612,7 @@ pub(crate) fn fetch(
587612
};
588613
match reference {
589614
// With the default branch, adding context is confusing
590-
GitReference::DefaultBranch => result,
615+
ReferenceOrOid::Reference(GitReference::DefaultBranch) => result,
591616
_ => result.with_context(|| {
592617
format!(
593618
"failed to fetch {} `{}`",
@@ -703,7 +728,7 @@ enum FastPathRev {
703728
fn github_fast_path(
704729
git: &mut GitRepository,
705730
url: &Url,
706-
reference: &GitReference,
731+
reference: ReferenceOrOid<'_>,
707732
client: &ClientWithMiddleware,
708733
) -> Result<FastPathRev> {
709734
let Some(GitHubRepository { owner, repo }) = GitHubRepository::parse(url) else {
@@ -713,12 +738,12 @@ fn github_fast_path(
713738
let local_object = reference.resolve(git).ok();
714739

715740
let github_branch_name = match reference {
716-
GitReference::Branch(branch) => branch,
717-
GitReference::Tag(tag) => tag,
718-
GitReference::BranchOrTag(branch_or_tag) => branch_or_tag,
719-
GitReference::DefaultBranch => "HEAD",
720-
GitReference::NamedRef(rev) => rev,
721-
GitReference::BranchOrTagOrCommit(rev) => {
741+
ReferenceOrOid::Reference(GitReference::DefaultBranch) => "HEAD",
742+
ReferenceOrOid::Reference(GitReference::Branch(branch)) => branch,
743+
ReferenceOrOid::Reference(GitReference::Tag(tag)) => tag,
744+
ReferenceOrOid::Reference(GitReference::BranchOrTag(branch_or_tag)) => branch_or_tag,
745+
ReferenceOrOid::Reference(GitReference::NamedRef(rev)) => rev,
746+
ReferenceOrOid::Reference(GitReference::BranchOrTagOrCommit(rev)) => {
722747
// `revparse_single` (used by `resolve`) is the only way to turn
723748
// short hash -> long hash, but it also parses other things,
724749
// like branch and tag names, which might coincidentally be
@@ -743,18 +768,18 @@ fn github_fast_path(
743768
}
744769
rev
745770
}
746-
GitReference::FullCommit(rev) => {
771+
ReferenceOrOid::Oid(rev) => {
747772
debug!("Skipping GitHub fast path; full commit hash provided: {rev}");
748773

749-
if let Some(ref local_object) = local_object {
774+
if let Some(local_object) = local_object {
750775
if rev == local_object {
751776
return Ok(FastPathRev::UpToDate);
752777
}
753778
}
754779

755780
// If we know the reference is a full commit hash, we can just return it without
756781
// querying GitHub.
757-
return Ok(FastPathRev::NeedsFetch(*rev));
782+
return Ok(FastPathRev::NeedsFetch(rev));
758783
}
759784
};
760785

crates/uv-git/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ pub struct GitUrl {
3131
impl GitUrl {
3232
/// Create a new [`GitUrl`] from a repository URL and a reference.
3333
pub fn from_reference(repository: Url, reference: GitReference) -> Self {
34-
let precise = reference.as_sha();
3534
Self {
3635
repository,
3736
reference,
38-
precise,
37+
precise: None,
3938
}
4039
}
4140

@@ -113,9 +112,6 @@ impl From<GitUrl> for Url {
113112
} else {
114113
// Otherwise, add the branch or tag name.
115114
match git.reference {
116-
GitReference::FullCommit(rev) => {
117-
url.set_path(&format!("{}@{}", url.path(), rev));
118-
}
119115
GitReference::Branch(rev)
120116
| GitReference::Tag(rev)
121117
| GitReference::BranchOrTag(rev)

crates/uv-pypi-types/src/requirement.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,6 @@ impl From<RequirementSource> for RequirementSourceWire {
745745
| GitReference::NamedRef(rev) => {
746746
url.query_pairs_mut().append_pair("rev", rev.as_str());
747747
}
748-
GitReference::FullCommit(rev) => {
749-
url.query_pairs_mut().append_pair("rev", rev.as_str());
750-
}
751748
GitReference::DefaultBranch => {}
752749
}
753750

crates/uv-resolver/src/lock/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,7 +3511,6 @@ impl From<GitReference> for GitSourceKind {
35113511
GitReference::BranchOrTag(rev) => GitSourceKind::Rev(rev.to_string()),
35123512
GitReference::BranchOrTagOrCommit(rev) => GitSourceKind::Rev(rev.to_string()),
35133513
GitReference::NamedRef(rev) => GitSourceKind::Rev(rev.to_string()),
3514-
GitReference::FullCommit(rev) => GitSourceKind::Rev(rev.to_string()),
35153514
GitReference::DefaultBranch => GitSourceKind::DefaultBranch,
35163515
}
35173516
}
@@ -3564,9 +3563,6 @@ fn locked_git_url(git_dist: &GitSourceDist) -> Url {
35643563
| GitReference::NamedRef(rev) => {
35653564
url.query_pairs_mut().append_pair("rev", rev.as_str());
35663565
}
3567-
GitReference::FullCommit(rev) => {
3568-
url.query_pairs_mut().append_pair("rev", rev.as_str());
3569-
}
35703566
GitReference::DefaultBranch => {}
35713567
}
35723568

0 commit comments

Comments
 (0)