feat: update depot version to 0.29.1 and enhance git fetch handling with full refs support

This commit is contained in:
2026-03-21 13:49:34 -05:00
parent ae93cf0bd8
commit bfbec3ff8e
4 changed files with 77 additions and 15 deletions
Generated
+1 -1
View File
@@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2"
[[package]] [[package]]
name = "depot" name = "depot"
version = "0.29.0" version = "0.29.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ar", "ar",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "depot" name = "depot"
version = "0.29.0" version = "0.29.1"
edition = "2024" edition = "2024"
[lints.rust] [lints.rust]
+1 -1
View File
@@ -1,6 +1,6 @@
project( project(
'depot', 'depot',
version: '0.29.0', version: '0.29.1',
meson_version: '>=0.60.0', meson_version: '>=0.60.0',
default_options: ['buildtype=release'], default_options: ['buildtype=release'],
) )
+74 -12
View File
@@ -2,7 +2,8 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use git2::{ use git2::{
CheckoutNotificationType, Cred, CredentialType, FetchOptions, Oid, RemoteCallbacks, Repository, AutotagOption, CheckoutNotificationType, Cred, CredentialType, FetchOptions, Oid,
RemoteCallbacks, Repository,
}; };
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use inquire::Password; use inquire::Password;
@@ -199,7 +200,7 @@ fn ensure_mirror(
#[derive(Clone)] #[derive(Clone)]
enum FetchAttempt { enum FetchAttempt {
Default, FullRefs,
HeadRefs, HeadRefs,
Tag(String), Tag(String),
Branch(String), Branch(String),
@@ -208,7 +209,7 @@ enum FetchAttempt {
impl FetchAttempt { impl FetchAttempt {
fn refspecs(&self) -> Vec<&str> { fn refspecs(&self) -> Vec<&str> {
match self { match self {
FetchAttempt::Default => Vec::new(), FetchAttempt::FullRefs => vec![ALL_HEADS_REFSPEC, ALL_TAGS_REFSPEC],
FetchAttempt::HeadRefs => vec!["+refs/heads/*:refs/heads/*"], FetchAttempt::HeadRefs => vec!["+refs/heads/*:refs/heads/*"],
FetchAttempt::Tag(tag) => vec![tag.as_str()], FetchAttempt::Tag(tag) => vec![tag.as_str()],
FetchAttempt::Branch(branch) => vec![branch.as_str()], FetchAttempt::Branch(branch) => vec![branch.as_str()],
@@ -216,6 +217,9 @@ impl FetchAttempt {
} }
} }
const ALL_HEADS_REFSPEC: &str = "+refs/heads/*:refs/heads/*";
const ALL_TAGS_REFSPEC: &str = "+refs/tags/*:refs/tags/*";
fn ensure_origin_remote<'a>(repo: &'a Repository, url: &str) -> Result<git2::Remote<'a>> { fn ensure_origin_remote<'a>(repo: &'a Repository, url: &str) -> Result<git2::Remote<'a>> {
match repo.find_remote("origin") { match repo.find_remote("origin") {
Ok(remote) => Ok(remote), Ok(remote) => Ok(remote),
@@ -235,6 +239,8 @@ fn fetch_remote_refspecs(
refspecs: &[&str], refspecs: &[&str],
) -> Result<()> { ) -> Result<()> {
let mut fo = FetchOptions::new(); let mut fo = FetchOptions::new();
fo.download_tags(AutotagOption::All);
fo.update_fetchhead(true);
let transfer_progress = TransferProgress::new(format!("git {}", pkgname)); let transfer_progress = TransferProgress::new(format!("git {}", pkgname));
fo.remote_callbacks(authenticated_remote_callbacks( fo.remote_callbacks(authenticated_remote_callbacks(
Some(transfer_progress.bar()), Some(transfer_progress.bar()),
@@ -261,7 +267,7 @@ fn fetch_attempt_message(attempt: &FetchAttempt, rev: &str, fresh: bool) -> Opti
"mirror updated" "mirror updated"
}; };
match attempt { match attempt {
FetchAttempt::Default => Some(state.to_string()), FetchAttempt::FullRefs => Some(format!("{state} (all heads/tags)")),
FetchAttempt::HeadRefs => Some(format!("{state} (heads only)")), FetchAttempt::HeadRefs => Some(format!("{state} (heads only)")),
FetchAttempt::Tag(_) => Some(format!("{state} (tag {})", rev)), FetchAttempt::Tag(_) => Some(format!("{state} (tag {})", rev)),
FetchAttempt::Branch(_) => Some(format!("{state} (branch {})", rev)), FetchAttempt::Branch(_) => Some(format!("{state} (branch {})", rev)),
@@ -334,17 +340,17 @@ fn ensure_valid_local_head(repo: &Repository) -> Result<()> {
fn fetch_attempts_for_rev(rev: &str) -> Vec<FetchAttempt> { fn fetch_attempts_for_rev(rev: &str) -> Vec<FetchAttempt> {
if rev.eq_ignore_ascii_case("HEAD") { if rev.eq_ignore_ascii_case("HEAD") {
return vec![FetchAttempt::HeadRefs, FetchAttempt::Default]; return vec![FetchAttempt::HeadRefs, FetchAttempt::FullRefs];
} }
if is_probably_oid(rev) { if is_probably_oid(rev) {
return vec![FetchAttempt::Default]; return vec![FetchAttempt::FullRefs];
} }
vec![ vec![
FetchAttempt::Tag(tag_refspec(rev)), FetchAttempt::Tag(tag_refspec(rev)),
FetchAttempt::Branch(branch_refspec(rev)), FetchAttempt::Branch(branch_refspec(rev)),
FetchAttempt::Default, FetchAttempt::FullRefs,
] ]
} }
@@ -388,7 +394,7 @@ fn is_probably_oid(rev: &str) -> bool {
} }
fn tag_refspec(rev: &str) -> String { fn tag_refspec(rev: &str) -> String {
format!("refs/tags/{rev}:refs/tags/{rev}") format!("+refs/tags/{rev}:refs/tags/{rev}")
} }
fn branch_refspec(rev: &str) -> String { fn branch_refspec(rev: &str) -> String {
@@ -883,7 +889,7 @@ mod tests {
let attempts = fetch_attempts_for_rev("HEAD"); let attempts = fetch_attempts_for_rev("HEAD");
assert!(matches!( assert!(matches!(
attempts.as_slice(), attempts.as_slice(),
[FetchAttempt::HeadRefs, FetchAttempt::Default] [FetchAttempt::HeadRefs, FetchAttempt::FullRefs]
)); ));
} }
@@ -892,18 +898,24 @@ mod tests {
let attempts = fetch_attempts_for_rev("v1.2.3"); let attempts = fetch_attempts_for_rev("v1.2.3");
assert_eq!(attempts.len(), 3); assert_eq!(attempts.len(), 3);
assert!( assert!(
matches!(&attempts[0], FetchAttempt::Tag(tag) if tag == "refs/tags/v1.2.3:refs/tags/v1.2.3") matches!(&attempts[0], FetchAttempt::Tag(tag) if tag == "+refs/tags/v1.2.3:refs/tags/v1.2.3")
); );
assert!( assert!(
matches!(&attempts[1], FetchAttempt::Branch(branch) if branch == "+refs/heads/v1.2.3:refs/heads/v1.2.3") matches!(&attempts[1], FetchAttempt::Branch(branch) if branch == "+refs/heads/v1.2.3:refs/heads/v1.2.3")
); );
assert!(matches!(attempts[2], FetchAttempt::Default)); assert!(matches!(attempts[2], FetchAttempt::FullRefs));
} }
#[test] #[test]
fn fetch_attempts_for_oid_use_full_fetch_only() { fn fetch_attempts_for_oid_use_full_fetch_only() {
let attempts = fetch_attempts_for_rev("0123456789abcdef"); let attempts = fetch_attempts_for_rev("0123456789abcdef");
assert!(matches!(attempts.as_slice(), [FetchAttempt::Default])); assert!(matches!(attempts.as_slice(), [FetchAttempt::FullRefs]));
}
#[test]
fn full_fetch_attempt_includes_heads_and_tags_refspecs() {
let refspecs = FetchAttempt::FullRefs.refspecs();
assert_eq!(refspecs, vec![ALL_HEADS_REFSPEC, ALL_TAGS_REFSPEC]);
} }
#[test] #[test]
@@ -1082,4 +1094,54 @@ mod tests {
"topic\n" "topic\n"
); );
} }
#[test]
fn checkout_resolves_annotated_tags_from_remote() {
let temp = tempfile::tempdir().unwrap();
let origin_dir = temp.path().join("origin.git");
let workdir = temp.path().join("work");
let cache_dir = temp.path().join("cache");
let checkout_dir = temp.path().join("checkout");
std::fs::create_dir_all(&workdir).unwrap();
let origin = Repository::init_bare(&origin_dir).unwrap();
let repo = Repository::init(&workdir).unwrap();
repo.set_head("refs/heads/main").unwrap();
let release_commit = commit_file(&repo, &workdir, "README", "release\n");
let release_target = repo.find_object(release_commit, None).unwrap();
let sig = git2::Signature::now("depot-test", "depot@example.test").unwrap();
repo.tag("v1.0.0", &release_target, &sig, "release tag", false)
.unwrap();
let mut remote = repo.remote("origin", origin_dir.to_str().unwrap()).unwrap();
remote
.push(
&[
"refs/heads/main:refs/heads/main",
"refs/tags/v1.0.0:refs/tags/v1.0.0",
],
None,
)
.unwrap();
origin.set_head("refs/heads/main").unwrap();
let origin_url = url::Url::from_file_path(&origin_dir).unwrap().to_string();
checkout(
&origin_url,
"v1.0.0",
&checkout_dir,
&cache_dir,
"test-pkg",
&[],
)
.unwrap();
let checkout_repo = Repository::open(&checkout_dir).unwrap();
assert_eq!(checkout_repo.head().unwrap().target(), Some(release_commit));
assert_eq!(
std::fs::read_to_string(checkout_dir.join("README")).unwrap(),
"release\n"
);
}
} }