Skip to content

Commit

Permalink
Fixed #24: Fixed edge case issue where constraint "> 0" does not hand…
Browse files Browse the repository at this point in the history
…le "0.0.1-alpha" properly.
  • Loading branch information
mattfarina committed Nov 21, 2016
1 parent 05d8cdb commit 2fb1d3a
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 10 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Release 1.2.1 (unreleased)

## Fixed:
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
properly.

# Release 1.2.0 (2016-11-04)

## Added
Expand Down
78 changes: 70 additions & 8 deletions constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,6 @@ type constraint struct {

// Check if a version meets the constraint
func (c *constraint) check(v *Version) bool {

// 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() == "" {
return false
}

return c.function(v, c)
}

Expand Down Expand Up @@ -212,6 +204,14 @@ func parseConstraint(c string) (*constraint, error) {
// Constraint functions
func constraintNotEqual(v *Version, c *constraint) bool {
if c.dirty {

// 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() == "" {
return false
}

if c.con.Major() != v.Major() {
return true
}
Expand All @@ -228,10 +228,31 @@ func constraintNotEqual(v *Version, c *constraint) bool {
}

func constraintGreaterThan(v *Version, c *constraint) bool {

// An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease
// exists. This that case.
if !c.con.isNonZero && v.isNonZero {
return true
}

// 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() == "" {
return false
}

return v.Compare(c.con) == 1
}

func constraintLessThan(v *Version, c *constraint) bool {
// 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() == "" {
return false
}

if !c.dirty {
return v.Compare(c.con) < 0
}
Expand All @@ -246,10 +267,30 @@ func constraintLessThan(v *Version, c *constraint) bool {
}

func constraintGreaterThanEqual(v *Version, c *constraint) bool {
// An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease
// exists. This that case.
if !c.con.isNonZero && v.isNonZero {
return true
}

// 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() == "" {
return false
}

return v.Compare(c.con) >= 0
}

func constraintLessThanEqual(v *Version, c *constraint) bool {
// 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() == "" {
return false
}

