Skip to content

Commit a7917fd

Browse files
committed
Auto merge of #14250 - linyihai:update-breaking-prerelease, r=weihanglo
Don't downgrade on prerelease `VersionReq` when update with --breaking. ### What does this PR try to resolve? Do nothing with prerelease when update with `--breaking`. Fixes #14178 ### How should we test and review this PR? Previous commit add a test, next commit to fix and update. ### Additional information
2 parents 9bda502 + 9e2701a commit a7917fd

File tree

2 files changed

+137
-3
lines changed

2 files changed

+137
-3
lines changed

Diff for: src/cargo/util/toml_mut/upgrade.rs

+46-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ pub(crate) fn upgrade_requirement(
1515
// Empty matches everything, no-change.
1616
Ok(None)
1717
} else {
18-
let comparators: CargoResult<Vec<_>> = raw_req
18+
let comparators: Vec<_> = raw_req
1919
.comparators
2020
.into_iter()
21+
// Don't downgrade if pre-release was used, see https://github.com/rust-lang/cargo/issues/14178 and https://github.com/rust-lang/cargo/issues/13290.
22+
.filter(|p| p.pre.is_empty() || matches_greater(p, version))
2123
.map(|p| set_comparator(p, version))
22-
.collect();
23-
let comparators = comparators?;
24+
.collect::<CargoResult<_>>()?;
25+
if comparators.is_empty() {
26+
return Ok(None);
27+
}
2428
let new_req = semver::VersionReq { comparators };
2529
let mut new_req_text = new_req.to_string();
2630
if new_req_text.starts_with('^') && !req.starts_with('^') {
@@ -74,6 +78,33 @@ fn set_comparator(
7478
}
7579
}
7680

81+
// See https://github.com/dtolnay/semver/blob/69efd3cc770ead273a06ad1788477b3092996d29/src/eval.rs#L64-L88
82+
fn matches_greater(cmp: &semver::Comparator, ver: &semver::Version) -> bool {
83+
if ver.major != cmp.major {
84+
return ver.major > cmp.major;
85+
}
86+
87+
match cmp.minor {
88+
None => return false,
89+
Some(minor) => {
90+
if ver.minor != minor {
91+
return ver.minor > minor;
92+
}
93+
}
94+
}
95+
96+
match cmp.patch {
97+
None => return false,
98+
Some(patch) => {
99+
if ver.patch != patch {
100+
return ver.patch > patch;
101+
}
102+
}
103+
}
104+
105+
ver.pre > cmp.pre
106+
}
107+
77108
fn assign_partial_req(
78109
version: &semver::Version,
79110
mut pred: semver::Comparator,
@@ -217,5 +248,17 @@ mod test {
217248
assert_req_bump("1.1.1", "=1.0.0", "=1.1.1");
218249
assert_req_bump("2.0.0", "=1.0.0", "=2.0.0");
219250
}
251+
252+
#[test]
253+
fn greater_prerelease() {
254+
assert_req_bump("1.7.0", "2.0.0-beta.21", None);
255+
assert_req_bump("1.7.0", "=2.0.0-beta.21", None);
256+
assert_req_bump("1.7.0", "~2.0.0-beta.21", None);
257+
assert_req_bump("2.0.0-beta.20", "2.0.0-beta.21", None);
258+
assert_req_bump("2.0.0-beta.21", "2.0.0-beta.21", None);
259+
assert_req_bump("2.0.0-beta.22", "2.0.0-beta.21", "2.0.0-beta.22");
260+
assert_req_bump("2.0.0", "2.0.0-beta.21", "2.0.0");
261+
assert_req_bump("3.0.0", "2.0.0-beta.21", "3.0.0");
262+
}
220263
}
221264
}

Diff for: tests/testsuite/update.rs

+91
Original file line numberDiff line numberDiff line change
@@ -2619,3 +2619,94 @@ fn update_breaking_mixed_pinning_renaming() {
26192619
"#]],
26202620
);
26212621
}
2622+
2623+
#[cargo_test]
2624+
fn update_breaking_pre_release_downgrade() {
2625+
Package::new("bar", "2.0.0-beta.21").publish();
2626+
2627+
let p = project()
2628+
.file(
2629+
"Cargo.toml",
2630+
r#"
2631+
[package]
2632+
name = "foo"
2633+
version = "0.0.1"
2634+
edition = "2015"
2635+
authors = []
2636+
2637+
[dependencies]
2638+
bar = "2.0.0-beta.21"
2639+
"#,
2640+
)
2641+
.file("src/lib.rs", "")
2642+
.build();
2643+
2644+
p.cargo("generate-lockfile").run();
2645+
2646+
// The purpose of this test is
2647+
// to demonstrate that `update --breaking` will not try to downgrade to the latest stable version (1.7.0),
2648+
// but will rather keep the latest pre-release (2.0.0-beta.21).
2649+
Package::new("bar", "1.7.0").publish();
2650+
p.cargo("update -Zunstable-options --breaking bar")
2651+
.masquerade_as_nightly_cargo(&["update-breaking"])
2652+
.with_stderr_data(str![[r#"
2653+
[UPDATING] `dummy-registry` index
2654+
2655+
"#]])
2656+
.run();
2657+
}
2658+
2659+
#[cargo_test]
2660+
fn update_breaking_pre_release_upgrade() {
2661+
Package::new("bar", "2.0.0-beta.21").publish();
2662+
2663+
let p = project()
2664+
.file(
2665+
"Cargo.toml",
2666+
r#"
2667+
[package]
2668+
name = "foo"
2669+
version = "0.0.1"
2670+
edition = "2015"
2671+
authors = []
2672+
2673+
[dependencies]
2674+
bar = "2.0.0-beta.21"
2675+
"#,
2676+
)
2677+
.file("src/lib.rs", "")
2678+
.build();
2679+
2680+
p.cargo("generate-lockfile").run();
2681+
2682+
// TODO: `2.0.0-beta.21` can be upgraded to `2.0.0-beta.22`
2683+
Package::new("bar", "2.0.0-beta.22").publish();
2684+
p.cargo("update -Zunstable-options --breaking bar")
2685+
.masquerade_as_nightly_cargo(&["update-breaking"])
2686+
.with_stderr_data(str![[r#"
2687+
[UPDATING] `dummy-registry` index
2688+
2689+
"#]])
2690+
.run();
2691+
// TODO: `2.0.0-beta.21` can be upgraded to `2.0.0`
2692+
Package::new("bar", "2.0.0").publish();
2693+
p.cargo("update -Zunstable-options --breaking bar")
2694+
.masquerade_as_nightly_cargo(&["update-breaking"])
2695+
.with_stderr_data(str![[r#"
2696+
[UPDATING] `dummy-registry` index
2697+
2698+
"#]])
2699+
.run();
2700+
2701+
Package::new("bar", "3.0.0").publish();
2702+
p.cargo("update -Zunstable-options --breaking bar")
2703+
.masquerade_as_nightly_cargo(&["update-breaking"])
2704+
.with_stderr_data(str![[r#"
2705+
[UPDATING] `dummy-registry` index
2706+
[UPGRADING] bar ^2.0.0-beta.21 -> ^3.0.0
2707+
[LOCKING] 1 package to latest compatible version
2708+
[UPDATING] bar v2.0.0-beta.21 -> v3.0.0
2709+
2710+
"#]])
2711+
.run();
2712+
}

0 commit comments

Comments
 (0)