From b7a686a531f684b1a8e2ad0bfbc9dd165f02cd90 Mon Sep 17 00:00:00 2001 From: SFG545 Date: Fri, 20 Mar 2026 21:49:21 -0500 Subject: [PATCH] feat: update depot version to 0.28.1, upgrade dependencies and enhance git source handling --- Cargo.lock | 24 ++------ Cargo.toml | 6 +- meson.build | 2 +- src/source/git.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 155 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff40b90..3c65010 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" [[package]] name = "depot" -version = "0.28.0" +version = "0.28.1" dependencies = [ "anyhow", "ar", @@ -2122,9 +2122,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" dependencies = [ "filetime", "libc", @@ -3054,20 +3054,6 @@ name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "zerotrie" @@ -3104,9 +3090,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b680f2a0cd479b4cff6e1233c483fdead418106eae419dc60200ae9850f6d004" +checksum = "4a243cfad17427fc077f529da5a95abe4e94fd2bfdb601611870a6557cc67657" dependencies = [ "aes", "bzip2", diff --git a/Cargo.toml b/Cargo.toml index df89611..b342319 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "depot" -version = "0.28.0" +version = "0.28.1" edition = "2024" [lints.rust] @@ -20,14 +20,14 @@ semver = "1.0.27" serde = { version = "1.0.228", features = ["derive"] } yaml-rust2 = "0.11.0" sha2 = "0.10.9" -tar = "0.4.44" +tar = "0.4.45" tempfile = "=3.27.0" thiserror = "2.0.18" toml = "1.0.6" url = "2.5.8" walkdir = "2.5.0" xz2 = "0.1.7" -zip = "8.2.0" +zip = "8.3.0" zstd = { version = "0.13.3", features = ["zstdmt"] } inquire = "0.9.4" md5 = "0.8.0" diff --git a/meson.build b/meson.build index 4cd5e68..91070e0 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'depot', - version: '0.28.0', + version: '0.28.1', meson_version: '>=0.60.0', default_options: ['buildtype=release'], ) diff --git a/src/source/git.rs b/src/source/git.rs index fcbed45..3268755 100755 --- a/src/source/git.rs +++ b/src/source/git.rs @@ -177,6 +177,7 @@ fn ensure_mirror(url: &str, mirror_dir: &Path, pkgname: &str, rev: &str) -> Resu attempted = true; let refspecs = attempt.refspecs(); fetch_remote_refspecs(&mut remote, url, pkgname, &refspecs)?; + repair_mirror_refs(&repo)?; if resolve_rev_object(&repo, rev).is_ok() { crate::log_info!("{}", message); return Ok(()); @@ -202,7 +203,7 @@ impl FetchAttempt { fn refspecs(&self) -> Vec<&str> { match self { FetchAttempt::Default => Vec::new(), - FetchAttempt::HeadRefs => vec!["+refs/heads/*:refs/remotes/origin/*"], + FetchAttempt::HeadRefs => vec!["+refs/heads/*:refs/heads/*"], FetchAttempt::Tag(tag) => vec![tag.as_str()], FetchAttempt::Branch(branch) => vec![branch.as_str()], } @@ -261,6 +262,70 @@ fn fetch_attempt_message(attempt: &FetchAttempt, rev: &str, fresh: bool) -> Opti } } +fn repair_mirror_refs(repo: &Repository) -> Result<()> { + sync_remote_tracking_heads(repo)?; + ensure_valid_local_head(repo) +} + +fn sync_remote_tracking_heads(repo: &Repository) -> Result<()> { + for reference_result in repo.references_glob("refs/remotes/origin/*")? { + let reference = reference_result?; + let Some(name) = reference.name() else { + continue; + }; + if name == "refs/remotes/origin/HEAD" { + continue; + } + let Some(branch) = name.strip_prefix("refs/remotes/origin/") else { + continue; + }; + let Some(target) = reference.target() else { + continue; + }; + repo.reference( + &format!("refs/heads/{branch}"), + target, + true, + "sync mirror branch from origin tracking ref", + )?; + } + Ok(()) +} + +fn ensure_valid_local_head(repo: &Repository) -> Result<()> { + if let Ok(head) = repo.head() + && (head.target().is_some() || head.resolve().is_ok()) + { + return Ok(()); + } + + let mut candidates: Vec = Vec::new(); + for reference_result in repo.references_glob("refs/heads/*")? { + let reference = reference_result?; + let Some(name) = reference.name() else { + continue; + }; + candidates.push(name.to_string()); + } + + if candidates.is_empty() { + return Ok(()); + } + + candidates.sort(); + let preferred = candidates + .iter() + .find(|name| name.as_str() == "refs/heads/main") + .or_else(|| { + candidates + .iter() + .find(|name| name.as_str() == "refs/heads/master") + }) + .unwrap_or(&candidates[0]); + repo.set_head(preferred)?; + Ok(()) +} + fn fetch_attempts_for_rev(rev: &str) -> Vec { if rev.eq_ignore_ascii_case("HEAD") { return vec![FetchAttempt::HeadRefs, FetchAttempt::Default]; @@ -303,7 +368,7 @@ fn tag_refspec(rev: &str) -> String { } fn branch_refspec(rev: &str) -> String { - format!("+refs/heads/{rev}:refs/remotes/origin/{rev}") + format!("+refs/heads/{rev}:refs/heads/{rev}") } fn checkout_rev(repo: &Repository, rev: &str) -> Result<()> { @@ -806,7 +871,7 @@ mod tests { matches!(&attempts[0], FetchAttempt::Tag(tag) if tag == "refs/tags/v1.2.3:refs/tags/v1.2.3") ); assert!( - matches!(&attempts[1], FetchAttempt::Branch(branch) if branch == "+refs/heads/v1.2.3:refs/remotes/origin/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)); } @@ -839,4 +904,82 @@ mod tests { crate::interrupts::reset(); assert!(git_operation_should_continue(Some(&bar))); } + + #[test] + fn ensure_valid_local_head_prefers_main_when_head_branch_is_missing() { + let temp = tempfile::tempdir().unwrap(); + let bare_dir = temp.path().join("bare.git"); + let workdir = temp.path().join("work"); + let repo = Repository::init_bare(&bare_dir).unwrap(); + std::fs::create_dir_all(&workdir).unwrap(); + let work_repo = Repository::init(&workdir).unwrap(); + work_repo.set_head("refs/heads/main").unwrap(); + commit_file(&work_repo, &workdir, "README", "hello"); + let topic_branch = work_repo + .branch( + "topic", + &work_repo.head().unwrap().peel_to_commit().unwrap(), + false, + ) + .unwrap(); + drop(topic_branch); + let mut remote = work_repo + .remote("origin", bare_dir.to_str().unwrap()) + .unwrap(); + remote + .push( + &[ + "refs/heads/main:refs/heads/main", + "refs/heads/topic:refs/heads/topic", + ], + None, + ) + .unwrap(); + repo.set_head("refs/heads/missing").unwrap(); + + ensure_valid_local_head(&repo).unwrap(); + + assert_eq!( + repo.head().unwrap().resolve().unwrap().name(), + Some("refs/heads/main") + ); + } + + #[test] + fn checkout_head_succeeds_with_bare_mirror_heads_only_fetch() { + 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 commit_oid = commit_file(&repo, &workdir, "README", "hello\n"); + let mut remote = repo.remote("origin", origin_dir.to_str().unwrap()).unwrap(); + remote + .push(&["refs/heads/main:refs/heads/main"], 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, + "HEAD", + &checkout_dir, + &cache_dir, + "test-pkg", + &[], + ) + .unwrap(); + + let checkout_repo = Repository::open(&checkout_dir).unwrap(); + assert_eq!(checkout_repo.head().unwrap().target(), Some(commit_oid)); + assert_eq!( + std::fs::read_to_string(checkout_dir.join("README")).unwrap(), + "hello\n" + ); + } }