Skip to content

Commit 55cfaf9

Browse files
authored
Apply lockfile marker normalization for fork markers (#18116)
While dependency markers get a roundtrip through simplify/complexify ([crates/uv-resolver/src/lock/mod.rs#L4846-L4848](https://github.com/astral-sh/uv/blob/3223b1c39f8011a4460f2b5d56ace19e5d26e16d/crates/uv-resolver/src/lock/mod.rs#L4846-L4848), #15994), this treatment was missing for fork markers, causing errors with `--locked --refresh` on a fresh lockfile. Fixes #16839 Closes #18024
1 parent 7ba5946 commit 55cfaf9

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

crates/uv-resolver/src/lock/mod.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,19 @@ impl Lock {
326326

327327
// If there are multiple distributions for the same package, include the markers of all
328328
// forks that included the current distribution.
329+
//
330+
// Normalize with a simplify/complexify round-trip through `requires-python` to
331+
// match markers deserialized from the lockfile (which get complexified on read).
329332
let fork_markers = if duplicates.contains(dist.name()) {
330333
resolution
331334
.fork_markers
332335
.iter()
333336
.filter(|fork_markers| !fork_markers.is_disjoint(dist.marker))
334-
.copied()
337+
.map(|marker| {
338+
let simplified =
339+
SimplifiedMarkerTree::new(&requires_python, marker.combined());
340+
UniversalMarker::from_combined(simplified.into_marker(&requires_python))
341+
})
335342
.collect()
336343
} else {
337344
vec![]
@@ -433,6 +440,18 @@ impl Lock {
433440
fork_strategy: resolution.options.fork_strategy,
434441
exclude_newer: resolution.options.exclude_newer.clone().into(),
435442
};
443+
// Normalize fork markers with a simplify/complexify round-trip through
444+
// `requires-python`. This ensures markers from the resolver (which don't include
445+
// `requires-python` bounds) match markers deserialized from the lockfile (which get
446+
// complexified on read).
447+
let fork_markers = resolution
448+
.fork_markers
449+
.iter()
450+
.map(|marker| {
451+
let simplified = SimplifiedMarkerTree::new(&requires_python, marker.combined());
452+
UniversalMarker::from_combined(simplified.into_marker(&requires_python))
453+
})
454+
.collect();
436455
let lock = Self::new(
437456
VERSION,
438457
REVISION,
@@ -443,7 +462,7 @@ impl Lock {
443462
Conflicts::empty(),
444463
vec![],
445464
vec![],
446-
resolution.fork_markers.clone(),
465+
fork_markers,
447466
)?;
448467
Ok(lock)
449468
}

crates/uv/tests/it/lock.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4597,6 +4597,50 @@ fn lock_upgrade_log_multi_version() -> Result<()> {
45974597
Ok(())
45984598
}
45994599

4600+
/// `--upgrade --dry-run` should not report changes when the lockfile is up-to-date with
4601+
/// fork markers.
4602+
///
4603+
/// Regression test for: <https://github.com/astral-sh/uv/issues/16839>
4604+
#[test]
4605+
fn lock_upgrade_dry_run_multi_version() -> Result<()> {
4606+
let context = uv_test::test_context!("3.12");
4607+
4608+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
4609+
pyproject_toml.write_str(
4610+
r#"
4611+
[project]
4612+
name = "project"
4613+
version = "0.1.0"
4614+
requires-python = ">=3.12"
4615+
dependencies = [
4616+
"markupsafe<2 ; sys_platform != 'win32'",
4617+
"markupsafe==2.0.0 ; sys_platform == 'win32'"
4618+
]
4619+
"#,
4620+
)?;
4621+
4622+
uv_snapshot!(context.filters(), context.lock(), @"
4623+
success: true
4624+
exit_code: 0
4625+
----- stdout -----
4626+
4627+
----- stderr -----
4628+
Resolved 3 packages in [TIME]
4629+
");
4630+
4631+
uv_snapshot!(context.filters(), context.lock().arg("--upgrade").arg("--dry-run"), @"
4632+
success: true
4633+
exit_code: 0
4634+
----- stdout -----
4635+
4636+
----- stderr -----
4637+
Resolved 3 packages in [TIME]
4638+
No lockfile changes detected
4639+
");
4640+
4641+
Ok(())
4642+
}
4643+
46004644
/// Respect the locked version in an existing lockfile.
46014645
#[test]
46024646
fn lock_preference() -> Result<()> {

0 commit comments

Comments
 (0)