sort versions semantically
...rather than relying on api order [#76848252] Signed-off-by: Alex Suraci <asuraci@pivotal.io>
This commit is contained in:
5
Godeps/Godeps.json
generated
5
Godeps/Godeps.json
generated
@@ -10,6 +10,11 @@
|
||||
"Comment": "weekly-43",
|
||||
"Rev": "d4571a95014ff1fdd0055dc0f6b7e977a42b1e5a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/blang/semver",
|
||||
"Comment": "v2.1.0",
|
||||
"Rev": "9bf7bff48b0388cb75991e58c6df7d13e982f1f2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/go-github/github",
|
||||
"Rev": "32eadd61120c7a84b8eeac3ac3795cb453a33054"
|
||||
|
22
Godeps/_workspace/src/github.com/blang/semver/LICENSE
generated
vendored
Normal file
22
Godeps/_workspace/src/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.
|
||||
|
142
Godeps/_workspace/src/github.com/blang/semver/README.md
generated
vendored
Normal file
142
Godeps/_workspace/src/github.com/blang/semver/README.md
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
semver for golang [](https://drone.io/github.com/blang/semver/latest) [](https://godoc.org/github.com/blang/semver) [](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.New("1.0.0-beta")
|
||||
v2, err := semver.New("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
|
||||
- Sortable (implements sort.Interface)
|
||||
- database/sql compatible (sql.Scanner/Valuer)
|
||||
- encoding/json compatible (json.Marshaler/Unmarshaler)
|
||||
|
||||
|
||||
Example
|
||||
-----
|
||||
|
||||
Have a look at full examples in [examples/main.go](examples/main.go)
|
||||
|
||||
```go
|
||||
import github.com/blang/semver
|
||||
|
||||
v, err := semver.New("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.New("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 5000000 328 ns/op 49 B/op 1 allocs/op
|
||||
BenchmarkParseComplex 1000000 2105 ns/op 263 B/op 7 allocs/op
|
||||
BenchmarkParseAverage 1000000 1301 ns/op 168 B/op 4 allocs/op
|
||||
BenchmarkStringSimple 10000000 130 ns/op 5 B/op 1 allocs/op
|
||||
BenchmarkStringLarger 5000000 280 ns/op 32 B/op 2 allocs/op
|
||||
BenchmarkStringComplex 3000000 512 ns/op 80 B/op 3 allocs/op
|
||||
BenchmarkStringAverage 5000000 387 ns/op 47 B/op 2 allocs/op
|
||||
BenchmarkValidateSimple 500000000 7.92 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkValidateComplex 2000000 923 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkValidateAverage 5000000 452 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkCompareSimple 100000000 11.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkCompareComplex 50000000 40.9 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkCompareAverage 50000000 43.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkSort 5000000 436 ns/op 259 B/op 2 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
Godeps/_workspace/src/github.com/blang/semver/examples/main.go
generated
vendored
Normal file
83
Godeps/_workspace/src/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)
|
||||
}
|
||||
}
|
||||
|
||||
// New == Parse
|
||||
v001, err := semver.New("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
Godeps/_workspace/src/github.com/blang/semver/json.go
generated
vendored
Normal file
23
Godeps/_workspace/src/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
|
||||
}
|
45
Godeps/_workspace/src/github.com/blang/semver/json_test.go
generated
vendored
Normal file
45
Godeps/_workspace/src/github.com/blang/semver/json_test.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
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")
|
||||
}
|
||||
}
|
382
Godeps/_workspace/src/github.com/blang/semver/semver.go
generated
vendored
Normal file
382
Godeps/_workspace/src/github.com/blang/semver/semver.go
generated
vendored
Normal file
@@ -0,0 +1,382 @@
|
||||
package semver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
numbers string = "0123456789"
|
||||
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
|
||||
alphanum = alphas + numbers
|
||||
)
|
||||
|
||||
// Latest fully supported spec version
|
||||
var SPEC_VERSION = Version{
|
||||
Major: 2,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// Checks if v is equal to o.
|
||||
func (v Version) Equals(o Version) bool {
|
||||
return (v.Compare(o) == 0)
|
||||
}
|
||||
|
||||
// Checks if v is equal to o.
|
||||
func (v Version) EQ(o Version) bool {
|
||||
return (v.Compare(o) == 0)
|
||||
}
|
||||
|
||||
// Checks if v is not equal to o.
|
||||
func (v Version) NE(o Version) bool {
|
||||
return (v.Compare(o) != 0)
|
||||
}
|
||||
|
||||
// Checks if v is greater than o.
|
||||
func (v Version) GT(o Version) bool {
|
||||
return (v.Compare(o) == 1)
|
||||
}
|
||||
|
||||
// Checks if v is greater than or equal to o.
|
||||
func (v Version) GTE(o Version) bool {
|
||||
return (v.Compare(o) >= 0)
|
||||
}
|
||||
|
||||
// Checks if v is greater than or equal to o.
|
||||
func (v Version) GE(o Version) bool {
|
||||
return (v.Compare(o) >= 0)
|
||||
}
|
||||
|
||||
// Checks if v is less than o.
|
||||
func (v Version) LT(o Version) bool {
|
||||
return (v.Compare(o) == -1)
|
||||
}
|
||||
|
||||
// Checks if v is less than or equal to o.
|
||||
func (v Version) LTE(o Version) bool {
|
||||
return (v.Compare(o) <= 0)
|
||||
}
|
||||
|
||||
// Checks if v is less than or equal to o.
|
||||
func (v Version) LE(o Version) bool {
|
||||
return (v.Compare(o) <= 0)
|
||||
}
|
||||
|
||||
// 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
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
if v.Minor != o.Minor {
|
||||
if v.Minor > o.Minor {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
if v.Patch != o.Patch {
|
||||
if v.Patch > o.Patch {
|
||||
return 1
|
||||
} else {
|
||||
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
|
||||
} else {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Alias for Parse, parses version string and returns a validated Version or error
|
||||
func New(s string) (Version, error) {
|
||||
return Parse(s)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// PreRelease Version
|
||||
type PRVersion struct {
|
||||
VersionStr string
|
||||
VersionNum uint64
|
||||
IsNum bool
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Is pre release version numeric?
|
||||
func (v PRVersion) IsNumeric() bool {
|
||||
return v.IsNum
|
||||
}
|
||||
|
||||
// Compares PreRelease Versions v to 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'
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
389
Godeps/_workspace/src/github.com/blang/semver/semver_test.go
generated
vendored
Normal file
389
Godeps/_workspace/src/github.com/blang/semver/semver_test.go
generated
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
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"},
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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++ {
|
||||
New(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++ {
|
||||
New(VERSION)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseAverage(b *testing.B) {
|
||||
l := len(formatTests)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
New(formatTests[n%l].result)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStringSimple(b *testing.B) {
|
||||
const VERSION = "0.0.1"
|
||||
v, _ := New(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, _ := New(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, _ := New(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, _ := New(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, _ := New(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, _ := New(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, _ := New(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))
|
||||
}
|
||||
}
|
24
Godeps/_workspace/src/github.com/blang/semver/sort.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/blang/semver/sort.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package semver
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Versions []Version
|
||||
|
||||
func (s Versions) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s Versions) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
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
Godeps/_workspace/src/github.com/blang/semver/sort_test.go
generated
vendored
Normal file
30
Godeps/_workspace/src/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, _ := New("1.0.0")
|
||||
v010, _ := New("0.1.0")
|
||||
v001, _ := New("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, _ := New("1.0.0")
|
||||
v010, _ := New("0.1.0")
|
||||
v001, _ := New("0.0.1")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
Sort([]Version{v010, v100, v001})
|
||||
}
|
||||
}
|
30
Godeps/_workspace/src/github.com/blang/semver/sql.go
generated
vendored
Normal file
30
Godeps/_workspace/src/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 (s Version) Value() (driver.Value, error) {
|
||||
return s.String(), nil
|
||||
}
|
38
Godeps/_workspace/src/github.com/blang/semver/sql_test.go
generated
vendored
Normal file
38
Godeps/_workspace/src/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{
|
||||
scanTest{"1.2.3", false, "1.2.3"},
|
||||
scanTest{[]byte("1.2.3"), false, "1.2.3"},
|
||||
scanTest{7, true, ""},
|
||||
scanTest{7e4, true, ""},
|
||||
scanTest{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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user