diff --git a/crates/pixi_command_dispatcher/tests/integration/snapshots/integration__simple_test.snap b/crates/pixi_command_dispatcher/tests/integration/snapshots/integration__simple_test.snap index cde84dcca5..fd3d8ebd34 100644 --- a/crates/pixi_command_dispatcher/tests/integration/snapshots/integration__simple_test.snap +++ b/crates/pixi_command_dispatcher/tests/integration/snapshots/integration__simple_test.snap @@ -6,12 +6,13 @@ Pixi solve (test@[PLATFORM]) ├── Git Checkout (file://[LOCAL_GIT_REPO]#[GIT_HASH]) ├── Source metadata (foobar-desktop @ git+file://[LOCAL_GIT_REPO]?subdirectory=recipe&rev=[GIT_REF]#[GIT_HASH]) │ ├── Build backend metadata (git+file://[LOCAL_GIT_REPO]?subdirectory=recipe&rev=[GIT_REF]#[GIT_HASH]) +│ │ ├── Git Checkout (file://[LOCAL_GIT_REPO]#[GIT_HASH]) │ │ └── Instantiate backend (pixi-build-rattler-build) -│ │ └── Conda solve #5 +│ │ └── Conda solve #6 │ └── Source record (foobar-desktop @ git+file://[LOCAL_GIT_REPO]?subdirectory=recipe&rev=[GIT_REF]#[GIT_HASH]) ├── Source metadata (foobar @ git+file://[LOCAL_GIT_REPO]?subdirectory=recipe&rev=[GIT_REF]#[GIT_HASH]) │ └── Source record (foobar @ git+file://[LOCAL_GIT_REPO]?subdirectory=recipe&rev=[GIT_REF]#[GIT_HASH]) -└── Conda solve #9 +└── Conda solve #10 Pixi install (test-env) ├── Backend source build (foobar-desktop) └── Backend source build (foobar) diff --git a/crates/pixi_compute_sources/src/git.rs b/crates/pixi_compute_sources/src/git.rs index 7717b065b6..54ddf58d1e 100644 --- a/crates/pixi_compute_sources/src/git.rs +++ b/crates/pixi_compute_sources/src/git.rs @@ -95,16 +95,19 @@ impl LifecycleKind for GitReporterLifecycle { } } -/// Dedup key for a git checkout. Keyed on [`RepositoryReference`] -/// (normalized URL + reference, no `precise`) so callers that differ -/// only in whether they pre-resolved the commit still dedup. +/// Dedup key for a git checkout. Keyed on the full [`GitUrl`]: URL, +/// reference, AND `precise` commit, so a caller asking for a specific +/// commit doesn't collide with one asking only for the branch. +/// Stripping `precise` from the key let `checkout_pinned_source(A)` +/// silently return the branch's HEAD instead of commit `A` +/// (prefix-dev/pixi#6073). #[derive(Clone, Debug, Display, Hash, PartialEq, Eq)] -#[display("{}@{}", _0.url.as_url(), _0.reference)] -pub struct CheckoutGit(RepositoryReference); +#[display("{}@{}", _0.repository(), _0.reference())] +pub struct CheckoutGit(GitUrl); impl CheckoutGit { pub fn new(git_url: &GitUrl) -> Self { - Self(RepositoryReference::from(git_url)) + Self(git_url.clone()) } } @@ -119,8 +122,9 @@ impl Key for CheckoutGit { let semaphore = data.git_checkout_semaphore().cloned(); let reporter = data.git_checkout_reporter().cloned(); + let reporter_env = RepositoryReference::from(&self.0); let lifecycle = - ReporterLifecycle::::queued(reporter.as_deref(), &self.0); + ReporterLifecycle::::queued(reporter.as_deref(), &reporter_env); let _permit = match semaphore.as_ref() { Some(s) => Some( @@ -132,14 +136,12 @@ impl Key for CheckoutGit { }; let _lifecycle = lifecycle.start(); - // `from_reference` auto-fills `precise` from a full-commit - // reference, so the resolver skips ref-resolution when it can. - let git_url = - GitUrl::from_reference(self.0.url.clone().into_url(), self.0.reference.clone()); - + // Pass the original `GitUrl` straight through so the resolver + // honours `precise` when set (pinned checkout) and advances to + // the branch HEAD when not (fresh resolve). Arc::new( resolver - .fetch(git_url, client, cache_dir.into_std_path_buf(), None) + .fetch(self.0.clone(), client, cache_dir.into_std_path_buf(), None) .await, ) }