Skip to content

Commit

Permalink
feat: Add node semver compatibility implementaion and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
linyihai committed Jul 25, 2024
1 parent 7b4ad61 commit 5861ac2
Show file tree
Hide file tree
Showing 7 changed files with 676 additions and 395 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ jobs:
env:
RUSTFLAGS: --cfg test_node_semver ${{env.RUSTFLAGS}}

mirror_node_matches_prerelease:
name: mirror_node_matches_prerelease
needs: pre_ci
if: needs.pre_ci.outputs.continue
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --package semver --test test_matches_prerelease --features "mirror_node_matches_prerelease"

minimal:
name: Minimal versions
needs: pre_ci
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rust-version = "1.31"

[features]
default = ["std"]
mirror_node_matches_prerelease = []
std = []

[dependencies]
Expand Down
164 changes: 5 additions & 159 deletions src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{Comparator, Op, Prerelease, Version, VersionReq};
use crate::{eval_ext, Comparator, Op, Version, VersionReq};

pub(crate) fn matches_req(req: &VersionReq, ver: &Version, prerelease_matches: bool) -> bool {
for cmp in &req.comparators {
if prerelease_matches {
if !matches_prerelease_impl(cmp, ver) {
if !eval_ext::matches_prerelease_impl(cmp, ver) {
return false;
}
} else if !matches_impl(cmp, ver) {
Expand All @@ -30,41 +30,6 @@ pub(crate) fn matches_req(req: &VersionReq, ver: &Version, prerelease_matches: b
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
fn fill_partial_req(cmp: &Comparator) -> Comparator {
let mut cmp = cmp.clone();
if cmp.minor.is_none() {
cmp.minor = Some(0);
cmp.patch = Some(0);
} else if cmp.patch.is_none() {
cmp.patch = Some(0);
}
cmp
}

fn matches_prerelease_impl(cmp: &Comparator, ver: &Version) -> bool {
match cmp.op {
Op::Exact | Op::Wildcard => matches_exact_prerelease(cmp, ver),
Op::Greater => matches_greater(cmp, ver),
Op::GreaterEq => {
if matches_exact_prerelease(cmp, ver) {
return true;
}
matches_greater(cmp, ver)
}
Op::Less => matches_less(&fill_partial_req(cmp), ver),
Op::LessEq => {
if matches_exact_prerelease(cmp, ver) {
return true;
}
matches_less(&fill_partial_req(cmp), ver)
}
Op::Tilde => matches_tilde_prerelease(cmp, ver),
Op::Caret => matches_caret_prerelease(cmp, ver),
#[cfg(no_non_exhaustive)]
Op::__NonExhaustive => unreachable!(),
}
}

fn matches_impl(cmp: &Comparator, ver: &Version) -> bool {
match cmp.op {
Expand All @@ -80,49 +45,7 @@ fn matches_impl(cmp: &Comparator, ver: &Version) -> bool {
}
}

fn matches_exact_prerelease(cmp: &Comparator, ver: &Version) -> bool {
if matches_exact(cmp, ver) {
return true;
}

// If the comparator has a prerelease tag like =3.0.0-alpha.24,
// then it shoud be only exactly match 3.0.0-alpha.24.
if !cmp.pre.is_empty() {
return false;
}

if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

let mut upper = Comparator {
op: Op::Less,
pre: Prerelease::new("0").unwrap(),
..cmp.clone()
};

match (upper.minor.is_some(), upper.patch.is_some()) {
(true, true) => {
upper.patch = Some(upper.patch.unwrap() + 1);
}
(true, false) => {
// Partial Exact VersionReq eg. =0.24
upper.minor = Some(upper.minor.unwrap() + 1);
upper.patch = Some(0);
}
(false, false) => {
// Partial Exact VersionReq eg. =0
upper.major += 1;
upper.minor = Some(0);
upper.patch = Some(0);
}
_ => {}
}

matches_less(&upper, ver)
}

fn matches_exact(cmp: &Comparator, ver: &Version) -> bool {
pub(super) fn matches_exact(cmp: &Comparator, ver: &Version) -> bool {
if ver.major != cmp.major {
return false;
}
Expand All @@ -142,7 +65,7 @@ fn matches_exact(cmp: &Comparator, ver: &Version) -> bool {
ver.pre == cmp.pre
}

fn matches_greater(cmp: &Comparator, ver: &Version) -> bool {
pub(super) fn matches_greater(cmp: &Comparator, ver: &Version) -> bool {
if ver.major != cmp.major {
return ver.major > cmp.major;
}
Expand All @@ -168,7 +91,7 @@ fn matches_greater(cmp: &Comparator, ver: &Version) -> bool {
ver.pre > cmp.pre
}

fn matches_less(cmp: &Comparator, ver: &Version) -> bool {
pub(super) fn matches_less(cmp: &Comparator, ver: &Version) -> bool {
if ver.major != cmp.major {
return ver.major < cmp.major;
}
Expand All @@ -194,37 +117,6 @@ fn matches_less(cmp: &Comparator, ver: &Version) -> bool {
ver.pre < cmp.pre
}

fn matches_tilde_prerelease(cmp: &Comparator, ver: &Version) -> bool {
if matches_exact(cmp, ver) {
return true;
}

if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

let mut upper = Comparator {
op: Op::Less,
pre: Prerelease::new("0").unwrap(),
..cmp.clone()
};

match (upper.minor.is_some(), upper.patch.is_some()) {
(true, _) => {
upper.minor = Some(upper.minor.unwrap() + 1);
upper.patch = Some(0);
}
(false, false) => {
upper.major += 1;
upper.minor = Some(0);
upper.patch = Some(0);
}
_ => {}
}

matches_less(&upper, ver)
}

fn matches_tilde(cmp: &Comparator, ver: &Version) -> bool {
if ver.major != cmp.major {
return false;
Expand All @@ -245,52 +137,6 @@ fn matches_tilde(cmp: &Comparator, ver: &Version) -> bool {
ver.pre >= cmp.pre
}

fn matches_caret_prerelease(cmp: &Comparator, ver: &Version) -> bool {
if matches_exact(cmp, ver) {
return true;
}

if !matches_greater(&fill_partial_req(cmp), ver) {
return false;
}

let mut upper = Comparator {
op: Op::Less,
pre: Prerelease::new("0").unwrap(),
..cmp.clone()
};

match (
upper.major > 0,
upper.minor.is_some(),
upper.patch.is_some(),
) {
(true, _, _) | (_, false, false) => {
upper.major += 1;
upper.minor = Some(0);
upper.patch = Some(0);
}
(_, true, false) => {
upper.minor = Some(upper.minor.unwrap() + 1);
upper.patch = Some(0);
}
(_, true, _) if upper.minor.unwrap() > 0 => {
upper.minor = Some(upper.minor.unwrap() + 1);
upper.patch = Some(0);
}
(_, true, _) if upper.minor.unwrap() == 0 => {
if upper.patch.is_none() {
upper.patch = Some(1);
} else {
upper.patch = Some(upper.patch.unwrap() + 1);
}
}
_ => {}
}

matches_less(&upper, ver)
}

fn matches_caret(cmp: &Comparator, ver: &Version) -> bool {
if ver.major != cmp.major {
return false;
Expand Down
Loading

0 comments on commit 5861ac2

Please sign in to comment.