From 55902cd6f7505c4ca609bd26610ebb525512e58b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 07:10:14 +0000 Subject: [PATCH] Retire bare uv manifest overrides of old uv The nightly e2e-full legs of e2e_redirect_uv_build for uv 0.2.37, 0.3.5, 0.4.30 and 0.5.3 fail since #1453 added the orphan-unwind step: after rollback retires a leftover hosted override, uv.lock still holds `[manifest] overrides = [{ name = "six", specifier = "==1.17.0" }]`. uv before 0.5.6 records the override the hosted rewrite adds without folding in its [tool.uv.sources] url, and the restore only dropped records that carry the hosted url. Drop the bare `==` record of the pin under the rewrite's ownership mark too; a user's own unmarked pin keeps its record (#411). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012v7idpMckM6PU5mBKBBmmg --- .../src/patch/redirect/upstream/uv.rs | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/crates/socket-patch-core/src/patch/redirect/upstream/uv.rs b/crates/socket-patch-core/src/patch/redirect/upstream/uv.rs index c25ed2b6d..648282aae 100644 --- a/crates/socket-patch-core/src/patch/redirect/upstream/uv.rs +++ b/crates/socket-patch-core/src/patch/redirect/upstream/uv.rs @@ -1639,10 +1639,22 @@ fn restore_requirement_array( .and_then(Value::as_str) .and_then(|u| ctx.hosted_uuid(u)) .is_some_and(|u| u == hit.uuid); + let rewrite_override = + matches!(declared, Declared::Manifest("overrides")) && transitive_override; + // uv before 0.5.6 records the rewrite's override without folding in + // its `[tool.uv.sources]` url: `{ name, specifier = "==" }`. + let bare_pin = entry.get("url").is_none() + && entry.get("marker").is_none() + && entry.get("specifier").and_then(Value::as_str) + == Some(format!("=={}", hit.version).as_str()); + if names_hit && rewrite_override && bare_pin { + drop.push(i); + continue; + } if !names_hit || !hosted { continue; } - if matches!(declared, Declared::Manifest("overrides")) && transitive_override { + if rewrite_override { drop.push(i); continue; } @@ -2155,6 +2167,34 @@ mod declaration_tests { assert!(!out.contains("[manifest]"), "{out}"); } + /// uv before 0.5.6 records the rewrite's override as a bare + /// `{ name, specifier }` with no url: it is dropped with the marked pin, + /// while the same record of a user's own pin stays. + #[test] + fn bare_manifest_override_of_the_rewrite_is_dropped() { + let bare = spec("==1.16.0", None); + let lock_text = format!( + "{}\n[manifest]\noverrides = [{bare}]\n", + lock( + &[spec("==2.8.2", None).replace("six", "python-dateutil")], + &[] + ) + ); + let added = format!( + "{HEAD}dependencies = [\"python-dateutil==2.8.2\"]\n\n[tool.uv]\n\ + override-dependencies = [\n {}\n \"six==1.16.0\",\n]\n", + crate::utils::python_script::HOSTED_OVERRIDE_MARK + ); + let out = unwind(&added, &lock_text).unwrap(); + assert!(!out.contains("[manifest]"), "{out}"); + let user = format!( + "{HEAD}dependencies = [\"python-dateutil==2.8.2\"]\n\n[tool.uv]\n\ + override-dependencies = [\"six==1.16.0\"]\n" + ); + let out = unwind(&user, &lock_text).unwrap(); + assert!(out.contains(&format!("overrides = [{bare}]")), "{out}"); + } + /// #606 (a): a pin in `dependencies` and a floor in an extra. #[test] fn dependencies_and_extra_with_different_specifiers() {