From 68dfa8751c11926504cb64e8c0374651c02546b0 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Tue, 9 Aug 2022 15:05:01 -0500 Subject: [PATCH] Allow pre-releases when the range uses them Currently, when a range uses a pre-release, such as 1.0.0-alpha.1 - 1.1.0, all pre-release versions are being rejected when the constraint is checked because the upper part of the range does include a pre-release. For example, 1.0.0-alpha.2 should match that range, but it is rejected right now. I have updated how we evaluate constraints so that it checks whether a constraint part uses pre-releases OR the larger constraint range that it is part of uses a pre-release. When either part of a range uses a pre-release, the entire range should allow pre-release versions. Fixes #177 Signed-off-by: Carolyn Van Slyck --- README.md | 3 ++- constraints.go | 33 ++++++++++++++++++++++++++++----- constraints_test.go | 3 +++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d8f54dc..04beb94 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,8 @@ differences to notes between these two methods of comparison. different set of rules that are common for ranges with tools like npm/js and Rust/Cargo. This includes considering prereleases to be invalid if the ranges does not include one. If you want to have it include pre-releases a - simple solution is to include `-0` in your range. + simple solution is to include `-0` in your range. For example, `~1.2.3-0` or + `1.2.3-0 - 1.5.0`. 3. Constraint ranges can have some complex rules including the shorthand use of ~ and ^. For more details on those see the options below. diff --git a/constraints.go b/constraints.go index 547613f..10d9ca4 100644 --- a/constraints.go +++ b/constraints.go @@ -32,6 +32,10 @@ func NewConstraint(c string) (*Constraints, error) { return nil, fmt.Errorf("improper constraint: %s", v) } + // If any part of the range uses a pre-release, + // then allow pre-release versions to match when the range is checked. + var rangeUsesPrerelease bool + cs := findConstraintRegex.FindAllString(v, -1) if cs == nil { cs = append(cs, v) @@ -44,7 +48,21 @@ func NewConstraint(c string) (*Constraints, error) { } result[i] = pc + + // Check if the range uses a pre-release + if !rangeUsesPrerelease && pc.con.Prerelease() != "" { + rangeUsesPrerelease = true + } } + + if rangeUsesPrerelease { + // If any part of the range used a pre-release, + // all versions in the range should allow pre-releases + for _, pc := range result { + pc.allowPrerelease = true + } + } + or[k] = result } @@ -202,6 +220,10 @@ type constraint struct { minorDirty bool dirty bool patchDirty bool + + // allowPrerelease indicates if the constraint should allow pre-releases, + // such as when part of a range constraint that uses pre-releases + allowPrerelease bool } // Check if a version meets the constraint @@ -257,6 +279,7 @@ func parseConstraint(c string) (*constraint, error) { cs.minorDirty = minorDirty cs.patchDirty = patchDirty cs.dirty = dirty + cs.allowPrerelease = cs.con.Prerelease() != "" return cs, nil } @@ -389,7 +412,7 @@ func constraintGreaterThanEqual(v *Version, c *constraint) (bool, error) { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. - if v.Prerelease() != "" && c.con.Prerelease() == "" { + if v.Prerelease() != "" && !c.allowPrerelease { return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) } @@ -404,7 +427,7 @@ func constraintLessThanEqual(v *Version, c *constraint) (bool, error) { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. - if v.Prerelease() != "" && c.con.Prerelease() == "" { + if v.Prerelease() != "" && !c.allowPrerelease { return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) } @@ -437,7 +460,7 @@ func constraintTilde(v *Version, c *constraint) (bool, error) { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. - if v.Prerelease() != "" && c.con.Prerelease() == "" { + if v.Prerelease() != "" && !c.allowPrerelease { return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) } @@ -469,7 +492,7 @@ func constraintTildeOrEqual(v *Version, c *constraint) (bool, error) { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. - if v.Prerelease() != "" && c.con.Prerelease() == "" { + if v.Prerelease() != "" && !c.allowPrerelease { return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) } @@ -498,7 +521,7 @@ func constraintCaret(v *Version, c *constraint) (bool, error) { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. - if v.Prerelease() != "" && c.con.Prerelease() == "" { + if v.Prerelease() != "" && !c.allowPrerelease { return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v) } diff --git a/constraints_test.go b/constraints_test.go index 0504399..3eb4062 100644 --- a/constraints_test.go +++ b/constraints_test.go @@ -374,6 +374,9 @@ func TestConstraintsCheck(t *testing.T) { {"~1.1-alpha", "1.1.1-beta", true}, {"~1.1.1-beta", "1.1.1-alpha", false}, {"~1.1.1-beta", "1.1.1", true}, + {constraint: "1.0.0-alpha.1 - 1.0.0", version: "1.0.0-beta.2", check: true}, + {constraint: "~1.2.3 || 1.2.3-beta.1", version: "1.2.3-beta.1", check: true}, + {constraint: "~1.2.3 || 1.2.3-beta.1", version: "1.2.3-beta.2", check: false}, {"~1.2.3", "1.2.5", true}, {"~1.2.3", "1.2.2", false}, {"~1.2.3", "1.3.2", false},