From 0bd64aa5c8f7b3b4693b31052619f631d52a0321 Mon Sep 17 00:00:00 2001 From: Lin Yihai Date: Wed, 17 Jul 2024 09:47:58 +0800 Subject: [PATCH] fix: Do not downgrade with update --breaking if VersionReq is prerelease --- src/cargo/util/toml_mut/upgrade.rs | 45 ++++++++++++++++++++++++++++-- tests/testsuite/update.rs | 3 -- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/cargo/util/toml_mut/upgrade.rs b/src/cargo/util/toml_mut/upgrade.rs index 698fcab654c1..783d5a2a208e 100644 --- a/src/cargo/util/toml_mut/upgrade.rs +++ b/src/cargo/util/toml_mut/upgrade.rs @@ -18,9 +18,14 @@ pub(crate) fn upgrade_requirement( let comparators: CargoResult> = raw_req .comparators .into_iter() + // See rust-lang/cargo#14178 and rust-lang/cargo#13290 + .filter(|p| p.pre.is_empty() || matches_greater(p, version)) .map(|p| set_comparator(p, version)) .collect(); - let comparators = comparators?; + let comparators: Vec<_> = comparators?; + if comparators.is_empty() { + return Ok(None); + } let new_req = semver::VersionReq { comparators }; let mut new_req_text = new_req.to_string(); if new_req_text.starts_with('^') && !req.starts_with('^') { @@ -74,6 +79,33 @@ fn set_comparator( } } +// See https://github.com/dtolnay/semver/blob/master/src/eval.rs#L64 +fn matches_greater(cmp: &semver::Comparator, ver: &semver::Version) -> bool { + if ver.major != cmp.major { + return ver.major > cmp.major; + } + + match cmp.minor { + None => return false, + Some(minor) => { + if ver.minor != minor { + return ver.minor > minor; + } + } + } + + match cmp.patch { + None => return false, + Some(patch) => { + if ver.patch != patch { + return ver.patch > patch; + } + } + } + + ver.pre > cmp.pre +} + fn assign_partial_req( version: &semver::Version, mut pred: semver::Comparator, @@ -219,8 +251,15 @@ mod test { } #[test] - fn caret_prerelease() { - assert_req_bump("1.7.0", "2.0.0-beta.21", "1.7.0"); + fn greater_prerelease() { + assert_req_bump("1.7.0", "2.0.0-beta.21", None); + assert_req_bump("1.7.0", "=2.0.0-beta.21", None); + assert_req_bump("1.7.0", "~2.0.0-beta.21", None); + assert_req_bump("2.0.0-beta.20", "2.0.0-beta.21", None); + assert_req_bump("2.0.0-beta.21", "2.0.0-beta.21", None); + assert_req_bump("2.0.0-beta.22", "2.0.0-beta.21", "2.0.0-beta.22"); + assert_req_bump("2.0.0", "2.0.0-beta.21", "2.0.0"); + assert_req_bump("3.0.0", "2.0.0-beta.21", "3.0.0"); } } } diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs index 4d02ba6fb876..e99ea18af8a5 100644 --- a/tests/testsuite/update.rs +++ b/tests/testsuite/update.rs @@ -2646,9 +2646,6 @@ fn update_breaking_pre_release() { .masquerade_as_nightly_cargo(&["update-breaking"]) .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index -[UPGRADING] bar ^2.0.0-beta.21 -> ^1.7.0 -[LOCKING] 1 package to latest compatible version -[DOWNGRADING] bar v2.0.0-beta.21 -> v1.7.0 "#]]) .run();