if !c.dirty {
return v.Compare(c.con) <= 0
}
Expand All @@ -270,6 +311,13 @@ func constraintLessThanEqual(v *Version, c *constraint) bool {
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
func constraintTilde(v *Version, c *constraint) bool {
// 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() == "" {
return false
}

if v.LessThan(c.con) {
return false
}
Expand All @@ -294,6 +342,13 @@ func constraintTilde(v *Version, c *constraint) bool {
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
// it's a straight =
func constraintTildeOrEqual(v *Version, c *constraint) bool {
// 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() == "" {
return false
}

if c.dirty {
c.msg = constraintMsg["~"]
return constraintTilde(v, c)
Expand All @@ -309,6 +364,13 @@ func constraintTildeOrEqual(v *Version, c *constraint) bool {
// ^1.2.3 --> >=1.2.3, <2.0.0
// ^1.2.0 --> >=1.2.0, <2.0.0
func constraintCaret(v *Version, c *constraint) bool {
// 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() == "" {
return false
}

if v.LessThan(c.con) {
return false
}
Expand Down
6 changes: 5 additions & 1 deletion constraints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func TestConstraintCheck(t *testing.T) {
{"<=1.1", "0.1.0", true},
{"<=1.1", "1.1.0", true},
{"<=1.1", "1.1.1", false},
{">0", "0.0.1-alpha", true},
{">=0", "0.0.1-alpha", true},
{">0", "0", false},
{">=0", "0", true},
}

for _, tc := range tests {
Expand All @@ -89,7 +93,7 @@ func TestConstraintCheck(t *testing.T) {

a := c.check(v)
if a != tc.check {
t.Errorf("Constraint '%s' failing", tc.constraint)
t.Errorf("Constraint %q failing with %q", tc.constraint, tc.version)
}
}
}
Expand Down
34 changes: 33 additions & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ type Version struct {
pre string
metadata string
original string

// If the value is a non-zero (0.0.0) version. This is NonZero because
// an empty instance not created with NewVersion would have 0 value. This
// will still work with that case.
isNonZero bool
}

func init() {
Expand Down Expand Up @@ -85,6 +90,12 @@ func NewVersion(v string) (*Version, error) {
sv.patch = 0
}

// Note, per the spec the metadata is not part of the value of the version
// so ignoring it in evaluating a non-zero value.
if sv.major != 0 || sv.minor != 0 || sv.patch != 0 || sv.pre != "" {
sv.isNonZero = true
}

return sv, nil
}

Expand Down Expand Up @@ -176,6 +187,7 @@ func (v Version) IncPatch() Version {
vNext.patch = v.patch + 1
}
vNext.original = v.originalVPrefix() + "" + vNext.String()
vNext.isNonZero = true
return vNext
}

Expand All @@ -191,6 +203,7 @@ func (v Version) IncMinor() Version {
vNext.patch = 0
vNext.minor = v.minor + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
vNext.isNonZero = true
return vNext
}

Expand All @@ -208,10 +221,11 @@ func (v Version) IncMajor() Version {
vNext.minor = 0
vNext.major = v.major + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
vNext.isNonZero = true
return vNext
}

// SetPrelease defines the prerelease value.
// SetPrerelease defines the prerelease value.
// Value must not include the required 'hypen' prefix.
func (v Version) SetPrerelease(prerelease string) (Version, error) {
vNext := v
Expand All @@ -220,6 +234,15 @@ func (v Version) SetPrerelease(prerelease string) (Version, error) {
}
vNext.pre = prerelease
vNext.original = v.originalVPrefix() + "" + vNext.String()

// Note, per the spec the metadata is not part of the value of the version
// so ignoring it in evaluating a non-zero value.
if vNext.major != 0 || vNext.minor != 0 || vNext.patch != 0 || vNext.pre != "" {
vNext.isNonZero = true
} else {
vNext.isNonZero = false
}

return vNext, nil
}

Expand All @@ -232,6 +255,15 @@ func (v Version) SetMetadata(metadata string) (Version, error) {
}
vNext.metadata = metadata
vNext.original = v.originalVPrefix() + "" + vNext.String()

// Note, per the spec the metadata is not part of the value of the version
// so ignoring it in evaluating a non-zero value.
if vNext.major != 0 || vNext.minor != 0 || vNext.patch != 0 || vNext.pre != "" {
vNext.isNonZero = true
} else {
vNext.isNonZero = false
}

return vNext, nil
}

Expand Down
53 changes: 53 additions & 0 deletions version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,56 @@ func TestOriginalVPrefix(t *testing.T) {
}
}
}

func TestIsNonZero(t *testing.T) {
tests := []struct {
version string
non bool
}{
{"0.0.0", false},
{"0.0.0-beta", true},
{"0.0.0+meta", false},
{"1.0.0", true},
{"0.2.0", true},
{"0.0.3", true},
}

for _, tc := range tests {
v1, _ := NewVersion(tc.version)
a := v1.isNonZero
e := tc.non
if a != e {
t.Errorf("Expected nonZero flag=%q, but got %q", e, a)
}
}

v1, _ := NewVersion("0")
if v1.isNonZero != false {
t.Fatal("Zero version marked at non-zero value")
}

v2 := v1.IncMajor()
if v2.isNonZero != true {
t.Error("Incrementing major didn't set to non-zero value")
}

v2 = v1.IncMinor()
if v2.isNonZero != true {
t.Error("Incrementing minor didn't set to non-zero value")
}

v2 = v1.IncPatch()
if v2.isNonZero != true {
t.Error("Incrementing patch didn't set to non-zero value")
}

v2, _ = v1.SetMetadata("foo")
if v2.isNonZero != false {
t.Error("Setting metadata set to non-zero value")
}

v2, _ = v1.SetPrerelease("alpha")
if v2.isNonZero != true {
t.Error("Setting pre-release didn't set to non-zero value")
}
}

0 comments on commit 2fb1d3a

Please sign in to comment.