Skip to content
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

Support for constraint operators caret (^) and tilde (~) #14

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ versions, can increment versions, etc.

Versions used with go-version must follow [SemVer](http://semver.org/).

## Installation and Usage
# Installation and Usage

Package documentation can be found on
[GoDoc](http://godoc.org/github.com/6543/go-version).
Expand All @@ -22,7 +22,7 @@ Installation can be done with a normal `go get`:
$ go get github.com/6543/go-version
```

#### Version Parsing and Comparison
# Version Parsing and Comparison

```go
v1, err := version.NewVersion("1.2")
Expand All @@ -35,7 +35,7 @@ if v1.LessThan(v2) {
}
```

#### Version Constraints
# Version Constraints

```go
v1, err := version.NewVersion("1.2")
Expand All @@ -45,9 +45,38 @@ constraints, err := version.NewConstraint(">= 1.0, < 1.4")
if constraints.Check(v1) {
fmt.Printf("%s satisfies constraints %s", v1, constraints)
}

### Tilde Range Comparisons (Patch)

The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,

* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3, < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `~1.x` is equivalent to `>= 1, < 2`

### Caret Range Comparisons (Major)

The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,

* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
* `^0` is equivalent to `>=0.0.0 <1.0.0`
```

#### Version Sorting
# Version Sorting

```go
versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"}
Expand All @@ -61,7 +90,7 @@ for i, raw := range versionsRaw {
sort.Sort(version.Collection(versions))
```

## Issues and Contributing
# Issues and Contributing

If you find an issue with this library, please report an issue. If you'd
like, we welcome any contributions. Fork this library and submit a pull
Expand Down
30 changes: 30 additions & 0 deletions constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ func init() {
">=": constraintGreaterThanEqual,
"<=": constraintLessThanEqual,
"~>": constraintPessimistic,
"^": constraintCaret,
"~": constraintTilde,
}

ops := make([]string, 0, len(constraintOperators))
Expand Down Expand Up @@ -197,3 +199,31 @@ func constraintPessimistic(v, c *Version) bool {
// be valid against the constraint
return c.segments[cs-1] <= v.segments[cs-1]
}

func constraintCaret(v, c *Version) bool {
if !prereleaseCheck(v, c) || v.LessThan(c) {
return false
}

if v.segments[0] != c.segments[0] {
return false
}

return true
}

func constraintTilde(v, c *Version) bool {
if !prereleaseCheck(v, c) || v.LessThan(c) {
return false
}

if v.segments[0] != c.segments[0] {
return false
}

if c.si > 1 && v.segments[1] != c.segments[1] {
return false
}

return true
}
41 changes: 40 additions & 1 deletion constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,45 @@ func TestConstraintCheck(t *testing.T) {
{">= 2.1.0-a", "2.1.1-beta", false},
{">= 2.1.0-a", "2.1.0", true},
{"<= 2.1.0-a", "2.0.0", true},
{"^1.1", "1.1.1", true},
{"^1.1", "1.2.3", true},
{"^1.1", "2.1.0", false},
{"^1.1.2", "1.1.1", false},
{"^1.1.2", "1.1.2", true},
{"^1.1.2", "1.1.2.3", true},
{"~1", "1.3.5", true},
{"~1", "2.1.0", false},
{"~1.1", "1.1.1", true},
{"~1.1", "1.2.3", false},
{"~1.1.2", "1.1.1", false},
{"~1.1.2", "1.1.2", true},
{"~1.1.2", "1.1.2.5", true},
{"~1.1.2", "1.1.2.3", true},
{"^1.0.0", "1.0.0", true},
{"^1.0.0", "1.0.1", true},
{"^1.0.0", "1.9.1", true},
{"^1.0.0", "2.0.0", false},
{"^0.1.0", "0.1.0", true},
{"^0.1.0", "0.2.0", true},
{"^0.1.0", "0.3.0", true},
{"^0.1.0", "0.1.4", true},
{"^0.0.1", "0.0.0", false},
{"^0.0.1", "0.0.1", true},
{"^0.0.1", "0.0.2", true},
{"^0.0.1", "0.2.0", true},
{"^1.2.3", "1.99.99", true},
{"^1.2.3", "2.00.00", false},
{"~1.0.0", "1.0.0", true},
{"~1.0.0", "1.0.1", true},
{"~1.0.0", "1.9.1", false},
{"~1.0.0", "2.0.0", false},
{"~0.1.0", "0.1.0", true},
{"~0.1.0", "0.2.0", false},
{"~0.1.0", "0.1.4", true},
{"~0.0.1", "0.0.0", false},
{"~0.0.1", "0.0.1", true},
{"~0.0.1", "0.0.2", true},
{"~0.0.1", "0.2.0", false},
}

for _, tc := range cases {
Expand All @@ -91,7 +130,7 @@ func TestConstraintCheck(t *testing.T) {
actual := c.Check(v)
expected := tc.check
if actual != expected {
t.Fatalf("Version: %s\nConstraint: %s\nExpected: %#v",
t.Fatalf("\nVersion: %s\nConstraint: %s\nExpected: %#v",
tc.version, tc.constraint, expected)
}
}
Expand Down