-
-
Notifications
You must be signed in to change notification settings - Fork 130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add matches_prerelease
to allow update to prerelease version if it meets Semver compatible
#321
Conversation
68f2b8d
to
5b8de4e
Compare
Sorry, need to address the node test firstly |
5b8de4e
to
174ec3f
Compare
Oh, In this case, I didn't know if there was a corresponding pre-release compatibility match test for node, so I bypassed the node test |
Experimented with this branch, definitely found cases I was not expecting. For example the requirement |
Oops,the paritial-version doesn't take into consideration. Thank you for your feedback. |
Thanks for the update! I tried again and found more examples that didn't match my expectations:
These are of course just "my expectations" and the "correct behavior" may not match what's in my head at the moment. |
1693e4b
to
34bec6c
Compare
34bec6c
to
2b5a7d3
Compare
My apologies. My Last commit have some regression and I am eager to correct it. I test you example and use it to explain the match logic
|
Thanks for the update!
I tried again and found more examples:
|
I am very appreciate your feedback.
This had been corrected. Then for comparison, I collated the versions that currently have pre-release comparison logic
At present, I think this version is much better than the first commit, but I feel that there are still some corners that have not been sorted out, which may be discussed separately next time |
Thank you for the prompt fixes. I only had a brief chance to look at this today, and it requires more thought than I had available. I will try and look at it again next week. |
Should we be trialing this in Cargo under a nightly feature before trying to merge this into a stable API? |
src/eval.rs
Outdated
@@ -26,6 +30,41 @@ pub(crate) fn matches_req(req: &VersionReq, ver: &Version) -> bool { | |||
pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool { | |||
matches_impl(cmp, ver) && (ver.pre.is_empty() || pre_is_compatible(cmp, ver)) | |||
} | |||
// If VersionReq missing Minor, Patch, then filling them with 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra newline
// If VersionReq missing Minor, Patch, then filling them with 0 | |
// If VersionReq missing Minor, Patch, then filling them with 0 |
tests/test_matches_prerelease.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I got everything right, these are the current-proposed semantic
(bold texts are semantic missing in #321 (comment) and guessed by me).
In both matches and matches_prerelease columns the equivalent matching semantic is using the old VersionReq::matches
minus this prelease specific behavior.
req | matches | matches_prerelease |
---|---|---|
Op::Exact |
||
=I.J.K | =I.J.K | >=I.J.K, <I.J.(K+1)-0 |
=I.J | >=I.J.0, <I.(J+1).0 | >=I.J.0, <I.(J+1).0-0 |
=I | >=I.0.0, <(I+1).0.0 | >=I.0.0, <(I+1).0.0-0 |
Op::Greater |
||
>I.J.K | >I.J.K | >I.J.K |
>I.J | >=I.(J+1).0 | >=I.(J+1).0-0 |
>I | >=(I+1).0.0 | >=(I+1).0.0-0 |
Op::GreaterEq |
||
>=I.J.K | >=I.J.K | >=I.J.K |
>=I.J | >=I.J.0 | >=I.J.0 |
>=I | >=I.0.0 | >=I.0.0 |
Op::Less |
||
<I.J.K | <I.J.K | <I.J.K |
<I.J | <I.J.0 | <I.J.0 |
<I | <I.0.0 | <I.0.0 |
Op::LessEq |
||
<=I.J.K | <=I.J.K | <=I.J.K |
<=I.J | <I.(J+1).0 | <I.(J+1).0-0 |
<=I | <(I+1).0.0 | <(I+1).0.0-0 |
Op::Tilde |
||
~I.J.K | >=I.J.K, <I.(J+1).0 | >=I.J.K, <I.(J+1).0-0 |
~I.J | =I.J | >=I.J.0, <I.(J+1).0-0 |
~I | =I | >=I.0.0, <(I+1).0.0-0 |
Op::Caret |
||
^I.J.K (for I>0) | >=I.J.K, <(I+1).0.0 | >=I.J.K, <(I+1).0.0-0 |
^0.J.K (for J>0) | >=0.J.K, <0.(J+1).0 | >=0.J.K, <0.(J+1).0-0 |
^0.0.K | =0.0.K | >=0.0.K, <0.0.(K+1)-0 |
^I.J | ^I.J.0 | >=I.J.0, <(I+1).0.0-0 |
^0.0 | =0.0 | >=0.0.0, <0.1.0-0 |
^I | =I | >=I.0.0, <(I+1).0.0-0 |
Op::Wildcard |
||
I.J.* |
=I.J | =I.J |
I.* or I.*.* |
=I | =I |
table markdown source
| req | matches | matches_prerelease |
|------------------|---------------------|------------------------|
| `Op::Exact` | | |
| =I.J.K | =I.J.K | >=I.J.K, <I.J.(K+1)-0 |
| =I.J | >=I.J.0, <I.(J+1).0 | >=I.J.0, <I.(J+1).0-0 |
| =I | >=I.0.0, <(I+1).0.0 | >=I.0.0, <(I+1).0.0-0 |
| `Op::Greater` | | |
| >I.J.K | >I.J.K | **>I.J.K** |
| >I.J | >=I.(J+1).0 | >=I.(J+1).0-0 |
| >I | >=(I+1).0.0 | >=(I+1).0.0-0 |
| `Op::GreaterEq` | | |
| >=I.J.K | >=I.J.K | **>=I.J.K** |
| >=I.J | >=I.J.0 | >=I.J.0 |
| >=I | >=I.0.0 | >=I.0.0 |
| `Op::Less` | | |
| <I.J.K | <I.J.K | **<I.J.K** |
| <I.J | <I.J.0 | <I.J.0 |
| <I | <I.0.0 | <I.0.0 |
| `Op::LessEq` | | |
| <=I.J.K | <=I.J.K | **<=I.J.K** |
| <=I.J | <I.(J+1).0 | <I.(J+1).0-0 |
| <=I | <(I+1).0.0 | <(I+1).0.0-0 |
| `Op::Tilde` | | |
| ~I.J.K | >=I.J.K, <I.(J+1).0 | >=I.J.K, <I.(J+1).0-0 |
| ~I.J | =I.J | >=I.J.0, <I.(J+1).0-0 |
| ~I | =I | >=I.0.0, <(I+1).0.0-0 |
| `Op::Caret` | | |
| ^I.J.K (for I>0) | >=I.J.K, <(I+1).0.0 | >=I.J.K, <(I+1).0.0-0 |
| ^0.J.K (for J>0) | >=0.J.K, <0.(J+1).0 | >=0.J.K, <0.(J+1).0-0 |
| ^0.0.K | =0.0.K | >=0.0.K, <0.0.(K+1)-0 |
| ^I.J | ^I.J.0 | >=I.J.0, <(I+1).0.0-0 |
| ^0.0 | =0.0 | >=0.0.0, <0.1.0-0 |
| ^I | =I | >=I.0.0, <(I+1).0.0-0 |
| `Op::Wildcard` | | |
| `I.J.*` | =I.J | =I.J |
| `I.*` or `I.*.*` | =I | =I |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@linyihai Please help correct if anything wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In both matches and matches_prerelease columns the equivalent matching semantic is using the old VersionReq::matches.
The two are different, even if they are same literally
In the matches_prerelease
proposed semantic, it doesn't follow the limit
Lines 14 to 21 in 69efd3c
// If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it | |
// will only be allowed to satisfy req if at least one comparator with the | |
// same major.minor.patch also has a prerelease tag. | |
for cmp in &req.comparators { | |
if pre_is_compatible(cmp, ver) { | |
return true; | |
} | |
} |
For example, see playground example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yean I forgot that part. It's the old matches minus prerelease speicial treatment, right?
diff --git a/src/eval.rs b/src/eval.rs
index e6e3894..6cdf99d 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -7,20 +7,7 @@ pub(crate) fn matches_req(req: &VersionReq, ver: &Version) -> bool {
}
}
- if ver.pre.is_empty() {
- return true;
- }
-
- // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it
- // will only be allowed to satisfy req if at least one comparator with the
- // same major.minor.patch also has a prerelease tag.
- for cmp in &req.comparators {
- if pre_is_compatible(cmp, ver) {
- return true;
- }
- }
-
- false
+ true
}
pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It equivalents what you said, but I add a flag to sidestep that
if ver.pre.is_empty() || prerelease_matches {
return true;
}
rust-lang/rfcs#3493 is the only customer of this features now. And the BTW, rust-lang/rfcs#3493 doesn't give all scenes need to be considered, it only give a
And I found I haven't read fully The semantic versioner for npm, who knows what inspiration this might bring In short, it is better to carry this implementation into Cargo, and can be better combined with cargo design |
5861ac2
to
3464fd1
Compare
By this commit, these stuffs have been added:
I found the diffenence between
If my assumption is correct, then the |
Thank you for all the work you put into this! The details here are tricky and overwhelming and I really appreciate you sticking with it. Compatibility with npm is nice but not required. Starting with their semantics was a very good idea for a place to start, someone else thought this was the right choice. But, we have every right to decide we want different semantics if that's what we decide we need. I was able to reproduce the semantics as of 3464fd1 in my project. The diff is mostly boilerplate. The only two exceptions were the lower bound for I've assumed that if |
feat: Add matches_prerelease semantic ### What does this PR try to resolve? One implementaion for #13290 Thanks to `@Eh2406` feedback, a working version came out, and I think it should be able to test under the nightly feature. This PR proposes a `matches_prerelease semantic`. | req | matches | matches_prerelease | matches_prerelease_mirror_node [<sub>2<sub>](#mirror-node) | |------------------|---------------------|------------------------| ----------------------------------| | `Op::Exact` | | | | | =I.J.K | =I.J.K | >=I.J.K, <I.J.(K+1)-0 | >=I.J.K, <I.J.(K+1)-0 | | =I.J | >=I.J.0, <I.(J+1).0 | >=I.J.0, <I.(J+1).0-0 | >=I.J.0-0, <I.(J+1).0-0 | | =I | >=I.0.0, <(I+1).0.0 | >=I.0.0, <(I+1).0.0-0 | >=I.0.0-0, <(I+1).0.0-0 | | `Op::Greater` | | | | | >I.J.K | >I.J.K | >I.J.K | >I.J.K | | >I.J | >=I.(J+1).0 | >=I.(J+1).0-0 | >=I.(J+1).0-0 | | >I | >=(I+1).0.0 | >=(I+1).0.0-0 | >=(I+1).0.0-0 | | `Op::GreaterEq` | | | | | >=I.J.K | >=I.J.K | >=I.J.K | >=I.J.K | | >=I.J | >=I.J.0 | >=I.J.0 | >=I.J.0-0 | | >=I | >=I.0.0 | >=I.0.0 | >=I.0.0-0 | | `Op::Less` | | | | | <I.J.K | <I.J.K | <I.J.K or I.J.K-0 depends [<sub>1<sub>](#op-less) | <I.J.K | | <I.J | <I.J.0 | <I.J.0-0 | <I.J.0-0 | | <I | <I.0.0 | <I.0.0-0 | <I.0.0-0 | | `Op::LessEq` | | | | | <=I.J.K | <=I.J.K | <=I.J.K | <=I.J.K | | <=I.J | <I.(J+1).0 | <I.(J+1).0-0 | <I.(J+1).0-0 | | <=I | <(I+1).0.0 | <(I+1).0.0-0 | <(I+1).0.0-0 | | `Op::Tilde` | | | | | ~I.J.K | >=I.J.K, <I.(J+1).0 | >=I.J.K, <I.(J+1).0-0 | >=I.J.K, <I.(J+1).0-0 | | ~I.J | =I.J | >=I.J.0, <I.(J+1).0-0 | >=I.J.0, <I.(J+1).0-0 | | ~I | =I | >=I.0.0, <(I+1).0.0-0 | >=I.0.0, <(I+1).0.0-0 | | `Op::Caret` | | | | | ^I.J.K (for I>0) | >=I.J.K, <(I+1).0.0 | >=I.J.K, <(I+1).0.0-0 | >=I.J.K, <(I+1).0.0-0 | | ^0.J.K (for J>0) | >=0.J.K, <0.(J+1).0 | >=0.J.K, <0.(J+1).0-0 | >=0.J.K-0, <0.(J+1).0-0 | | ^0.0.K | =0.0.K | >=0.0.K, <0.0.(K+1)-0 | >=0.J.K-0, <0.(J+1).0-0 | | ^I.J | ^I.J.0 | >=I.J.0, <(I+1).0.0-0 | >=I.J.0-0, <(I+1).0.0-0 | | ^0.0 | =0.0 | >=0.0.0, <0.1.0-0 | >=0.0.0-0, <0.1.0-0 | | ^I | =I | >=I.0.0, <(I+1).0.0-0 | >=I.0.0-0, <(I+1).0.0-0 | | `Op::Wildcard` | | | | | `I.J.*` | =I.J | >=I.J.0, <I.(J+1).0-0 | >=I.J.0-0, <I.(J+1).0-0 | | `I.*` or `I.*.*` | =I | >=I.0.0, <(I+1).0.0-0 | >=I.0.0-0, <(I+1).0.0-0 | Notes: <div id="op-less"></div> - `<I.J.K`: This is equivalent to `<I.J.K-0` if no lower bound or the lower bound isn't pre-release, otherwise this is equivalent to `<I.J.K`. <div id="mirror-node"></div> - [matches_prerelease_mirror_node](dtolnay/semver@3464fd1) is yet another implementation of [node semver compatibility](https://github.com/npm/node-semver?tab=readme-ov-file#semver1----the-semantic-versioner-for-npm) (with [includePrerelease=true](https://github.com/npm/node-semver?tab=readme-ov-file#functions)) test. This is extrapolated from the test cases and is not necessarily the same as the node implementation Besides, the proposed semtantic left a [unsolved issuse ](dtolnay/semver#321 (comment)), I don't have clear idea to handle it. ### How should we test and review this PR? The tests in `src/cargo/util/semver_eval_ext.rs` are designed to reflect current semantic. ### Additional information Migrated from dtolnay/semver#321 TBO, this feature was not conceived in advance plus the semantic is unclear at first. I need to experiment step by step and find out what I think makes sense. My experiment can be seen this [comment](#13290 (comment)).
Is there any plan to merge this? |
I doubt there is in the short term. The Cargo Team is |
The proposed semantics isn't determinate, welcome any ideas and feadbacks. BTW, this proposal had merged into Cargo, if you like to test it, please refer to https://doc.rust-lang.org/cargo/reference/unstable.html?highlight=unstable#precise-pre-release. |
What 's this PR want to solve?
The main purpose is to solve the
upper bound semantic
approved by rfc#precise-pre-release-cargo-updateit extends the matching mechanism of the pre-release version,
If this PR could be merged, it maybe fixed the
cargo update --precise <pre-release>
upper bound semantic