diff --git a/Cargo.lock b/Cargo.lock index 99a05f7..4d28ea4 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" [[package]] name = "depot" -version = "0.13.2" +version = "0.13.3" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 414c828..8732229 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "depot" -version = "0.13.2" +version = "0.13.3" edition = "2024" [lints.rust] diff --git a/meson.build b/meson.build index 38f0653..0a495c9 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'depot', - version: '0.13.2', + version: '0.13.3', meson_version: '>=0.60.0', ) diff --git a/src/commands.rs b/src/commands.rs index 77e1f03..33ccb01 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1438,6 +1438,10 @@ fn candidate_request_path( } fn sync_source_repositories_for_update(config: &config::Config) -> Result<()> { + if config.repo_settings.prefer_binary { + return Ok(()); + } + let mirrors = config.enabled_source_mirror_map(); if mirrors.is_empty() { return Ok(()); @@ -1704,7 +1708,11 @@ fn collect_update_candidates( } } - let source_candidates = collect_best_source_update_candidates(config, &target_names)?; + let source_candidates = if config.repo_settings.prefer_binary { + HashMap::new() + } else { + collect_best_source_update_candidates(config, &target_names)? + }; let binary_candidates = collect_best_binary_update_candidates(config, rootfs, &target_names)?; let mut updates = Vec::new(); @@ -4577,6 +4585,65 @@ optional = [] assert_eq!(selected.candidate_completed_at, Some(200)); } + #[test] + fn collect_update_candidates_skips_source_when_prefer_binary_is_enabled() -> Result<()> { + let temp = tempfile::tempdir().context("Failed to create temp dir")?; + let rootfs = temp.path().join("rootfs"); + let repo_clones = temp.path().join("repos"); + let build_dir = temp.path().join("build"); + let db_dir = rootfs.join("var/lib/depot"); + fs::create_dir_all(&db_dir)?; + fs::create_dir_all(&repo_clones)?; + fs::create_dir_all(&build_dir)?; + + let mut config = config::Config::for_rootfs(&rootfs); + config.repo_clone_dir = repo_clones.clone(); + config.build_dir = build_dir; + config.db_dir = db_dir.clone(); + config.repo_settings.prefer_binary = true; + config.binary_repos.clear(); + config.source_repos.insert( + "private".into(), + config::SourceRepo { + url: "https://example.test/private.git".into(), + enabled: true, + priority: 0, + subdirs: Vec::new(), + }, + ); + + let installed_spec = package::PackageSpec { + package: package::PackageInfo { + name: "pkg".into(), + version: "1.0.0".into(), + revision: 1, + description: "pkg".into(), + homepage: "https://example.test".into(), + license: vec!["MIT".into()], + }, + packages: Vec::new(), + alternatives: package::Alternatives::default(), + manual_sources: Vec::new(), + source: Vec::new(), + build: package::Build { + build_type: package::BuildType::Bin, + flags: package::BuildFlags::default(), + }, + dependencies: package::Dependencies::default(), + package_alternatives: Default::default(), + package_dependencies: Default::default(), + spec_dir: PathBuf::from("."), + }; + let dest = temp.path().join("dest"); + fs::create_dir_all(dest.join("usr/bin"))?; + fs::write(dest.join("usr/bin/pkg"), "pkg")?; + db::register_package(&config.installed_db_path(&rootfs), &installed_spec, &dest)?; + + let updates = collect_update_candidates(&config, &rootfs, &[])?; + assert!(updates.is_empty()); + Ok(()) + } + #[test] fn collect_missing_update_dependencies_skips_planned_provides_and_installed_deps() -> Result<()> { diff --git a/src/db/repo.rs b/src/db/repo.rs index d6a2889..15ea9a0 100644 --- a/src/db/repo.rs +++ b/src/db/repo.rs @@ -2037,7 +2037,7 @@ pub fn sync_mirrors( repo_dir: &std::path::Path, mirrors: &std::collections::HashMap, ) -> Result<()> { - use git2::{Cred, FetchOptions, RemoteCallbacks, Repository, ResetType, build::RepoBuilder}; + use git2::{FetchOptions, Repository, ResetType, build::RepoBuilder}; use std::os::unix::fs::PermissionsExt; let base = repo_dir.to_path_buf(); @@ -2051,15 +2051,10 @@ pub fn sync_mirrors( if !target.exists() { crate::log_info!("Cloning mirror '{}' -> {}", name, target.display()); - // Use git2 RepoBuilder to clone - let mut cb = RemoteCallbacks::new(); - cb.credentials(|_url, username_from_url, _allowed| { - // Try default credentials (ssh-agent / keychain) - Cred::ssh_key_from_agent(username_from_url.unwrap_or("git")) - }); - let mut fo = FetchOptions::new(); - fo.remote_callbacks(cb); + fo.remote_callbacks(crate::source::authenticated_remote_callbacks( + None, &git_url, + )); let mut builder = RepoBuilder::new(); builder.fetch_options(fo); @@ -2072,13 +2067,10 @@ pub fn sync_mirrors( let repo = Repository::open(&target) .with_context(|| format!("Failed to open repository at {}", target.display()))?; - let mut cb = RemoteCallbacks::new(); - cb.credentials(|_url, username_from_url, _allowed| { - Cred::ssh_key_from_agent(username_from_url.unwrap_or("git")) - }); - let mut fo = FetchOptions::new(); - fo.remote_callbacks(cb); + fo.remote_callbacks(crate::source::authenticated_remote_callbacks( + None, &git_url, + )); // Fetch from origin let mut remote = repo diff --git a/src/source/git.rs b/src/source/git.rs index 377bb26..3075892 100755 --- a/src/source/git.rs +++ b/src/source/git.rs @@ -146,7 +146,10 @@ fn ensure_mirror(url: &str, mirror_dir: &Path, pkgname: &str) -> Result<()> { crate::log_info!("Cloning git mirror for {} ({})...", pkgname, url); let mut fo = FetchOptions::new(); let transfer_progress = TransferProgress::new(format!("git {}", pkgname)); - fo.remote_callbacks(remote_callbacks(Some(transfer_progress.bar()), url)); + fo.remote_callbacks(authenticated_remote_callbacks( + Some(transfer_progress.bar()), + url, + )); let mut builder = git2::build::RepoBuilder::new(); builder.fetch_options(fo); builder.bare(true); @@ -168,7 +171,10 @@ fn ensure_mirror(url: &str, mirror_dir: &Path, pkgname: &str) -> Result<()> { let mut fo = FetchOptions::new(); let transfer_progress = TransferProgress::new(format!("git {}", pkgname)); - fo.remote_callbacks(remote_callbacks(Some(transfer_progress.bar()), url)); + fo.remote_callbacks(authenticated_remote_callbacks( + Some(transfer_progress.bar()), + url, + )); // Fetch all remote refs (tags + heads). Empty refspec uses default. remote @@ -274,7 +280,10 @@ fn resolve_remote_head_like<'a>(repo: &'a Repository) -> Result, _label: &str) -> RemoteCallbacks<'static> { +pub(crate) fn authenticated_remote_callbacks( + progress_bar: Option, + _label: &str, +) -> RemoteCallbacks<'static> { let mut callbacks = RemoteCallbacks::new(); let mut credential_state = CredentialState::default(); diff --git a/src/source/mod.rs b/src/source/mod.rs index 02e9b27..22ca10d 100755 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -5,6 +5,8 @@ mod fetcher; mod git; pub mod hooks; +pub(crate) use git::authenticated_remote_callbacks; + use crate::package::PackageSpec; use anyhow::{Context, Result, bail}; use sha2::{Digest, Sha256};