Skip to content

Commit

Permalink
feat: Add prerelease upper bound semantic
Browse files Browse the repository at this point in the history
  • Loading branch information
linyihai committed Jul 9, 2024
1 parent 3a76b8c commit bff56de
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 27 deletions.
16 changes: 12 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ rusqlite = { version = "0.31.0", features = ["bundled"] }
rustfix = { version = "0.8.2", path = "crates/rustfix" }
same-file = "1.0.6"
security-framework = "2.10.0"
semver = { version = "1.0.22", features = ["serde"] }
semver = { version = "1.0.22", features = ["serde"], git = "https://github.com/linyihai/semver.git", branch = "prerelease-match"}
serde = "1.0.199"
serde-untagged = "0.1.5"
serde-value = "0.7.0"
Expand Down
31 changes: 14 additions & 17 deletions src/cargo/util/semver_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,12 @@ impl OptVersionReq {
}
}

/// Since Semver does not support prerelease versions,
/// the simplest implementation is taken here without comparing the prerelease section.
/// The logic here is temporary, we'll have to consider more boundary conditions later,
/// and we're not sure if this part of the functionality should be implemented in semver or cargo.
/// Similar to [`Self::matches`], but can be match any "Semver-compatible" pre-release version.
pub fn matches_prerelease(&self, version: &Version) -> bool {
if version.is_prerelease() {
let mut version = version.clone();
version.pre = semver::Prerelease::EMPTY;
return self.matches(&version);
if let OptVersionReq::Req(req) = self {
return req.matches_prerelease(version);
}
}
self.matches(version)
}
Expand Down Expand Up @@ -203,12 +200,12 @@ mod matches_prerelease {
// https://rust-lang.github.io/rfcs/3493-precise-pre-release-cargo-update.html#version-ranges-with-pre-release-upper-bounds
let cases = [
//
("1.2.3", "1.2.3-0", true), // bug, must be false
("1.2.3", "1.2.3-1", true), // bug, must be false
("1.2.3", "1.2.3-0", false), // bug, must be false
("1.2.3", "1.2.3-1", false), // bug, must be false
("1.2.3", "1.2.4-0", true),
//
(">=1.2.3", "1.2.3-0", true), // bug, must be false
(">=1.2.3", "1.2.3-1", true), // bug, must be false
(">=1.2.3", "1.2.3-0", false), // bug, must be false
(">=1.2.3", "1.2.3-1", false), // bug, must be false
(">=1.2.3", "1.2.4-0", true),
//
(">1.2.3", "1.2.3-0", false),
Expand All @@ -217,18 +214,18 @@ mod matches_prerelease {
//
(">1.2.3, <1.2.4", "1.2.3-0", false),
(">1.2.3, <1.2.4", "1.2.3-1", false),
(">1.2.3, <1.2.4", "1.2.4-0", false), // upper bound semantic
(">1.2.3, <1.2.4", "1.2.4-0", true), // upper bound semantic
//
(">=1.2.3, <1.2.4", "1.2.3-0", true), // bug, must be false
(">=1.2.3, <1.2.4", "1.2.3-1", true), // bug, must be false
(">=1.2.3, <1.2.4", "1.2.4-0", false), // upper bound semantic
(">=1.2.3, <1.2.4", "1.2.3-0", false), // bug, must be false
(">=1.2.3, <1.2.4", "1.2.3-1", false), // bug, must be false
(">=1.2.3, <1.2.4", "1.2.4-0", true), // upper bound semantic
//
(">1.2.3, <=1.2.4", "1.2.3-0", false),
(">1.2.3, <=1.2.4", "1.2.3-1", false),
(">1.2.3, <=1.2.4", "1.2.4-0", true),
//
(">=1.2.3-0, <1.2.3", "1.2.3-0", false), // upper bound semantic
(">=1.2.3-0, <1.2.3", "1.2.3-1", false), // upper bound semantic
(">=1.2.3-0, <1.2.3", "1.2.3-0", true), // upper bound semantic
(">=1.2.3-0, <1.2.3", "1.2.3-1", true), // upper bound semantic
(">=1.2.3-0, <1.2.3", "1.2.4-0", false),
];
for (req, ver, expected) in cases {
Expand Down
41 changes: 36 additions & 5 deletions tests/testsuite/precise_pre_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn update_pre_release() {
fn update_pre_release_differ() {
cargo_test_support::registry::init();

for version in ["0.1.2", "0.1.2-pre.0", "0.1.2-pre.1"] {
for version in ["0.1.2-pre.0", "0.1.2", "0.1.3-pre.1", "0.1.3", "0.2.0-0"] {
cargo_test_support::registry::Package::new("my-dependency", version).publish();
}

Expand All @@ -96,23 +96,54 @@ fn update_pre_release_differ() {
.build();

p.cargo("update -p my-dependency --precise 0.1.2-pre.0 -Zunstable-options")
.masquerade_as_nightly_cargo(&["precise-pre-release"])
.with_status(101)
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for the requirement `my-dependency = "^0.1.2"`
candidate versions found which didn't match: 0.1.2-pre.0
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `package v0.0.0 ([ROOT]/foo)`
if you are looking for the prerelease package it needs to be specified explicitly
my-dependency = { version = "0.1.2-pre.0" }
perhaps a crate was updated and forgotten to be re-vendored?
"#]])
.run();

p.cargo("update -p my-dependency --precise 0.2.0-0 -Zunstable-options")
.masquerade_as_nightly_cargo(&["precise-pre-release"])
.with_status(101)
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for the requirement `my-dependency = "^0.1.2"`
candidate versions found which didn't match: 0.2.0-0
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `package v0.0.0 ([ROOT]/foo)`
if you are looking for the prerelease package it needs to be specified explicitly
my-dependency = { version = "0.2.0-0" }
perhaps a crate was updated and forgotten to be re-vendored?
"#]])
.run();

p.cargo("update -p my-dependency --precise 0.1.3 -Zunstable-options")
.masquerade_as_nightly_cargo(&["precise-pre-release"])
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[DOWNGRADING] my-dependency v0.1.2 -> v0.1.2-pre.0
"#]])
.run();

p.cargo("update -p my-dependency --precise 0.1.2-pre.1 -Zunstable-options")
p.cargo("update -p my-dependency --precise 0.1.3-pre.1 -Zunstable-options")
.masquerade_as_nightly_cargo(&["precise-pre-release"])
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[UPDATING] my-dependency v0.1.2-pre.0 -> v0.1.2-pre.1
[DOWNGRADING] my-dependency v0.1.3 -> v0.1.3-pre.1
"#]])
.run();

let lockfile = p.read_lockfile();
assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.2-pre.1\""));
assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.3-pre.1\""));
}

0 comments on commit bff56de

Please sign in to comment.