add vendor
This commit is contained in:
parent
3e41b5f477
commit
a13c724673
1
vendor/github.com/blang/semver/.gx/lastpubver
generated
vendored
Normal file
1
vendor/github.com/blang/semver/.gx/lastpubver
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.5.1: QmYRGECuvQnRX73fcvPnGbYijBcGN2HbKZQ7jh26qmLiHG
|
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
Normal file
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
language: go
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- go: 1.4.3
|
||||||
|
- go: 1.5.4
|
||||||
|
- go: 1.6.3
|
||||||
|
- go: 1.7
|
||||||
|
- go: tip
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
install:
|
||||||
|
- go get golang.org/x/tools/cmd/cover
|
||||||
|
- go get github.com/mattn/goveralls
|
||||||
|
script:
|
||||||
|
- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
|
||||||
|
-repotoken $COVERALLS_TOKEN
|
||||||
|
- echo "Build examples" ; cd examples && go build
|
||||||
|
- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
|
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
Normal file
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
194
vendor/github.com/blang/semver/README.md
generated
vendored
Normal file
194
vendor/github.com/blang/semver/README.md
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
|
||||||
|
======
|
||||||
|
|
||||||
|
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
```bash
|
||||||
|
$ go get github.com/blang/semver
|
||||||
|
```
|
||||||
|
Note: Always vendor your dependencies or fix on a specific version tag.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import github.com/blang/semver
|
||||||
|
v1, err := semver.Make("1.0.0-beta")
|
||||||
|
v2, err := semver.Make("2.0.0-beta")
|
||||||
|
v1.Compare(v2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
|
||||||
|
|
||||||
|
Why should I use this lib?
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Fully spec compatible
|
||||||
|
- No reflection
|
||||||
|
- No regex
|
||||||
|
- Fully tested (Coverage >99%)
|
||||||
|
- Readable parsing/validation errors
|
||||||
|
- Fast (See [Benchmarks](#benchmarks))
|
||||||
|
- Only Stdlib
|
||||||
|
- Uses values instead of pointers
|
||||||
|
- Many features, see below
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Parsing and validation at all levels
|
||||||
|
- Comparator-like comparisons
|
||||||
|
- Compare Helper Methods
|
||||||
|
- InPlace manipulation
|
||||||
|
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
|
||||||
|
- Wildcards `>=1.x`, `<=2.5.x`
|
||||||
|
- Sortable (implements sort.Interface)
|
||||||
|
- database/sql compatible (sql.Scanner/Valuer)
|
||||||
|
- encoding/json compatible (json.Marshaler/Unmarshaler)
|
||||||
|
|
||||||
|
Ranges
|
||||||
|
------
|
||||||
|
|
||||||
|
A `Range` is a set of conditions which specify which versions satisfy the range.
|
||||||
|
|
||||||
|
A condition is composed of an operator and a version. The supported operators are:
|
||||||
|
|
||||||
|
- `<1.0.0` Less than `1.0.0`
|
||||||
|
- `<=1.0.0` Less than or equal to `1.0.0`
|
||||||
|
- `>1.0.0` Greater than `1.0.0`
|
||||||
|
- `>=1.0.0` Greater than or equal to `1.0.0`
|
||||||
|
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
|
||||||
|
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
|
||||||
|
|
||||||
|
Note that spaces between the operator and the version will be gracefully tolerated.
|
||||||
|
|
||||||
|
A `Range` can link multiple `Ranges` separated by space:
|
||||||
|
|
||||||
|
Ranges can be linked by logical AND:
|
||||||
|
|
||||||
|
- `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
|
||||||
|
- `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
|
||||||
|
|
||||||
|
Ranges can also be linked by logical OR:
|
||||||
|
|
||||||
|
- `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
|
||||||
|
|
||||||
|
AND has a higher precedence than OR. It's not possible to use brackets.
|
||||||
|
|
||||||
|
Ranges can be combined by both AND and OR
|
||||||
|
|
||||||
|
- `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
||||||
|
|
||||||
|
Range usage:
|
||||||
|
|
||||||
|
```
|
||||||
|
v, err := semver.Parse("1.2.3")
|
||||||
|
range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
|
||||||
|
if range(v) {
|
||||||
|
//valid
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Example
|
||||||
|
-----
|
||||||
|
|
||||||
|
Have a look at full examples in [examples/main.go](examples/main.go)
|
||||||
|
|
||||||
|
```go
|
||||||
|
import github.com/blang/semver
|
||||||
|
|
||||||
|
v, err := semver.Make("0.0.1-alpha.preview+123.github")
|
||||||
|
fmt.Printf("Major: %d\n", v.Major)
|
||||||
|
fmt.Printf("Minor: %d\n", v.Minor)
|
||||||
|
fmt.Printf("Patch: %d\n", v.Patch)
|
||||||
|
fmt.Printf("Pre: %s\n", v.Pre)
|
||||||
|
fmt.Printf("Build: %s\n", v.Build)
|
||||||
|
|
||||||
|
// Prerelease versions array
|
||||||
|
if len(v.Pre) > 0 {
|
||||||
|
fmt.Println("Prerelease versions:")
|
||||||
|
for i, pre := range v.Pre {
|
||||||
|
fmt.Printf("%d: %q\n", i, pre)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build meta data array
|
||||||
|
if len(v.Build) > 0 {
|
||||||
|
fmt.Println("Build meta data:")
|
||||||
|
for i, build := range v.Build {
|
||||||
|
fmt.Printf("%d: %q\n", i, build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v001, err := semver.Make("0.0.1")
|
||||||
|
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
|
||||||
|
v001.GT(v) == true
|
||||||
|
v.LT(v001) == true
|
||||||
|
v.GTE(v) == true
|
||||||
|
v.LTE(v) == true
|
||||||
|
|
||||||
|
// Or use v.Compare(v2) for comparisons (-1, 0, 1):
|
||||||
|
v001.Compare(v) == 1
|
||||||
|
v.Compare(v001) == -1
|
||||||
|
v.Compare(v) == 0
|
||||||
|
|
||||||
|
// Manipulate Version in place:
|
||||||
|
v.Pre[0], err = semver.NewPRVersion("beta")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing pre release version: %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("\nValidate versions:")
|
||||||
|
v.Build[0] = "?"
|
||||||
|
|
||||||
|
err = v.Validate()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Validation failed: %s\n", err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Benchmarks
|
||||||
|
-----
|
||||||
|
|
||||||
|
BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
|
||||||
|
BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
|
||||||
|
BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
|
||||||
|
BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
|
||||||
|
BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
|
||||||
|
BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
|
||||||
|
BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
|
||||||
|
BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
|
||||||
|
BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
|
||||||
|
BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
|
||||||
|
BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
|
||||||
|
BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
|
||||||
|
|
||||||
|
See benchmark cases at [semver_test.go](semver_test.go)
|
||||||
|
|
||||||
|
|
||||||
|
Motivation
|
||||||
|
-----
|
||||||
|
|
||||||
|
I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
|
||||||
|
|
||||||
|
|
||||||
|
Contribution
|
||||||
|
-----
|
||||||
|
|
||||||
|
Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-----
|
||||||
|
|
||||||
|
See [LICENSE](LICENSE) file.
|
83
vendor/github.com/blang/semver/examples/main.go
generated
vendored
Normal file
83
vendor/github.com/blang/semver/examples/main.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/blang/semver"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v, err := semver.Parse("0.0.1-alpha.preview.222+123.github")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error while parsing (not valid): %q", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Version to string: %q\n", v)
|
||||||
|
|
||||||
|
fmt.Printf("Major: %d\n", v.Major)
|
||||||
|
fmt.Printf("Minor: %d\n", v.Minor)
|
||||||
|
fmt.Printf("Patch: %d\n", v.Patch)
|
||||||
|
|
||||||
|
// Prerelease versions
|
||||||
|
if len(v.Pre) > 0 {
|
||||||
|
fmt.Println("Prerelease versions:")
|
||||||
|
for i, pre := range v.Pre {
|
||||||
|
fmt.Printf("%d: %q\n", i, pre)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build meta data
|
||||||
|
if len(v.Build) > 0 {
|
||||||
|
fmt.Println("Build meta data:")
|
||||||
|
for i, build := range v.Build {
|
||||||
|
fmt.Printf("%d: %q\n", i, build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make == Parse (Value), New for Pointer
|
||||||
|
v001, err := semver.Make("0.0.1")
|
||||||
|
|
||||||
|
fmt.Println("\nUse Version.Compare for comparisons (-1, 0, 1):")
|
||||||
|
fmt.Printf("%q is greater than %q: Compare == %d\n", v001, v, v001.Compare(v))
|
||||||
|
fmt.Printf("%q is less than %q: Compare == %d\n", v, v001, v.Compare(v001))
|
||||||
|
fmt.Printf("%q is equal to %q: Compare == %d\n", v, v, v.Compare(v))
|
||||||
|
|
||||||
|
fmt.Println("\nUse comparison helpers returning booleans:")
|
||||||
|
fmt.Printf("%q is greater than %q: %t\n", v001, v, v001.GT(v))
|
||||||
|
fmt.Printf("%q is greater than equal %q: %t\n", v001, v, v001.GTE(v))
|
||||||
|
fmt.Printf("%q is greater than equal %q: %t\n", v, v, v.GTE(v))
|
||||||
|
fmt.Printf("%q is less than %q: %t\n", v, v001, v.LT(v001))
|
||||||
|
fmt.Printf("%q is less than equal %q: %t\n", v, v001, v.LTE(v001))
|
||||||
|
fmt.Printf("%q is less than equal %q: %t\n", v, v, v.LTE(v))
|
||||||
|
|
||||||
|
fmt.Println("\nManipulate Version in place:")
|
||||||
|
v.Pre[0], err = semver.NewPRVersion("beta")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing pre release version: %q", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Version to string: %q\n", v)
|
||||||
|
|
||||||
|
fmt.Println("\nCompare Prerelease versions:")
|
||||||
|
pre1, _ := semver.NewPRVersion("123")
|
||||||
|
pre2, _ := semver.NewPRVersion("alpha")
|
||||||
|
pre3, _ := semver.NewPRVersion("124")
|
||||||
|
fmt.Printf("%q is less than %q: Compare == %d\n", pre1, pre2, pre1.Compare(pre2))
|
||||||
|
fmt.Printf("%q is greater than %q: Compare == %d\n", pre3, pre1, pre3.Compare(pre1))
|
||||||
|
fmt.Printf("%q is equal to %q: Compare == %d\n", pre1, pre1, pre1.Compare(pre1))
|
||||||
|
|
||||||
|
fmt.Println("\nValidate versions:")
|
||||||
|
v.Build[0] = "?"
|
||||||
|
|
||||||
|
err = v.Validate()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Validation failed: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Create valid build meta data:")
|
||||||
|
b1, _ := semver.NewBuildVersion("build123")
|
||||||
|
v.Build[0] = b1
|
||||||
|
fmt.Printf("Version with new build version %q\n", v)
|
||||||
|
|
||||||
|
_, err = semver.NewBuildVersion("build?123")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Create build version failed: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
23
vendor/github.com/blang/semver/json.go
generated
vendored
Normal file
23
vendor/github.com/blang/semver/json.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarshalJSON implements the encoding/json.Marshaler interface.
|
||||||
|
func (v Version) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(v.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
|
||||||
|
func (v *Version) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
var versionString string
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &versionString); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*v, err = Parse(versionString)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
49
vendor/github.com/blang/semver/json_test.go
generated
vendored
Normal file
49
vendor/github.com/blang/semver/json_test.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJSONMarshal(t *testing.T) {
|
||||||
|
versionString := "3.1.4-alpha.1.5.9+build.2.6.5"
|
||||||
|
v, err := Parse(versionString)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
versionJSON, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
quotedVersionString := strconv.Quote(versionString)
|
||||||
|
|
||||||
|
if string(versionJSON) != quotedVersionString {
|
||||||
|
t.Fatalf("JSON marshaled semantic version not equal: expected %q, got %q", quotedVersionString, string(versionJSON))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONUnmarshal(t *testing.T) {
|
||||||
|
versionString := "3.1.4-alpha.1.5.9+build.2.6.5"
|
||||||
|
quotedVersionString := strconv.Quote(versionString)
|
||||||
|
|
||||||
|
var v Version
|
||||||
|
if err := json.Unmarshal([]byte(quotedVersionString), &v); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.String() != versionString {
|
||||||
|
t.Fatalf("JSON unmarshaled semantic version not equal: expected %q, got %q", versionString, v.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
badVersionString := strconv.Quote("3.1.4.1.5.9.2.6.5-other-digits-of-pi")
|
||||||
|
if err := json.Unmarshal([]byte(badVersionString), &v); err == nil {
|
||||||
|
t.Fatal("expected JSON unmarshal error, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte("3.1"), &v); err == nil {
|
||||||
|
t.Fatal("expected JSON unmarshal error, got nil")
|
||||||
|
}
|
||||||
|
}
|
17
vendor/github.com/blang/semver/package.json
generated
vendored
Normal file
17
vendor/github.com/blang/semver/package.json
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"author": "blang",
|
||||||
|
"bugs": {
|
||||||
|
"URL": "https://github.com/blang/semver/issues",
|
||||||
|
"url": "https://github.com/blang/semver/issues"
|
||||||
|
},
|
||||||
|
"gx": {
|
||||||
|
"dvcsimport": "github.com/blang/semver"
|
||||||
|
},
|
||||||
|
"gxVersion": "0.10.0",
|
||||||
|
"language": "go",
|
||||||
|
"license": "MIT",
|
||||||
|
"name": "semver",
|
||||||
|
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
|
||||||
|
"version": "3.5.1"
|
||||||
|
}
|
||||||
|
|
416
vendor/github.com/blang/semver/range.go
generated
vendored
Normal file
416
vendor/github.com/blang/semver/range.go
generated
vendored
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type wildcardType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
noneWildcard wildcardType = iota
|
||||||
|
majorWildcard wildcardType = 1
|
||||||
|
minorWildcard wildcardType = 2
|
||||||
|
patchWildcard wildcardType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
func wildcardTypefromInt(i int) wildcardType {
|
||||||
|
switch i {
|
||||||
|
case 1:
|
||||||
|
return majorWildcard
|
||||||
|
case 2:
|
||||||
|
return minorWildcard
|
||||||
|
case 3:
|
||||||
|
return patchWildcard
|
||||||
|
default:
|
||||||
|
return noneWildcard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type comparator func(Version, Version) bool
|
||||||
|
|
||||||
|
var (
|
||||||
|
compEQ comparator = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) == 0
|
||||||
|
}
|
||||||
|
compNE = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) != 0
|
||||||
|
}
|
||||||
|
compGT = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) == 1
|
||||||
|
}
|
||||||
|
compGE = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) >= 0
|
||||||
|
}
|
||||||
|
compLT = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) == -1
|
||||||
|
}
|
||||||
|
compLE = func(v1 Version, v2 Version) bool {
|
||||||
|
return v1.Compare(v2) <= 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type versionRange struct {
|
||||||
|
v Version
|
||||||
|
c comparator
|
||||||
|
}
|
||||||
|
|
||||||
|
// rangeFunc creates a Range from the given versionRange.
|
||||||
|
func (vr *versionRange) rangeFunc() Range {
|
||||||
|
return Range(func(v Version) bool {
|
||||||
|
return vr.c(v, vr.v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range represents a range of versions.
|
||||||
|
// A Range can be used to check if a Version satisfies it:
|
||||||
|
//
|
||||||
|
// range, err := semver.ParseRange(">1.0.0 <2.0.0")
|
||||||
|
// range(semver.MustParse("1.1.1") // returns true
|
||||||
|
type Range func(Version) bool
|
||||||
|
|
||||||
|
// OR combines the existing Range with another Range using logical OR.
|
||||||
|
func (rf Range) OR(f Range) Range {
|
||||||
|
return Range(func(v Version) bool {
|
||||||
|
return rf(v) || f(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AND combines the existing Range with another Range using logical AND.
|
||||||
|
func (rf Range) AND(f Range) Range {
|
||||||
|
return Range(func(v Version) bool {
|
||||||
|
return rf(v) && f(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRange parses a range and returns a Range.
|
||||||
|
// If the range could not be parsed an error is returned.
|
||||||
|
//
|
||||||
|
// Valid ranges are:
|
||||||
|
// - "<1.0.0"
|
||||||
|
// - "<=1.0.0"
|
||||||
|
// - ">1.0.0"
|
||||||
|
// - ">=1.0.0"
|
||||||
|
// - "1.0.0", "=1.0.0", "==1.0.0"
|
||||||
|
// - "!1.0.0", "!=1.0.0"
|
||||||
|
//
|
||||||
|
// A Range can consist of multiple ranges separated by space:
|
||||||
|
// Ranges can be linked by logical AND:
|
||||||
|
// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
|
||||||
|
// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
|
||||||
|
//
|
||||||
|
// Ranges can also be linked by logical OR:
|
||||||
|
// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
|
||||||
|
//
|
||||||
|
// AND has a higher precedence than OR. It's not possible to use brackets.
|
||||||
|
//
|
||||||
|
// Ranges can be combined by both AND and OR
|
||||||
|
//
|
||||||
|
// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
||||||
|
func ParseRange(s string) (Range, error) {
|
||||||
|
parts := splitAndTrim(s)
|
||||||
|
orParts, err := splitORParts(parts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
expandedParts, err := expandWildcardVersion(orParts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var orFn Range
|
||||||
|
for _, p := range expandedParts {
|
||||||
|
var andFn Range
|
||||||
|
for _, ap := range p {
|
||||||
|
opStr, vStr, err := splitComparatorVersion(ap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
vr, err := buildVersionRange(opStr, vStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
|
||||||
|
}
|
||||||
|
rf := vr.rangeFunc()
|
||||||
|
|
||||||
|
// Set function
|
||||||
|
if andFn == nil {
|
||||||
|
andFn = rf
|
||||||
|
} else { // Combine with existing function
|
||||||
|
andFn = andFn.AND(rf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if orFn == nil {
|
||||||
|
orFn = andFn
|
||||||
|
} else {
|
||||||
|
orFn = orFn.OR(andFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return orFn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitORParts splits the already cleaned parts by '||'.
|
||||||
|
// Checks for invalid positions of the operator and returns an
|
||||||
|
// error if found.
|
||||||
|
func splitORParts(parts []string) ([][]string, error) {
|
||||||
|
var ORparts [][]string
|
||||||
|
last := 0
|
||||||
|
for i, p := range parts {
|
||||||
|
if p == "||" {
|
||||||
|
if i == 0 {
|
||||||
|
return nil, fmt.Errorf("First element in range is '||'")
|
||||||
|
}
|
||||||
|
ORparts = append(ORparts, parts[last:i])
|
||||||
|
last = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if last == len(parts) {
|
||||||
|
return nil, fmt.Errorf("Last element in range is '||'")
|
||||||
|
}
|
||||||
|
ORparts = append(ORparts, parts[last:])
|
||||||
|
return ORparts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildVersionRange takes a slice of 2: operator and version
|
||||||
|
// and builds a versionRange, otherwise an error.
|
||||||
|
func buildVersionRange(opStr, vStr string) (*versionRange, error) {
|
||||||
|
c := parseComparator(opStr)
|
||||||
|
if c == nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
|
||||||
|
}
|
||||||
|
v, err := Parse(vStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &versionRange{
|
||||||
|
v: v,
|
||||||
|
c: c,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// inArray checks if a byte is contained in an array of bytes
|
||||||
|
func inArray(s byte, list []byte) bool {
|
||||||
|
for _, el := range list {
|
||||||
|
if el == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitAndTrim splits a range string by spaces and cleans whitespaces
|
||||||
|
func splitAndTrim(s string) (result []string) {
|
||||||
|
last := 0
|
||||||
|
var lastChar byte
|
||||||
|
excludeFromSplit := []byte{'>', '<', '='}
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
|
||||||
|
if last < i-1 {
|
||||||
|
result = append(result, s[last:i])
|
||||||
|
}
|
||||||
|
last = i + 1
|
||||||
|
} else if s[i] != ' ' {
|
||||||
|
lastChar = s[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if last < len(s)-1 {
|
||||||
|
result = append(result, s[last:])
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range result {
|
||||||
|
result[i] = strings.Replace(v, " ", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parts := strings.Split(s, " ")
|
||||||
|
// for _, x := range parts {
|
||||||
|
// if s := strings.TrimSpace(x); len(s) != 0 {
|
||||||
|
// result = append(result, s)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitComparatorVersion splits the comparator from the version.
|
||||||
|
// Input must be free of leading or trailing spaces.
|
||||||
|
func splitComparatorVersion(s string) (string, string, error) {
|
||||||
|
i := strings.IndexFunc(s, unicode.IsDigit)
|
||||||
|
if i == -1 {
|
||||||
|
return "", "", fmt.Errorf("Could not get version from string: %q", s)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(s[0:i]), s[i:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWildcardType will return the type of wildcard that the
|
||||||
|
// passed version contains
|
||||||
|
func getWildcardType(vStr string) wildcardType {
|
||||||
|
parts := strings.Split(vStr, ".")
|
||||||
|
nparts := len(parts)
|
||||||
|
wildcard := parts[nparts-1]
|
||||||
|
|
||||||
|
possibleWildcardType := wildcardTypefromInt(nparts)
|
||||||
|
if wildcard == "x" {
|
||||||
|
return possibleWildcardType
|
||||||
|
}
|
||||||
|
|
||||||
|
return noneWildcard
|
||||||
|
}
|
||||||
|
|
||||||
|
// createVersionFromWildcard will convert a wildcard version
|
||||||
|
// into a regular version, replacing 'x's with '0's, handling
|
||||||
|
// special cases like '1.x.x' and '1.x'
|
||||||
|
func createVersionFromWildcard(vStr string) string {
|
||||||
|
// handle 1.x.x
|
||||||
|
vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
|
||||||
|
vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
|
||||||
|
parts := strings.Split(vStr2, ".")
|
||||||
|
|
||||||
|
// handle 1.x
|
||||||
|
if len(parts) == 2 {
|
||||||
|
return vStr2 + ".0"
|
||||||
|
}
|
||||||
|
|
||||||
|
return vStr2
|
||||||
|
}
|
||||||
|
|
||||||
|
// incrementMajorVersion will increment the major version
|
||||||
|
// of the passed version
|
||||||
|
func incrementMajorVersion(vStr string) (string, error) {
|
||||||
|
parts := strings.Split(vStr, ".")
|
||||||
|
i, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
parts[0] = strconv.Itoa(i + 1)
|
||||||
|
|
||||||
|
return strings.Join(parts, "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// incrementMajorVersion will increment the minor version
|
||||||
|
// of the passed version
|
||||||
|
func incrementMinorVersion(vStr string) (string, error) {
|
||||||
|
parts := strings.Split(vStr, ".")
|
||||||
|
i, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
parts[1] = strconv.Itoa(i + 1)
|
||||||
|
|
||||||
|
return strings.Join(parts, "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandWildcardVersion will expand wildcards inside versions
|
||||||
|
// following these rules:
|
||||||
|
//
|
||||||
|
// * when dealing with patch wildcards:
|
||||||
|
// >= 1.2.x will become >= 1.2.0
|
||||||
|
// <= 1.2.x will become < 1.3.0
|
||||||
|
// > 1.2.x will become >= 1.3.0
|
||||||
|
// < 1.2.x will become < 1.2.0
|
||||||
|
// != 1.2.x will become < 1.2.0 >= 1.3.0
|
||||||
|
//
|
||||||
|
// * when dealing with minor wildcards:
|
||||||
|
// >= 1.x will become >= 1.0.0
|
||||||
|
// <= 1.x will become < 2.0.0
|
||||||
|
// > 1.x will become >= 2.0.0
|
||||||
|
// < 1.0 will become < 1.0.0
|
||||||
|
// != 1.x will become < 1.0.0 >= 2.0.0
|
||||||
|
//
|
||||||
|
// * when dealing with wildcards without
|
||||||
|
// version operator:
|
||||||
|
// 1.2.x will become >= 1.2.0 < 1.3.0
|
||||||
|
// 1.x will become >= 1.0.0 < 2.0.0
|
||||||
|
func expandWildcardVersion(parts [][]string) ([][]string, error) {
|
||||||
|
var expandedParts [][]string
|
||||||
|
for _, p := range parts {
|
||||||
|
var newParts []string
|
||||||
|
for _, ap := range p {
|
||||||
|
if strings.Index(ap, "x") != -1 {
|
||||||
|
opStr, vStr, err := splitComparatorVersion(ap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
versionWildcardType := getWildcardType(vStr)
|
||||||
|
flatVersion := createVersionFromWildcard(vStr)
|
||||||
|
|
||||||
|
var resultOperator string
|
||||||
|
var shouldIncrementVersion bool
|
||||||
|
switch opStr {
|
||||||
|
case ">":
|
||||||
|
resultOperator = ">="
|
||||||
|
shouldIncrementVersion = true
|
||||||
|
case ">=":
|
||||||
|
resultOperator = ">="
|
||||||
|
case "<":
|
||||||
|
resultOperator = "<"
|
||||||
|
case "<=":
|
||||||
|
resultOperator = "<"
|
||||||
|
shouldIncrementVersion = true
|
||||||
|
case "", "=", "==":
|
||||||
|
newParts = append(newParts, ">="+flatVersion)
|
||||||
|
resultOperator = "<"
|
||||||
|
shouldIncrementVersion = true
|
||||||
|
case "!=", "!":
|
||||||
|
newParts = append(newParts, "<"+flatVersion)
|
||||||
|
resultOperator = ">="
|
||||||
|
shouldIncrementVersion = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultVersion string
|
||||||
|
if shouldIncrementVersion {
|
||||||
|
switch versionWildcardType {
|
||||||
|
case patchWildcard:
|
||||||
|
resultVersion, _ = incrementMinorVersion(flatVersion)
|
||||||
|
case minorWildcard:
|
||||||
|
resultVersion, _ = incrementMajorVersion(flatVersion)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resultVersion = flatVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
ap = resultOperator + resultVersion
|
||||||
|
}
|
||||||
|
newParts = append(newParts, ap)
|
||||||
|
}
|
||||||
|
expandedParts = append(expandedParts, newParts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return expandedParts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseComparator(s string) comparator {
|
||||||
|
switch s {
|
||||||
|
case "==":
|
||||||
|
fallthrough
|
||||||
|
case "":
|
||||||
|
fallthrough
|
||||||
|
case "=":
|
||||||
|
return compEQ
|
||||||
|
case ">":
|
||||||
|
return compGT
|
||||||
|
case ">=":
|
||||||
|
return compGE
|
||||||
|
case "<":
|
||||||
|
return compLT
|
||||||
|
case "<=":
|
||||||
|
return compLE
|
||||||
|
case "!":
|
||||||
|
fallthrough
|
||||||
|
case "!=":
|
||||||
|
return compNE
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseRange is like ParseRange but panics if the range cannot be parsed.
|
||||||
|
func MustParseRange(s string) Range {
|
||||||
|
r, err := ParseRange(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(`semver: ParseRange(` + s + `): ` + err.Error())
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
581
vendor/github.com/blang/semver/range_test.go
generated
vendored
Normal file
581
vendor/github.com/blang/semver/range_test.go
generated
vendored
Normal file
@ -0,0 +1,581 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type wildcardTypeTest struct {
|
||||||
|
input string
|
||||||
|
wildcardType wildcardType
|
||||||
|
}
|
||||||
|
|
||||||
|
type comparatorTest struct {
|
||||||
|
input string
|
||||||
|
comparator func(comparator) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseComparator(t *testing.T) {
|
||||||
|
compatorTests := []comparatorTest{
|
||||||
|
{">", testGT},
|
||||||
|
{">=", testGE},
|
||||||
|
{"<", testLT},
|
||||||
|
{"<=", testLE},
|
||||||
|
{"", testEQ},
|
||||||
|
{"=", testEQ},
|
||||||
|
{"==", testEQ},
|
||||||
|
{"!=", testNE},
|
||||||
|
{"!", testNE},
|
||||||
|
{"-", nil},
|
||||||
|
{"<==", nil},
|
||||||
|
{"<<", nil},
|
||||||
|
{">>", nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range compatorTests {
|
||||||
|
if c := parseComparator(tc.input); c == nil {
|
||||||
|
if tc.comparator != nil {
|
||||||
|
t.Errorf("Comparator nil for case %q\n", tc.input)
|
||||||
|
}
|
||||||
|
} else if !tc.comparator(c) {
|
||||||
|
t.Errorf("Invalid comparator for case %q\n", tc.input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
v1 = MustParse("1.2.2")
|
||||||
|
v2 = MustParse("1.2.3")
|
||||||
|
v3 = MustParse("1.2.4")
|
||||||
|
)
|
||||||
|
|
||||||
|
func testEQ(f comparator) bool {
|
||||||
|
return f(v1, v1) && !f(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNE(f comparator) bool {
|
||||||
|
return !f(v1, v1) && f(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGT(f comparator) bool {
|
||||||
|
return f(v2, v1) && f(v3, v2) && !f(v1, v2) && !f(v1, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGE(f comparator) bool {
|
||||||
|
return f(v2, v1) && f(v3, v2) && !f(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLT(f comparator) bool {
|
||||||
|
return f(v1, v2) && f(v2, v3) && !f(v2, v1) && !f(v1, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLE(f comparator) bool {
|
||||||
|
return f(v1, v2) && f(v2, v3) && !f(v2, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitAndTrim(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
s []string
|
||||||
|
}{
|
||||||
|
{"1.2.3 1.2.3", []string{"1.2.3", "1.2.3"}},
|
||||||
|
{" 1.2.3 1.2.3 ", []string{"1.2.3", "1.2.3"}}, // Spaces
|
||||||
|
{" >= 1.2.3 <= 1.2.3 ", []string{">=1.2.3", "<=1.2.3"}}, // Spaces between operator and version
|
||||||
|
{"1.2.3 || >=1.2.3 <1.2.3", []string{"1.2.3", "||", ">=1.2.3", "<1.2.3"}},
|
||||||
|
{" 1.2.3 || >=1.2.3 <1.2.3 ", []string{"1.2.3", "||", ">=1.2.3", "<1.2.3"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
p := splitAndTrim(tc.i)
|
||||||
|
if !reflect.DeepEqual(p, tc.s) {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.s, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitComparatorVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
p []string
|
||||||
|
}{
|
||||||
|
{">1.2.3", []string{">", "1.2.3"}},
|
||||||
|
{">=1.2.3", []string{">=", "1.2.3"}},
|
||||||
|
{"<1.2.3", []string{"<", "1.2.3"}},
|
||||||
|
{"<=1.2.3", []string{"<=", "1.2.3"}},
|
||||||
|
{"1.2.3", []string{"", "1.2.3"}},
|
||||||
|
{"=1.2.3", []string{"=", "1.2.3"}},
|
||||||
|
{"==1.2.3", []string{"==", "1.2.3"}},
|
||||||
|
{"!=1.2.3", []string{"!=", "1.2.3"}},
|
||||||
|
{"!1.2.3", []string{"!", "1.2.3"}},
|
||||||
|
{"error", nil},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
if op, v, err := splitComparatorVersion(tc.i); err != nil {
|
||||||
|
if tc.p != nil {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got error %q", tc.i, tc.p, err)
|
||||||
|
}
|
||||||
|
} else if op != tc.p[0] {
|
||||||
|
t.Errorf("Invalid operator for case %q: Expected %q, got: %q", tc.i, tc.p[0], op)
|
||||||
|
} else if v != tc.p[1] {
|
||||||
|
t.Errorf("Invalid version for case %q: Expected %q, got: %q", tc.i, tc.p[1], v)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildVersionRange(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
opStr string
|
||||||
|
vStr string
|
||||||
|
c func(comparator) bool
|
||||||
|
v string
|
||||||
|
}{
|
||||||
|
{">", "1.2.3", testGT, "1.2.3"},
|
||||||
|
{">=", "1.2.3", testGE, "1.2.3"},
|
||||||
|
{"<", "1.2.3", testLT, "1.2.3"},
|
||||||
|
{"<=", "1.2.3", testLE, "1.2.3"},
|
||||||
|
{"", "1.2.3", testEQ, "1.2.3"},
|
||||||
|
{"=", "1.2.3", testEQ, "1.2.3"},
|
||||||
|
{"==", "1.2.3", testEQ, "1.2.3"},
|
||||||
|
{"!=", "1.2.3", testNE, "1.2.3"},
|
||||||
|
{"!", "1.2.3", testNE, "1.2.3"},
|
||||||
|
{">>", "1.2.3", nil, ""}, // Invalid comparator
|
||||||
|
{"=", "invalid", nil, ""}, // Invalid version
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
if r, err := buildVersionRange(tc.opStr, tc.vStr); err != nil {
|
||||||
|
if tc.c != nil {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got error %q", strings.Join([]string{tc.opStr, tc.vStr}, ""), tc.v, err)
|
||||||
|
}
|
||||||
|
} else if r == nil {
|
||||||
|
t.Errorf("Invalid for case %q: got nil", strings.Join([]string{tc.opStr, tc.vStr}, ""))
|
||||||
|
} else {
|
||||||
|
// test version
|
||||||
|
if tv := MustParse(tc.v); !r.v.EQ(tv) {
|
||||||
|
t.Errorf("Invalid for case %q: Expected version %q, got: %q", strings.Join([]string{tc.opStr, tc.vStr}, ""), tv, r.v)
|
||||||
|
}
|
||||||
|
// test comparator
|
||||||
|
if r.c == nil {
|
||||||
|
t.Errorf("Invalid for case %q: got nil comparator", strings.Join([]string{tc.opStr, tc.vStr}, ""))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !tc.c(r.c) {
|
||||||
|
t.Errorf("Invalid comparator for case %q\n", strings.Join([]string{tc.opStr, tc.vStr}, ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitORParts(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i []string
|
||||||
|
o [][]string
|
||||||
|
}{
|
||||||
|
{[]string{">1.2.3", "||", "<1.2.3", "||", "=1.2.3"}, [][]string{
|
||||||
|
[]string{">1.2.3"},
|
||||||
|
[]string{"<1.2.3"},
|
||||||
|
[]string{"=1.2.3"},
|
||||||
|
}},
|
||||||
|
{[]string{">1.2.3", "<1.2.3", "||", "=1.2.3"}, [][]string{
|
||||||
|
[]string{">1.2.3", "<1.2.3"},
|
||||||
|
[]string{"=1.2.3"},
|
||||||
|
}},
|
||||||
|
{[]string{">1.2.3", "||"}, nil},
|
||||||
|
{[]string{"||", ">1.2.3"}, nil},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
o, err := splitORParts(tc.i)
|
||||||
|
if err != nil && tc.o != nil {
|
||||||
|
t.Errorf("Unexpected error for case %q: %s", tc.i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tc.o, o) {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.o, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetWildcardType(t *testing.T) {
|
||||||
|
wildcardTypeTests := []wildcardTypeTest{
|
||||||
|
{"x", majorWildcard},
|
||||||
|
{"1.x", minorWildcard},
|
||||||
|
{"1.2.x", patchWildcard},
|
||||||
|
{"fo.o.b.ar", noneWildcard},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range wildcardTypeTests {
|
||||||
|
o := getWildcardType(tc.input)
|
||||||
|
if o != tc.wildcardType {
|
||||||
|
t.Errorf("Invalid for case: %q: Expected %q, got: %q", tc.input, tc.wildcardType, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateVersionFromWildcard(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
s string
|
||||||
|
}{
|
||||||
|
{"1.2.x", "1.2.0"},
|
||||||
|
{"1.x", "1.0.0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
p := createVersionFromWildcard(tc.i)
|
||||||
|
if p != tc.s {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.s, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncrementMajorVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
s string
|
||||||
|
}{
|
||||||
|
{"1.2.3", "2.2.3"},
|
||||||
|
{"1.2", "2.2"},
|
||||||
|
{"foo.bar", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
p, _ := incrementMajorVersion(tc.i)
|
||||||
|
if p != tc.s {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.s, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncrementMinorVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
s string
|
||||||
|
}{
|
||||||
|
{"1.2.3", "1.3.3"},
|
||||||
|
{"1.2", "1.3"},
|
||||||
|
{"foo.bar", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
p, _ := incrementMinorVersion(tc.i)
|
||||||
|
if p != tc.s {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.s, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExpandWildcardVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
i [][]string
|
||||||
|
o [][]string
|
||||||
|
}{
|
||||||
|
{[][]string{[]string{"foox"}}, nil},
|
||||||
|
{[][]string{[]string{">=1.2.x"}}, [][]string{[]string{">=1.2.0"}}},
|
||||||
|
{[][]string{[]string{"<=1.2.x"}}, [][]string{[]string{"<1.3.0"}}},
|
||||||
|
{[][]string{[]string{">1.2.x"}}, [][]string{[]string{">=1.3.0"}}},
|
||||||
|
{[][]string{[]string{"<1.2.x"}}, [][]string{[]string{"<1.2.0"}}},
|
||||||
|
{[][]string{[]string{"!=1.2.x"}}, [][]string{[]string{"<1.2.0", ">=1.3.0"}}},
|
||||||
|
{[][]string{[]string{">=1.x"}}, [][]string{[]string{">=1.0.0"}}},
|
||||||
|
{[][]string{[]string{"<=1.x"}}, [][]string{[]string{"<2.0.0"}}},
|
||||||
|
{[][]string{[]string{">1.x"}}, [][]string{[]string{">=2.0.0"}}},
|
||||||
|
{[][]string{[]string{"<1.x"}}, [][]string{[]string{"<1.0.0"}}},
|
||||||
|
{[][]string{[]string{"!=1.x"}}, [][]string{[]string{"<1.0.0", ">=2.0.0"}}},
|
||||||
|
{[][]string{[]string{"1.2.x"}}, [][]string{[]string{">=1.2.0", "<1.3.0"}}},
|
||||||
|
{[][]string{[]string{"1.x"}}, [][]string{[]string{">=1.0.0", "<2.0.0"}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
o, _ := expandWildcardVersion(tc.i)
|
||||||
|
if !reflect.DeepEqual(tc.o, o) {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.o, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionRangeToRange(t *testing.T) {
|
||||||
|
vr := versionRange{
|
||||||
|
v: MustParse("1.2.3"),
|
||||||
|
c: compLT,
|
||||||
|
}
|
||||||
|
rf := vr.rangeFunc()
|
||||||
|
if !rf(MustParse("1.2.2")) || rf(MustParse("1.2.3")) {
|
||||||
|
t.Errorf("Invalid conversion to range func")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRangeAND(t *testing.T) {
|
||||||
|
v := MustParse("1.2.2")
|
||||||
|
v1 := MustParse("1.2.1")
|
||||||
|
v2 := MustParse("1.2.3")
|
||||||
|
rf1 := Range(func(v Version) bool {
|
||||||
|
return v.GT(v1)
|
||||||
|
})
|
||||||
|
rf2 := Range(func(v Version) bool {
|
||||||
|
return v.LT(v2)
|
||||||
|
})
|
||||||
|
rf := rf1.AND(rf2)
|
||||||
|
if rf(v1) {
|
||||||
|
t.Errorf("Invalid rangefunc, accepted: %s", v1)
|
||||||
|
}
|
||||||
|
if rf(v2) {
|
||||||
|
t.Errorf("Invalid rangefunc, accepted: %s", v2)
|
||||||
|
}
|
||||||
|
if !rf(v) {
|
||||||
|
t.Errorf("Invalid rangefunc, did not accept: %s", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRangeOR(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
v Version
|
||||||
|
b bool
|
||||||
|
}{
|
||||||
|
{MustParse("1.2.0"), true},
|
||||||
|
{MustParse("1.2.2"), false},
|
||||||
|
{MustParse("1.2.4"), true},
|
||||||
|
}
|
||||||
|
v1 := MustParse("1.2.1")
|
||||||
|
v2 := MustParse("1.2.3")
|
||||||
|
rf1 := Range(func(v Version) bool {
|
||||||
|
return v.LT(v1)
|
||||||
|
})
|
||||||
|
rf2 := Range(func(v Version) bool {
|
||||||
|
return v.GT(v2)
|
||||||
|
})
|
||||||
|
rf := rf1.OR(rf2)
|
||||||
|
for _, tc := range tests {
|
||||||
|
if r := rf(tc.v); r != tc.b {
|
||||||
|
t.Errorf("Invalid for case %q: Expected %t, got %t", tc.v, tc.b, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseRange(t *testing.T) {
|
||||||
|
type tv struct {
|
||||||
|
v string
|
||||||
|
b bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
i string
|
||||||
|
t []tv
|
||||||
|
}{
|
||||||
|
// Simple expressions
|
||||||
|
{">1.2.3", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", true},
|
||||||
|
}},
|
||||||
|
{">=1.2.3", []tv{
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", true},
|
||||||
|
{"1.2.2", false},
|
||||||
|
}},
|
||||||
|
{"<1.2.3", []tv{
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"<=1.2.3", []tv{
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"1.2.3", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"=1.2.3", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"==1.2.3", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"!=1.2.3", []tv{
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", true},
|
||||||
|
}},
|
||||||
|
{"!1.2.3", []tv{
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", true},
|
||||||
|
}},
|
||||||
|
// Simple Expression errors
|
||||||
|
{">>1.2.3", nil},
|
||||||
|
{"!1.2.3", nil},
|
||||||
|
{"1.0", nil},
|
||||||
|
{"string", nil},
|
||||||
|
{"", nil},
|
||||||
|
{"fo.ob.ar.x", nil},
|
||||||
|
// AND Expressions
|
||||||
|
{">1.2.2 <1.2.4", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{"<1.2.2 <1.2.4", []tv{
|
||||||
|
{"1.2.1", true},
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
{">1.2.2 <1.2.5 !=1.2.4", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
{"1.2.5", false},
|
||||||
|
}},
|
||||||
|
{">1.2.2 <1.2.5 !1.2.4", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
{"1.2.5", false},
|
||||||
|
}},
|
||||||
|
// OR Expressions
|
||||||
|
{">1.2.2 || <1.2.4", []tv{
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", true},
|
||||||
|
}},
|
||||||
|
{"<1.2.2 || >1.2.4", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", false},
|
||||||
|
{"1.2.4", false},
|
||||||
|
}},
|
||||||
|
// Wildcard expressions
|
||||||
|
{">1.x", []tv{
|
||||||
|
{"0.1.9", false},
|
||||||
|
{"1.2.6", false},
|
||||||
|
{"1.9.0", false},
|
||||||
|
{"2.0.0", true},
|
||||||
|
}},
|
||||||
|
{">1.2.x", []tv{
|
||||||
|
{"1.1.9", false},
|
||||||
|
{"1.2.6", false},
|
||||||
|
{"1.3.0", true},
|
||||||
|
}},
|
||||||
|
// Combined Expressions
|
||||||
|
{">1.2.2 <1.2.4 || >=2.0.0", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
{"2.0.0", true},
|
||||||
|
{"2.0.1", true},
|
||||||
|
}},
|
||||||
|
{"1.x || >=2.0.x <2.2.x", []tv{
|
||||||
|
{"0.9.2", false},
|
||||||
|
{"1.2.2", true},
|
||||||
|
{"2.0.0", true},
|
||||||
|
{"2.1.8", true},
|
||||||
|
{"2.2.0", false},
|
||||||
|
}},
|
||||||
|
{">1.2.2 <1.2.4 || >=2.0.0 <3.0.0", []tv{
|
||||||
|
{"1.2.2", false},
|
||||||
|
{"1.2.3", true},
|
||||||
|
{"1.2.4", false},
|
||||||
|
{"2.0.0", true},
|
||||||
|
{"2.0.1", true},
|
||||||
|
{"2.9.9", true},
|
||||||
|
{"3.0.0", false},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
r, err := ParseRange(tc.i)
|
||||||
|
if err != nil && tc.t != nil {
|
||||||
|
t.Errorf("Error parsing range %q: %s", tc.i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, tvc := range tc.t {
|
||||||
|
v := MustParse(tvc.v)
|
||||||
|
if res := r(v); res != tvc.b {
|
||||||
|
t.Errorf("Invalid for case %q matching %q: Expected %t, got: %t", tc.i, tvc.v, tvc.b, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMustParseRange(t *testing.T) {
|
||||||
|
testCase := ">1.2.2 <1.2.4 || >=2.0.0 <3.0.0"
|
||||||
|
r := MustParseRange(testCase)
|
||||||
|
if !r(MustParse("1.2.3")) {
|
||||||
|
t.Errorf("Unexpected range behavior on MustParseRange")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMustParseRange_panic(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if recover() == nil {
|
||||||
|
t.Errorf("Should have panicked")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
_ = MustParseRange("invalid version")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeParseSimple(b *testing.B) {
|
||||||
|
const VERSION = ">1.0.0"
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
ParseRange(VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeParseAverage(b *testing.B) {
|
||||||
|
const VERSION = ">=1.0.0 <2.0.0"
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
ParseRange(VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeParseComplex(b *testing.B) {
|
||||||
|
const VERSION = ">=1.0.0 <2.0.0 || >=3.0.1 <4.0.0 !=3.0.3 || >=5.0.0"
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
ParseRange(VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeMatchSimple(b *testing.B) {
|
||||||
|
const VERSION = ">1.0.0"
|
||||||
|
r, _ := ParseRange(VERSION)
|
||||||
|
v := MustParse("2.0.0")
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
r(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeMatchAverage(b *testing.B) {
|
||||||
|
const VERSION = ">=1.0.0 <2.0.0"
|
||||||
|
r, _ := ParseRange(VERSION)
|
||||||
|
v := MustParse("1.2.3")
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
r(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRangeMatchComplex(b *testing.B) {
|
||||||
|
const VERSION = ">=1.0.0 <2.0.0 || >=3.0.1 <4.0.0 !=3.0.3 || >=5.0.0"
|
||||||
|
r, _ := ParseRange(VERSION)
|
||||||
|
v := MustParse("5.0.1")
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
r(v)
|
||||||
|
}
|
||||||
|
}
|
418
vendor/github.com/blang/semver/semver.go
generated
vendored
Normal file
418
vendor/github.com/blang/semver/semver.go
generated
vendored
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
numbers string = "0123456789"
|
||||||
|
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
|
||||||
|
alphanum = alphas + numbers
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpecVersion is the latest fully supported spec version of semver
|
||||||
|
var SpecVersion = Version{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
Patch: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version represents a semver compatible version
|
||||||
|
type Version struct {
|
||||||
|
Major uint64
|
||||||
|
Minor uint64
|
||||||
|
Patch uint64
|
||||||
|
Pre []PRVersion
|
||||||
|
Build []string //No Precendence
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version to string
|
||||||
|
func (v Version) String() string {
|
||||||
|
b := make([]byte, 0, 5)
|
||||||
|
b = strconv.AppendUint(b, v.Major, 10)
|
||||||
|
b = append(b, '.')
|
||||||
|
b = strconv.AppendUint(b, v.Minor, 10)
|
||||||
|
b = append(b, '.')
|
||||||
|
b = strconv.AppendUint(b, v.Patch, 10)
|
||||||
|
|
||||||
|
if len(v.Pre) > 0 {
|
||||||
|
b = append(b, '-')
|
||||||
|
b = append(b, v.Pre[0].String()...)
|
||||||
|
|
||||||
|
for _, pre := range v.Pre[1:] {
|
||||||
|
b = append(b, '.')
|
||||||
|
b = append(b, pre.String()...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.Build) > 0 {
|
||||||
|
b = append(b, '+')
|
||||||
|
b = append(b, v.Build[0]...)
|
||||||
|
|
||||||
|
for _, build := range v.Build[1:] {
|
||||||
|
b = append(b, '.')
|
||||||
|
b = append(b, build...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals checks if v is equal to o.
|
||||||
|
func (v Version) Equals(o Version) bool {
|
||||||
|
return (v.Compare(o) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EQ checks if v is equal to o.
|
||||||
|
func (v Version) EQ(o Version) bool {
|
||||||
|
return (v.Compare(o) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NE checks if v is not equal to o.
|
||||||
|
func (v Version) NE(o Version) bool {
|
||||||
|
return (v.Compare(o) != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GT checks if v is greater than o.
|
||||||
|
func (v Version) GT(o Version) bool {
|
||||||
|
return (v.Compare(o) == 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GTE checks if v is greater than or equal to o.
|
||||||
|
func (v Version) GTE(o Version) bool {
|
||||||
|
return (v.Compare(o) >= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GE checks if v is greater than or equal to o.
|
||||||
|
func (v Version) GE(o Version) bool {
|
||||||
|
return (v.Compare(o) >= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LT checks if v is less than o.
|
||||||
|
func (v Version) LT(o Version) bool {
|
||||||
|
return (v.Compare(o) == -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LTE checks if v is less than or equal to o.
|
||||||
|
func (v Version) LTE(o Version) bool {
|
||||||
|
return (v.Compare(o) <= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LE checks if v is less than or equal to o.
|
||||||
|
func (v Version) LE(o Version) bool {
|
||||||
|
return (v.Compare(o) <= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare compares Versions v to o:
|
||||||
|
// -1 == v is less than o
|
||||||
|
// 0 == v is equal to o
|
||||||
|
// 1 == v is greater than o
|
||||||
|
func (v Version) Compare(o Version) int {
|
||||||
|
if v.Major != o.Major {
|
||||||
|
if v.Major > o.Major {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if v.Minor != o.Minor {
|
||||||
|
if v.Minor > o.Minor {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if v.Patch != o.Patch {
|
||||||
|
if v.Patch > o.Patch {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick comparison if a version has no prerelease versions
|
||||||
|
if len(v.Pre) == 0 && len(o.Pre) == 0 {
|
||||||
|
return 0
|
||||||
|
} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
|
||||||
|
return 1
|
||||||
|
} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for ; i < len(v.Pre) && i < len(o.Pre); i++ {
|
||||||
|
if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
|
||||||
|
continue
|
||||||
|
} else if comp == 1 {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all pr versions are the equal but one has further prversion, this one greater
|
||||||
|
if i == len(v.Pre) && i == len(o.Pre) {
|
||||||
|
return 0
|
||||||
|
} else if i == len(v.Pre) && i < len(o.Pre) {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates v and returns error in case
|
||||||
|
func (v Version) Validate() error {
|
||||||
|
// Major, Minor, Patch already validated using uint64
|
||||||
|
|
||||||
|
for _, pre := range v.Pre {
|
||||||
|
if !pre.IsNum { //Numeric prerelease versions already uint64
|
||||||
|
if len(pre.VersionStr) == 0 {
|
||||||
|
return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
|
||||||
|
}
|
||||||
|
if !containsOnly(pre.VersionStr, alphanum) {
|
||||||
|
return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, build := range v.Build {
|
||||||
|
if len(build) == 0 {
|
||||||
|
return fmt.Errorf("Build meta data can not be empty %q", build)
|
||||||
|
}
|
||||||
|
if !containsOnly(build, alphanum) {
|
||||||
|
return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
|
||||||
|
func New(s string) (vp *Version, err error) {
|
||||||
|
v, err := Parse(s)
|
||||||
|
vp = &v
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make is an alias for Parse, parses version string and returns a validated Version or error
|
||||||
|
func Make(s string) (Version, error) {
|
||||||
|
return Parse(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
|
||||||
|
// specs to be parsed by this library. It does so by normalizing versions before passing them to
|
||||||
|
// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
|
||||||
|
// with only major and minor components specified
|
||||||
|
func ParseTolerant(s string) (Version, error) {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
s = strings.TrimPrefix(s, "v")
|
||||||
|
|
||||||
|
// Split into major.minor.(patch+pr+meta)
|
||||||
|
parts := strings.SplitN(s, ".", 3)
|
||||||
|
if len(parts) < 3 {
|
||||||
|
if strings.ContainsAny(parts[len(parts)-1], "+-") {
|
||||||
|
return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
|
||||||
|
}
|
||||||
|
for len(parts) < 3 {
|
||||||
|
parts = append(parts, "0")
|
||||||
|
}
|
||||||
|
s = strings.Join(parts, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Parse(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses version string and returns a validated Version or error
|
||||||
|
func Parse(s string) (Version, error) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return Version{}, errors.New("Version string empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split into major.minor.(patch+pr+meta)
|
||||||
|
parts := strings.SplitN(s, ".", 3)
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return Version{}, errors.New("No Major.Minor.Patch elements found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Major
|
||||||
|
if !containsOnly(parts[0], numbers) {
|
||||||
|
return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
|
||||||
|
}
|
||||||
|
if hasLeadingZeroes(parts[0]) {
|
||||||
|
return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
|
||||||
|
}
|
||||||
|
major, err := strconv.ParseUint(parts[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return Version{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor
|
||||||
|
if !containsOnly(parts[1], numbers) {
|
||||||
|
return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
|
||||||
|
}
|
||||||
|
if hasLeadingZeroes(parts[1]) {
|
||||||
|
return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
|
||||||
|
}
|
||||||
|
minor, err := strconv.ParseUint(parts[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return Version{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v := Version{}
|
||||||
|
v.Major = major
|
||||||
|
v.Minor = minor
|
||||||
|
|
||||||
|
var build, prerelease []string
|
||||||
|
patchStr := parts[2]
|
||||||
|
|
||||||
|
if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
|
||||||
|
build = strings.Split(patchStr[buildIndex+1:], ".")
|
||||||
|
patchStr = patchStr[:buildIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
|
||||||
|
prerelease = strings.Split(patchStr[preIndex+1:], ".")
|
||||||
|
patchStr = patchStr[:preIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !containsOnly(patchStr, numbers) {
|
||||||
|
return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
|
||||||
|
}
|
||||||
|
if hasLeadingZeroes(patchStr) {
|
||||||
|
return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
|
||||||
|
}
|
||||||
|
patch, err := strconv.ParseUint(patchStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return Version{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Patch = patch
|
||||||
|
|
||||||
|
// Prerelease
|
||||||
|
for _, prstr := range prerelease {
|
||||||
|
parsedPR, err := NewPRVersion(prstr)
|
||||||
|
if err != nil {
|
||||||
|
return Version{}, err
|
||||||
|
}
|
||||||
|
v.Pre = append(v.Pre, parsedPR)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build meta data
|
||||||
|
for _, str := range build {
|
||||||
|
if len(str) == 0 {
|
||||||
|
return Version{}, errors.New("Build meta data is empty")
|
||||||
|
}
|
||||||
|
if !containsOnly(str, alphanum) {
|
||||||
|
return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
|
||||||
|
}
|
||||||
|
v.Build = append(v.Build, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParse is like Parse but panics if the version cannot be parsed.
|
||||||
|
func MustParse(s string) Version {
|
||||||
|
v, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(`semver: Parse(` + s + `): ` + err.Error())
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRVersion represents a PreRelease Version
|
||||||
|
type PRVersion struct {
|
||||||
|
VersionStr string
|
||||||
|
VersionNum uint64
|
||||||
|
IsNum bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPRVersion creates a new valid prerelease version
|
||||||
|
func NewPRVersion(s string) (PRVersion, error) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return PRVersion{}, errors.New("Prerelease is empty")
|
||||||
|
}
|
||||||
|
v := PRVersion{}
|
||||||
|
if containsOnly(s, numbers) {
|
||||||
|
if hasLeadingZeroes(s) {
|
||||||
|
return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
|
||||||
|
}
|
||||||
|
num, err := strconv.ParseUint(s, 10, 64)
|
||||||
|
|
||||||
|
// Might never be hit, but just in case
|
||||||
|
if err != nil {
|
||||||
|
return PRVersion{}, err
|
||||||
|
}
|
||||||
|
v.VersionNum = num
|
||||||
|
v.IsNum = true
|
||||||
|
} else if containsOnly(s, alphanum) {
|
||||||
|
v.VersionStr = s
|
||||||
|
v.IsNum = false
|
||||||
|
} else {
|
||||||
|
return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNumeric checks if prerelease-version is numeric
|
||||||
|
func (v PRVersion) IsNumeric() bool {
|
||||||
|
return v.IsNum
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare compares two PreRelease Versions v and o:
|
||||||
|
// -1 == v is less than o
|
||||||
|
// 0 == v is equal to o
|
||||||
|
// 1 == v is greater than o
|
||||||
|
func (v PRVersion) Compare(o PRVersion) int {
|
||||||
|
if v.IsNum && !o.IsNum {
|
||||||
|
return -1
|
||||||
|
} else if !v.IsNum && o.IsNum {
|
||||||
|
return 1
|
||||||
|
} else if v.IsNum && o.IsNum {
|
||||||
|
if v.VersionNum == o.VersionNum {
|
||||||
|
return 0
|
||||||
|
} else if v.VersionNum > o.VersionNum {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
} else { // both are Alphas
|
||||||
|
if v.VersionStr == o.VersionStr {
|
||||||
|
return 0
|
||||||
|
} else if v.VersionStr > o.VersionStr {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreRelease version to string
|
||||||
|
func (v PRVersion) String() string {
|
||||||
|
if v.IsNum {
|
||||||
|
return strconv.FormatUint(v.VersionNum, 10)
|
||||||
|
}
|
||||||
|
return v.VersionStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsOnly(s string, set string) bool {
|
||||||
|
return strings.IndexFunc(s, func(r rune) bool {
|
||||||
|
return !strings.ContainsRune(set, r)
|
||||||
|
}) == -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasLeadingZeroes(s string) bool {
|
||||||
|
return len(s) > 1 && s[0] == '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBuildVersion creates a new valid build version
|
||||||
|
func NewBuildVersion(s string) (string, error) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return "", errors.New("Buildversion is empty")
|
||||||
|
}
|
||||||
|
if !containsOnly(s, alphanum) {
|
||||||
|
return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
458
vendor/github.com/blang/semver/semver_test.go
generated
vendored
Normal file
458
vendor/github.com/blang/semver/semver_test.go
generated
vendored
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func prstr(s string) PRVersion {
|
||||||
|
return PRVersion{s, 0, false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prnum(i uint64) PRVersion {
|
||||||
|
return PRVersion{"", i, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
type formatTest struct {
|
||||||
|
v Version
|
||||||
|
result string
|
||||||
|
}
|
||||||
|
|
||||||
|
var formatTests = []formatTest{
|
||||||
|
{Version{1, 2, 3, nil, nil}, "1.2.3"},
|
||||||
|
{Version{0, 0, 1, nil, nil}, "0.0.1"},
|
||||||
|
{Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1-alpha.preview+123.456"},
|
||||||
|
{Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3-alpha.1+123.456"},
|
||||||
|
{Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3-alpha.1"},
|
||||||
|
{Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3+123.456"},
|
||||||
|
// Prereleases and build metadata hyphens
|
||||||
|
{Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3-alpha.b-eta+123.b-uild"},
|
||||||
|
{Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3+123.b-uild"},
|
||||||
|
{Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3-alpha.b-eta"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var tolerantFormatTests = []formatTest{
|
||||||
|
{Version{1, 2, 3, nil, nil}, "v1.2.3"},
|
||||||
|
{Version{1, 2, 3, nil, nil}, " 1.2.3 "},
|
||||||
|
{Version{1, 2, 0, nil, nil}, "1.2"},
|
||||||
|
{Version{1, 0, 0, nil, nil}, "1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringer(t *testing.T) {
|
||||||
|
for _, test := range formatTests {
|
||||||
|
if res := test.v.String(); res != test.result {
|
||||||
|
t.Errorf("Stringer, expected %q but got %q", test.result, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
for _, test := range formatTests {
|
||||||
|
if v, err := Parse(test.result); err != nil {
|
||||||
|
t.Errorf("Error parsing %q: %q", test.result, err)
|
||||||
|
} else if comp := v.Compare(test.v); comp != 0 {
|
||||||
|
t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp)
|
||||||
|
} else if err := v.Validate(); err != nil {
|
||||||
|
t.Errorf("Error validating parsed version %q: %q", test.v, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseTolerant(t *testing.T) {
|
||||||
|
for _, test := range tolerantFormatTests {
|
||||||
|
if v, err := ParseTolerant(test.result); err != nil {
|
||||||
|
t.Errorf("Error parsing %q: %q", test.result, err)
|
||||||
|
} else if comp := v.Compare(test.v); comp != 0 {
|
||||||
|
t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp)
|
||||||
|
} else if err := v.Validate(); err != nil {
|
||||||
|
t.Errorf("Error validating parsed version %q: %q", test.v, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMustParse(t *testing.T) {
|
||||||
|
_ = MustParse("32.2.1-alpha")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMustParse_panic(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if recover() == nil {
|
||||||
|
t.Errorf("Should have panicked")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
_ = MustParse("invalid version")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidate(t *testing.T) {
|
||||||
|
for _, test := range formatTests {
|
||||||
|
if err := test.v.Validate(); err != nil {
|
||||||
|
t.Errorf("Error validating %q: %q", test.v, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type compareTest struct {
|
||||||
|
v1 Version
|
||||||
|
v2 Version
|
||||||
|
result int
|
||||||
|
}
|
||||||
|
|
||||||
|
var compareTests = []compareTest{
|
||||||
|
{Version{1, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 0},
|
||||||
|
{Version{2, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 1},
|
||||||
|
{Version{0, 1, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 0},
|
||||||
|
{Version{0, 2, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 1},
|
||||||
|
{Version{0, 0, 1, nil, nil}, Version{0, 0, 1, nil, nil}, 0},
|
||||||
|
{Version{0, 0, 2, nil, nil}, Version{0, 0, 1, nil, nil}, 1},
|
||||||
|
{Version{1, 2, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 0},
|
||||||
|
{Version{2, 2, 4, nil, nil}, Version{1, 2, 4, nil, nil}, 1},
|
||||||
|
{Version{1, 3, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
|
||||||
|
{Version{1, 2, 4, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
|
||||||
|
|
||||||
|
// Spec Examples #11
|
||||||
|
{Version{1, 0, 0, nil, nil}, Version{2, 0, 0, nil, nil}, -1},
|
||||||
|
{Version{2, 0, 0, nil, nil}, Version{2, 1, 0, nil, nil}, -1},
|
||||||
|
{Version{2, 1, 0, nil, nil}, Version{2, 1, 1, nil, nil}, -1},
|
||||||
|
|
||||||
|
// Spec Examples #9
|
||||||
|
{Version{1, 0, 0, nil, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, 1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, -1},
|
||||||
|
{Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, Version{1, 0, 0, nil, nil}, -1},
|
||||||
|
|
||||||
|
// Ignore Build metadata
|
||||||
|
{Version{1, 0, 0, nil, []string{"1", "2", "3"}}, Version{1, 0, 0, nil, nil}, 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompare(t *testing.T) {
|
||||||
|
for _, test := range compareTests {
|
||||||
|
if res := test.v1.Compare(test.v2); res != test.result {
|
||||||
|
t.Errorf("Comparing %q : %q, expected %d but got %d", test.v1, test.v2, test.result, res)
|
||||||
|
}
|
||||||
|
//Test counterpart
|
||||||
|
if res := test.v2.Compare(test.v1); res != -test.result {
|
||||||
|
t.Errorf("Comparing %q : %q, expected %d but got %d", test.v2, test.v1, -test.result, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrongformatTest struct {
|
||||||
|
v *Version
|
||||||
|
str string
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrongformatTests = []wrongformatTest{
|
||||||
|
{nil, ""},
|
||||||
|
{nil, "."},
|
||||||
|
{nil, "1."},
|
||||||
|
{nil, ".1"},
|
||||||
|
{nil, "a.b.c"},
|
||||||
|
{nil, "1.a.b"},
|
||||||
|
{nil, "1.1.a"},
|
||||||
|
{nil, "1.a.1"},
|
||||||
|
{nil, "a.1.1"},
|
||||||
|
{nil, ".."},
|
||||||
|
{nil, "1.."},
|
||||||
|
{nil, "1.1."},
|
||||||
|
{nil, "1..1"},
|
||||||
|
{nil, "1.1.+123"},
|
||||||
|
{nil, "1.1.-beta"},
|
||||||
|
{nil, "-1.1.1"},
|
||||||
|
{nil, "1.-1.1"},
|
||||||
|
{nil, "1.1.-1"},
|
||||||
|
// giant numbers
|
||||||
|
{nil, "20000000000000000000.1.1"},
|
||||||
|
{nil, "1.20000000000000000000.1"},
|
||||||
|
{nil, "1.1.20000000000000000000"},
|
||||||
|
{nil, "1.1.1-20000000000000000000"},
|
||||||
|
// Leading zeroes
|
||||||
|
{nil, "01.1.1"},
|
||||||
|
{nil, "001.1.1"},
|
||||||
|
{nil, "1.01.1"},
|
||||||
|
{nil, "1.001.1"},
|
||||||
|
{nil, "1.1.01"},
|
||||||
|
{nil, "1.1.001"},
|
||||||
|
{nil, "1.1.1-01"},
|
||||||
|
{nil, "1.1.1-001"},
|
||||||
|
{nil, "1.1.1-beta.01"},
|
||||||
|
{nil, "1.1.1-beta.001"},
|
||||||
|
{&Version{0, 0, 0, []PRVersion{prstr("!")}, nil}, "0.0.0-!"},
|
||||||
|
{&Version{0, 0, 0, nil, []string{"!"}}, "0.0.0+!"},
|
||||||
|
// empty prversion
|
||||||
|
{&Version{0, 0, 0, []PRVersion{prstr(""), prstr("alpha")}, nil}, "0.0.0-.alpha"},
|
||||||
|
// empty build meta data
|
||||||
|
{&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{""}}, "0.0.0-alpha+"},
|
||||||
|
{&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{"test", ""}}, "0.0.0-alpha+test."},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrongFormat(t *testing.T) {
|
||||||
|
for _, test := range wrongformatTests {
|
||||||
|
|
||||||
|
if res, err := Parse(test.str); err == nil {
|
||||||
|
t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.v != nil {
|
||||||
|
if err := test.v.Validate(); err == nil {
|
||||||
|
t.Errorf("Validating wrong format version %q (%q), expected error", test.v, test.str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrongTolerantFormatTests = []wrongformatTest{
|
||||||
|
{nil, "1.0+abc"},
|
||||||
|
{nil, "1.0-rc.1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrongTolerantFormat(t *testing.T) {
|
||||||
|
for _, test := range wrongTolerantFormatTests {
|
||||||
|
if res, err := ParseTolerant(test.str); err == nil {
|
||||||
|
t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareHelper(t *testing.T) {
|
||||||
|
v := Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}
|
||||||
|
v1 := Version{1, 0, 0, nil, nil}
|
||||||
|
if !v.EQ(v) {
|
||||||
|
t.Errorf("%q should be equal to %q", v, v)
|
||||||
|
}
|
||||||
|
if !v.Equals(v) {
|
||||||
|
t.Errorf("%q should be equal to %q", v, v)
|
||||||
|
}
|
||||||
|
if !v1.NE(v) {
|
||||||
|
t.Errorf("%q should not be equal to %q", v1, v)
|
||||||
|
}
|
||||||
|
if !v.GTE(v) {
|
||||||
|
t.Errorf("%q should be greater than or equal to %q", v, v)
|
||||||
|
}
|
||||||
|
if !v.LTE(v) {
|
||||||
|
t.Errorf("%q should be less than or equal to %q", v, v)
|
||||||
|
}
|
||||||
|
if !v.LT(v1) {
|
||||||
|
t.Errorf("%q should be less than %q", v, v1)
|
||||||
|
}
|
||||||
|
if !v.LTE(v1) {
|
||||||
|
t.Errorf("%q should be less than or equal %q", v, v1)
|
||||||
|
}
|
||||||
|
if !v.LE(v1) {
|
||||||
|
t.Errorf("%q should be less than or equal %q", v, v1)
|
||||||
|
}
|
||||||
|
if !v1.GT(v) {
|
||||||
|
t.Errorf("%q should be greater than %q", v1, v)
|
||||||
|
}
|
||||||
|
if !v1.GTE(v) {
|
||||||
|
t.Errorf("%q should be greater than or equal %q", v1, v)
|
||||||
|
}
|
||||||
|
if !v1.GE(v) {
|
||||||
|
t.Errorf("%q should be greater than or equal %q", v1, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreReleaseVersions(t *testing.T) {
|
||||||
|
p1, err := NewPRVersion("123")
|
||||||
|
if !p1.IsNumeric() {
|
||||||
|
t.Errorf("Expected numeric prversion, got %q", p1)
|
||||||
|
}
|
||||||
|
if p1.VersionNum != 123 {
|
||||||
|
t.Error("Wrong prversion number")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Not expected error %q", err)
|
||||||
|
}
|
||||||
|
p2, err := NewPRVersion("alpha")
|
||||||
|
if p2.IsNumeric() {
|
||||||
|
t.Errorf("Expected non-numeric prversion, got %q", p2)
|
||||||
|
}
|
||||||
|
if p2.VersionStr != "alpha" {
|
||||||
|
t.Error("Wrong prversion string")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Not expected error %q", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildMetaDataVersions(t *testing.T) {
|
||||||
|
_, err := NewBuildVersion("123")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = NewBuildVersion("build")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = NewBuildVersion("test?")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error, got none")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = NewBuildVersion("")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error, got none")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewHelper(t *testing.T) {
|
||||||
|
v, err := New("1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns pointer
|
||||||
|
if v == nil {
|
||||||
|
t.Fatal("Version is nil")
|
||||||
|
}
|
||||||
|
if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
|
||||||
|
t.Fatal("Unexpected comparison problem")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeHelper(t *testing.T) {
|
||||||
|
v, err := Make("1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error %q", err)
|
||||||
|
}
|
||||||
|
if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
|
||||||
|
t.Fatal("Unexpected comparison problem")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParseSimple(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1"
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
Parse(VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParseComplex(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1-alpha.preview+123.456"
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
Parse(VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParseAverage(b *testing.B) {
|
||||||
|
l := len(formatTests)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
Parse(formatTests[n%l].result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkParseTolerantAverage(b *testing.B) {
|
||||||
|
l := len(tolerantFormatTests)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
ParseTolerant(tolerantFormatTests[n%l].result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStringSimple(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStringLarger(b *testing.B) {
|
||||||
|
const VERSION = "11.15.2012"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStringComplex(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1-alpha.preview+123.456"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkStringAverage(b *testing.B) {
|
||||||
|
l := len(formatTests)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
formatTests[n%l].v.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkValidateSimple(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.Validate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkValidateComplex(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1-alpha.preview+123.456"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.Validate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkValidateAverage(b *testing.B) {
|
||||||
|
l := len(formatTests)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
formatTests[n%l].v.Validate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCompareSimple(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.Compare(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCompareComplex(b *testing.B) {
|
||||||
|
const VERSION = "0.0.1-alpha.preview+123.456"
|
||||||
|
v, _ := Parse(VERSION)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
v.Compare(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCompareAverage(b *testing.B) {
|
||||||
|
l := len(compareTests)
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
compareTests[n%l].v1.Compare((compareTests[n%l].v2))
|
||||||
|
}
|
||||||
|
}
|
28
vendor/github.com/blang/semver/sort.go
generated
vendored
Normal file
28
vendor/github.com/blang/semver/sort.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Versions represents multiple versions.
|
||||||
|
type Versions []Version
|
||||||
|
|
||||||
|
// Len returns length of version collection
|
||||||
|
func (s Versions) Len() int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps two versions inside the collection by its indices
|
||||||
|
func (s Versions) Swap(i, j int) {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less checks if version at index i is less than version at index j
|
||||||
|
func (s Versions) Less(i, j int) bool {
|
||||||
|
return s[i].LT(s[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort sorts a slice of versions
|
||||||
|
func Sort(versions []Version) {
|
||||||
|
sort.Sort(Versions(versions))
|
||||||
|
}
|
30
vendor/github.com/blang/semver/sort_test.go
generated
vendored
Normal file
30
vendor/github.com/blang/semver/sort_test.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSort(t *testing.T) {
|
||||||
|
v100, _ := Parse("1.0.0")
|
||||||
|
v010, _ := Parse("0.1.0")
|
||||||
|
v001, _ := Parse("0.0.1")
|
||||||
|
versions := []Version{v010, v100, v001}
|
||||||
|
Sort(versions)
|
||||||
|
|
||||||
|
correct := []Version{v001, v010, v100}
|
||||||
|
if !reflect.DeepEqual(versions, correct) {
|
||||||
|
t.Fatalf("Sort returned wrong order: %s", versions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSort(b *testing.B) {
|
||||||
|
v100, _ := Parse("1.0.0")
|
||||||
|
v010, _ := Parse("0.1.0")
|
||||||
|
v001, _ := Parse("0.0.1")
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
Sort([]Version{v010, v100, v001})
|
||||||
|
}
|
||||||
|
}
|
30
vendor/github.com/blang/semver/sql.go
generated
vendored
Normal file
30
vendor/github.com/blang/semver/sql.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Scan implements the database/sql.Scanner interface.
|
||||||
|
func (v *Version) Scan(src interface{}) (err error) {
|
||||||
|
var str string
|
||||||
|
switch src := src.(type) {
|
||||||
|
case string:
|
||||||
|
str = src
|
||||||
|
case []byte:
|
||||||
|
str = string(src)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, err := Parse(str); err == nil {
|
||||||
|
*v = t
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value implements the database/sql/driver.Valuer interface.
|
||||||
|
func (v Version) Value() (driver.Value, error) {
|
||||||
|
return v.String(), nil
|
||||||
|
}
|
38
vendor/github.com/blang/semver/sql_test.go
generated
vendored
Normal file
38
vendor/github.com/blang/semver/sql_test.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type scanTest struct {
|
||||||
|
val interface{}
|
||||||
|
shouldError bool
|
||||||
|
expected string
|
||||||
|
}
|
||||||
|
|
||||||
|
var scanTests = []scanTest{
|
||||||
|
{"1.2.3", false, "1.2.3"},
|
||||||
|
{[]byte("1.2.3"), false, "1.2.3"},
|
||||||
|
{7, true, ""},
|
||||||
|
{7e4, true, ""},
|
||||||
|
{true, true, ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScanString(t *testing.T) {
|
||||||
|
for _, tc := range scanTests {
|
||||||
|
s := &Version{}
|
||||||
|
err := s.Scan(tc.val)
|
||||||
|
if tc.shouldError {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Scan did not return an error on %v (%T)", tc.val, tc.val)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Scan returned an unexpected error: %s (%T) on %v (%T)", tc.val, tc.val, tc.val, tc.val)
|
||||||
|
}
|
||||||
|
if val, _ := s.Value(); val != tc.expected {
|
||||||
|
t.Errorf("Wrong Value returned, expected %q, got %q", tc.expected, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user