diff options
Diffstat (limited to 'vendor/github.com/blang/semver')
-rw-r--r-- | vendor/github.com/blang/semver/LICENSE | 22 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/README.md | 194 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/json.go | 23 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/package.json | 17 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/range.go | 416 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/semver.go | 418 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/sort.go | 28 | ||||
-rw-r--r-- | vendor/github.com/blang/semver/sql.go | 30 |
8 files changed, 1148 insertions, 0 deletions
diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE new file mode 100644 index 0000000..5ba5c86 --- /dev/null +++ b/vendor/github.com/blang/semver/LICENSE | |||
@@ -0,0 +1,22 @@ | |||
1 | The MIT License | ||
2 | |||
3 | Copyright (c) 2014 Benedikt Lang <github at benediktlang.de> | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in | ||
13 | all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
21 | THE SOFTWARE. | ||
22 | |||
diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md new file mode 100644 index 0000000..08b2e4a --- /dev/null +++ b/vendor/github.com/blang/semver/README.md | |||
@@ -0,0 +1,194 @@ | |||
1 | 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) | ||
2 | ====== | ||
3 | |||
4 | semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. | ||
5 | |||
6 | Usage | ||
7 | ----- | ||
8 | ```bash | ||
9 | $ go get github.com/blang/semver | ||
10 | ``` | ||
11 | Note: Always vendor your dependencies or fix on a specific version tag. | ||
12 | |||
13 | ```go | ||
14 | import github.com/blang/semver | ||
15 | v1, err := semver.Make("1.0.0-beta") | ||
16 | v2, err := semver.Make("2.0.0-beta") | ||
17 | v1.Compare(v2) | ||
18 | ``` | ||
19 | |||
20 | Also check the [GoDocs](http://godoc.org/github.com/blang/semver). | ||
21 | |||
22 | Why should I use this lib? | ||
23 | ----- | ||
24 | |||
25 | - Fully spec compatible | ||
26 | - No reflection | ||
27 | - No regex | ||
28 | - Fully tested (Coverage >99%) | ||
29 | - Readable parsing/validation errors | ||
30 | - Fast (See [Benchmarks](#benchmarks)) | ||
31 | - Only Stdlib | ||
32 | - Uses values instead of pointers | ||
33 | - Many features, see below | ||
34 | |||
35 | |||
36 | Features | ||
37 | ----- | ||
38 | |||
39 | - Parsing and validation at all levels | ||
40 | - Comparator-like comparisons | ||
41 | - Compare Helper Methods | ||
42 | - InPlace manipulation | ||
43 | - Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1` | ||
44 | - Wildcards `>=1.x`, `<=2.5.x` | ||
45 | - Sortable (implements sort.Interface) | ||
46 | - database/sql compatible (sql.Scanner/Valuer) | ||
47 | - encoding/json compatible (json.Marshaler/Unmarshaler) | ||
48 | |||
49 | Ranges | ||
50 | ------ | ||
51 | |||
52 | A `Range` is a set of conditions which specify which versions satisfy the range. | ||
53 | |||
54 | A condition is composed of an operator and a version. The supported operators are: | ||
55 | |||
56 | - `<1.0.0` Less than `1.0.0` | ||
57 | - `<=1.0.0` Less than or equal to `1.0.0` | ||
58 | - `>1.0.0` Greater than `1.0.0` | ||
59 | - `>=1.0.0` Greater than or equal to `1.0.0` | ||
60 | - `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0` | ||
61 | - `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`. | ||
62 | |||
63 | Note that spaces between the operator and the version will be gracefully tolerated. | ||
64 | |||
65 | A `Range` can link multiple `Ranges` separated by space: | ||
66 | |||
67 | Ranges can be linked by logical AND: | ||
68 | |||
69 | - `>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` | ||
70 | - `>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` | ||
71 | |||
72 | Ranges can also be linked by logical OR: | ||
73 | |||
74 | - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x` | ||
75 | |||
76 | AND has a higher precedence than OR. It's not possible to use brackets. | ||
77 | |||
78 | Ranges can be combined by both AND and OR | ||
79 | |||
80 | - `>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` | ||
81 | |||
82 | Range usage: | ||
83 | |||
84 | ``` | ||
85 | v, err := semver.Parse("1.2.3") | ||
86 | range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0") | ||
87 | if range(v) { | ||
88 | //valid | ||
89 | } | ||
90 | |||
91 | ``` | ||
92 | |||
93 | Example | ||
94 | ----- | ||
95 | |||
96 | Have a look at full examples in [examples/main.go](examples/main.go) | ||
97 | |||
98 | ```go | ||
99 | import github.com/blang/semver | ||
100 | |||
101 | v, err := semver.Make("0.0.1-alpha.preview+123.github") | ||
102 | fmt.Printf("Major: %d\n", v.Major) | ||
103 | fmt.Printf("Minor: %d\n", v.Minor) | ||
104 | fmt.Printf("Patch: %d\n", v.Patch) | ||
105 | fmt.Printf("Pre: %s\n", v.Pre) | ||
106 | fmt.Printf("Build: %s\n", v.Build) | ||
107 | |||
108 | // Prerelease versions array | ||
109 | if len(v.Pre) > 0 { | ||
110 | fmt.Println("Prerelease versions:") | ||
111 | for i, pre := range v.Pre { | ||
112 | fmt.Printf("%d: %q\n", i, pre) | ||
113 | } | ||
114 | } | ||
115 | |||
116 | // Build meta data array | ||
117 | if len(v.Build) > 0 { | ||
118 | fmt.Println("Build meta data:") | ||
119 | for i, build := range v.Build { | ||
120 | fmt.Printf("%d: %q\n", i, build) | ||
121 | } | ||
122 | } | ||
123 | |||
124 | v001, err := semver.Make("0.0.1") | ||
125 | // Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE | ||
126 | v001.GT(v) == true | ||
127 | v.LT(v001) == true | ||
128 | v.GTE(v) == true | ||
129 | v.LTE(v) == true | ||
130 | |||
131 | // Or use v.Compare(v2) for comparisons (-1, 0, 1): | ||
132 | v001.Compare(v) == 1 | ||
133 | v.Compare(v001) == -1 | ||
134 | v.Compare(v) == 0 | ||
135 | |||
136 | // Manipulate Version in place: | ||
137 | v.Pre[0], err = semver.NewPRVersion("beta") | ||
138 | if err != nil { | ||
139 | fmt.Printf("Error parsing pre release version: %q", err) | ||
140 | } | ||
141 | |||
142 | fmt.Println("\nValidate versions:") | ||
143 | v.Build[0] = "?" | ||
144 | |||
145 | err = v.Validate() | ||
146 | if err != nil { | ||
147 | fmt.Printf("Validation failed: %s\n", err) | ||
148 | } | ||
149 | ``` | ||
150 | |||
151 | |||
152 | Benchmarks | ||
153 | ----- | ||
154 | |||
155 | BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op | ||
156 | BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op | ||
157 | BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op | ||
158 | BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op | ||
159 | BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op | ||
160 | BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op | ||
161 | BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op | ||
162 | BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op | ||
163 | BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op | ||
164 | BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op | ||
165 | BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op | ||
166 | BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op | ||
167 | BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op | ||
168 | BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op | ||
169 | BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op | ||
170 | BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op | ||
171 | BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op | ||
172 | BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op | ||
173 | BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op | ||
174 | BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op | ||
175 | |||
176 | See benchmark cases at [semver_test.go](semver_test.go) | ||
177 | |||
178 | |||
179 | Motivation | ||
180 | ----- | ||
181 | |||
182 | 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. | ||
183 | |||
184 | |||
185 | Contribution | ||
186 | ----- | ||
187 | |||
188 | Feel free to make a pull request. For bigger changes create a issue first to discuss about it. | ||
189 | |||
190 | |||
191 | License | ||
192 | ----- | ||
193 | |||
194 | See [LICENSE](LICENSE) file. | ||
diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go new file mode 100644 index 0000000..a74bf7c --- /dev/null +++ b/vendor/github.com/blang/semver/json.go | |||
@@ -0,0 +1,23 @@ | |||
1 | package semver | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | ) | ||
6 | |||
7 | // MarshalJSON implements the encoding/json.Marshaler interface. | ||
8 | func (v Version) MarshalJSON() ([]byte, error) { | ||
9 | return json.Marshal(v.String()) | ||
10 | } | ||
11 | |||
12 | // UnmarshalJSON implements the encoding/json.Unmarshaler interface. | ||
13 | func (v *Version) UnmarshalJSON(data []byte) (err error) { | ||
14 | var versionString string | ||
15 | |||
16 | if err = json.Unmarshal(data, &versionString); err != nil { | ||
17 | return | ||
18 | } | ||
19 | |||
20 | *v, err = Parse(versionString) | ||
21 | |||
22 | return | ||
23 | } | ||
diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json new file mode 100644 index 0000000..1cf8ebd --- /dev/null +++ b/vendor/github.com/blang/semver/package.json | |||
@@ -0,0 +1,17 @@ | |||
1 | { | ||
2 | "author": "blang", | ||
3 | "bugs": { | ||
4 | "URL": "https://github.com/blang/semver/issues", | ||
5 | "url": "https://github.com/blang/semver/issues" | ||
6 | }, | ||
7 | "gx": { | ||
8 | "dvcsimport": "github.com/blang/semver" | ||
9 | }, | ||
10 | "gxVersion": "0.10.0", | ||
11 | "language": "go", | ||
12 | "license": "MIT", | ||
13 | "name": "semver", | ||
14 | "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", | ||
15 | "version": "3.5.1" | ||
16 | } | ||
17 | |||
diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go new file mode 100644 index 0000000..fca406d --- /dev/null +++ b/vendor/github.com/blang/semver/range.go | |||
@@ -0,0 +1,416 @@ | |||
1 | package semver | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strconv" | ||
6 | "strings" | ||
7 | "unicode" | ||
8 | ) | ||
9 | |||
10 | type wildcardType int | ||
11 | |||
12 | const ( | ||
13 | noneWildcard wildcardType = iota | ||
14 | majorWildcard wildcardType = 1 | ||
15 | minorWildcard wildcardType = 2 | ||
16 | patchWildcard wildcardType = 3 | ||
17 | ) | ||
18 | |||
19 | func wildcardTypefromInt(i int) wildcardType { | ||
20 | switch i { | ||
21 | case 1: | ||
22 | return majorWildcard | ||
23 | case 2: | ||
24 | return minorWildcard | ||
25 | case 3: | ||
26 | return patchWildcard | ||
27 | default: | ||
28 | return noneWildcard | ||
29 | } | ||
30 | } | ||
31 | |||
32 | type comparator func(Version, Version) bool | ||
33 | |||
34 | var ( | ||
35 | compEQ comparator = func(v1 Version, v2 Version) bool { | ||
36 | return v1.Compare(v2) == 0 | ||
37 | } | ||
38 | compNE = func(v1 Version, v2 Version) bool { | ||
39 | return v1.Compare(v2) != 0 | ||
40 | } | ||
41 | compGT = func(v1 Version, v2 Version) bool { | ||
42 | return v1.Compare(v2) == 1 | ||
43 | } | ||
44 | compGE = func(v1 Version, v2 Version) bool { | ||
45 | return v1.Compare(v2) >= 0 | ||
46 | } | ||
47 | compLT = func(v1 Version, v2 Version) bool { | ||
48 | return v1.Compare(v2) == -1 | ||
49 | } | ||
50 | compLE = func(v1 Version, v2 Version) bool { | ||
51 | return v1.Compare(v2) <= 0 | ||
52 | } | ||
53 | ) | ||
54 | |||
55 | type versionRange struct { | ||
56 | v Version | ||
57 | c comparator | ||
58 | } | ||
59 | |||
60 | // rangeFunc creates a Range from the given versionRange. | ||
61 | func (vr *versionRange) rangeFunc() Range { | ||
62 | return Range(func(v Version) bool { | ||
63 | return vr.c(v, vr.v) | ||
64 | }) | ||
65 | } | ||
66 | |||
67 | // Range represents a range of versions. | ||
68 | // A Range can be used to check if a Version satisfies it: | ||
69 | // | ||
70 | // range, err := semver.ParseRange(">1.0.0 <2.0.0") | ||
71 | // range(semver.MustParse("1.1.1") // returns true | ||
72 | type Range func(Version) bool | ||
73 | |||
74 | // OR combines the existing Range with another Range using logical OR. | ||
75 | func (rf Range) OR(f Range) Range { | ||
76 | return Range(func(v Version) bool { | ||
77 | return rf(v) || f(v) | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | // AND combines the existing Range with another Range using logical AND. | ||
82 | func (rf Range) AND(f Range) Range { | ||
83 | return Range(func(v Version) bool { | ||
84 | return rf(v) && f(v) | ||
85 | }) | ||
86 | } | ||
87 | |||
88 | // ParseRange parses a range and returns a Range. | ||
89 | // If the range could not be parsed an error is returned. | ||
90 | // | ||
91 | // Valid ranges are: | ||
92 | // - "<1.0.0" | ||
93 | // - "<=1.0.0" | ||
94 | // - ">1.0.0" | ||
95 | // - ">=1.0.0" | ||
96 | // - "1.0.0", "=1.0.0", "==1.0.0" | ||
97 | // - "!1.0.0", "!=1.0.0" | ||
98 | // | ||
99 | // A Range can consist of multiple ranges separated by space: | ||
100 | // Ranges can be linked by logical AND: | ||
101 | // - ">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" | ||
102 | // - ">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 | ||
103 | // | ||
104 | // Ranges can also be linked by logical OR: | ||
105 | // - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x" | ||
106 | // | ||
107 | // AND has a higher precedence than OR. It's not possible to use brackets. | ||
108 | // | ||
109 | // Ranges can be combined by both AND and OR | ||
110 | // | ||
111 | // - `>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` | ||
112 | func ParseRange(s string) (Range, error) { | ||
113 | parts := splitAndTrim(s) | ||
114 | orParts, err := splitORParts(parts) | ||
115 | if err != nil { | ||
116 | return nil, err | ||
117 | } | ||
118 | expandedParts, err := expandWildcardVersion(orParts) | ||
119 | if err != nil { | ||
120 | return nil, err | ||
121 | } | ||
122 | var orFn Range | ||
123 | for _, p := range expandedParts { | ||
124 | var andFn Range | ||
125 | for _, ap := range p { | ||
126 | opStr, vStr, err := splitComparatorVersion(ap) | ||
127 | if err != nil { | ||
128 | return nil, err | ||
129 | } | ||
130 | vr, err := buildVersionRange(opStr, vStr) | ||
131 | if err != nil { | ||
132 | return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err) | ||
133 | } | ||
134 | rf := vr.rangeFunc() | ||
135 | |||
136 | // Set function | ||
137 | if andFn == nil { | ||
138 | andFn = rf | ||
139 | } else { // Combine with existing function | ||
140 | andFn = andFn.AND(rf) | ||
141 | } | ||
142 | } | ||
143 | if orFn == nil { | ||
144 | orFn = andFn | ||
145 | } else { | ||
146 | orFn = orFn.OR(andFn) | ||
147 | } | ||
148 | |||
149 | } | ||
150 | return orFn, nil | ||
151 | } | ||
152 | |||
153 | // splitORParts splits the already cleaned parts by '||'. | ||
154 | // Checks for invalid positions of the operator and returns an | ||
155 | // error if found. | ||
156 | func splitORParts(parts []string) ([][]string, error) { | ||
157 | var ORparts [][]string | ||
158 | last := 0 | ||
159 | for i, p := range parts { | ||
160 | if p == "||" { | ||
161 | if i == 0 { | ||
162 | return nil, fmt.Errorf("First element in range is '||'") | ||
163 | } | ||
164 | ORparts = append(ORparts, parts[last:i]) | ||
165 | last = i + 1 | ||
166 | } | ||
167 | } | ||
168 | if last == len(parts) { | ||
169 | return nil, fmt.Errorf("Last element in range is '||'") | ||
170 | } | ||
171 | ORparts = append(ORparts, parts[last:]) | ||
172 | return ORparts, nil | ||
173 | } | ||
174 | |||
175 | // buildVersionRange takes a slice of 2: operator and version | ||
176 | // and builds a versionRange, otherwise an error. | ||
177 | func buildVersionRange(opStr, vStr string) (*versionRange, error) { | ||
178 | c := parseComparator(opStr) | ||
179 | if c == nil { | ||
180 | return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, "")) | ||
181 | } | ||
182 | v, err := Parse(vStr) | ||
183 | if err != nil { | ||
184 | return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err) | ||
185 | } | ||
186 | |||
187 | return &versionRange{ | ||
188 | v: v, | ||
189 | c: c, | ||
190 | }, nil | ||
191 | |||
192 | } | ||
193 | |||
194 | // inArray checks if a byte is contained in an array of bytes | ||
195 | func inArray(s byte, list []byte) bool { | ||
196 | for _, el := range list { | ||
197 | if el == s { | ||
198 | return true | ||
199 | } | ||
200 | } | ||
201 | return false | ||
202 | } | ||
203 | |||
204 | // splitAndTrim splits a range string by spaces and cleans whitespaces | ||
205 | func splitAndTrim(s string) (result []string) { | ||
206 | last := 0 | ||
207 | var lastChar byte | ||
208 | excludeFromSplit := []byte{'>', '<', '='} | ||
209 | for i := 0; i < len(s); i++ { | ||
210 | if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) { | ||
211 | if last < i-1 { | ||
212 | result = append(result, s[last:i]) | ||
213 | } | ||
214 | last = i + 1 | ||
215 | } else if s[i] != ' ' { | ||
216 | lastChar = s[i] | ||
217 | } | ||
218 | } | ||
219 | if last < len(s)-1 { | ||
220 | result = append(result, s[last:]) | ||
221 | } | ||
222 | |||
223 | for i, v := range result { | ||
224 | result[i] = strings.Replace(v, " ", "", -1) | ||
225 | } | ||
226 | |||
227 | // parts := strings.Split(s, " ") | ||
228 | // for _, x := range parts { | ||
229 | // if s := strings.TrimSpace(x); len(s) != 0 { | ||
230 | // result = append(result, s) | ||
231 | // } | ||
232 | // } | ||
233 | return | ||
234 | } | ||
235 | |||
236 | // splitComparatorVersion splits the comparator from the version. | ||
237 | // Input must be free of leading or trailing spaces. | ||
238 | func splitComparatorVersion(s string) (string, string, error) { | ||
239 | i := strings.IndexFunc(s, unicode.IsDigit) | ||
240 | if i == -1 { | ||
241 | return "", "", fmt.Errorf("Could not get version from string: %q", s) | ||
242 | } | ||
243 | return strings.TrimSpace(s[0:i]), s[i:], nil | ||
244 | } | ||
245 | |||
246 | // getWildcardType will return the type of wildcard that the | ||
247 | // passed version contains | ||
248 | func getWildcardType(vStr string) wildcardType { | ||
249 | parts := strings.Split(vStr, ".") | ||
250 | nparts := len(parts) | ||
251 | wildcard := parts[nparts-1] | ||
252 | |||
253 | possibleWildcardType := wildcardTypefromInt(nparts) | ||
254 | if wildcard == "x" { | ||
255 | return possibleWildcardType | ||
256 | } | ||
257 | |||
258 | return noneWildcard | ||
259 | } | ||
260 | |||
261 | // createVersionFromWildcard will convert a wildcard version | ||
262 | // into a regular version, replacing 'x's with '0's, handling | ||
263 | // special cases like '1.x.x' and '1.x' | ||
264 | func createVersionFromWildcard(vStr string) string { | ||
265 | // handle 1.x.x | ||
266 | vStr2 := strings.Replace(vStr, ".x.x", ".x", 1) | ||
267 | vStr2 = strings.Replace(vStr2, ".x", ".0", 1) | ||
268 | parts := strings.Split(vStr2, ".") | ||
269 | |||
270 | // handle 1.x | ||
271 | if len(parts) == 2 { | ||
272 | return vStr2 + ".0" | ||
273 | } | ||
274 | |||
275 | return vStr2 | ||
276 | } | ||
277 | |||
278 | // incrementMajorVersion will increment the major version | ||
279 | // of the passed version | ||
280 | func incrementMajorVersion(vStr string) (string, error) { | ||
281 | parts := strings.Split(vStr, ".") | ||
282 | i, err := strconv.Atoi(parts[0]) | ||
283 | if err != nil { | ||
284 | return "", err | ||
285 | } | ||
286 | parts[0] = strconv.Itoa(i + 1) | ||
287 | |||
288 | return strings.Join(parts, "."), nil | ||
289 | } | ||
290 | |||
291 | // incrementMajorVersion will increment the minor version | ||
292 | // of the passed version | ||
293 | func incrementMinorVersion(vStr string) (string, error) { | ||
294 | parts := strings.Split(vStr, ".") | ||
295 | i, err := strconv.Atoi(parts[1]) | ||
296 | if err != nil { | ||
297 | return "", err | ||
298 | } | ||
299 | parts[1] = strconv.Itoa(i + 1) | ||
300 | |||
301 | return strings.Join(parts, "."), nil | ||
302 | } | ||
303 | |||
304 | // expandWildcardVersion will expand wildcards inside versions | ||
305 | // following these rules: | ||
306 | // | ||
307 | // * when dealing with patch wildcards: | ||
308 | // >= 1.2.x will become >= 1.2.0 | ||
309 | // <= 1.2.x will become < 1.3.0 | ||
310 | // > 1.2.x will become >= 1.3.0 | ||
311 | // < 1.2.x will become < 1.2.0 | ||
312 | // != 1.2.x will become < 1.2.0 >= 1.3.0 | ||
313 | // | ||
314 | // * when dealing with minor wildcards: | ||
315 | // >= 1.x will become >= 1.0.0 | ||
316 | // <= 1.x will become < 2.0.0 | ||
317 | // > 1.x will become >= 2.0.0 | ||
318 | // < 1.0 will become < 1.0.0 | ||
319 | // != 1.x will become < 1.0.0 >= 2.0.0 | ||
320 | // | ||
321 | // * when dealing with wildcards without | ||
322 | // version operator: | ||
323 | // 1.2.x will become >= 1.2.0 < 1.3.0 | ||
324 | // 1.x will become >= 1.0.0 < 2.0.0 | ||
325 | func expandWildcardVersion(parts [][]string) ([][]string, error) { | ||
326 | var expandedParts [][]string | ||
327 | for _, p := range parts { | ||
328 | var newParts []string | ||
329 | for _, ap := range p { | ||
330 | if strings.Index(ap, "x") != -1 { | ||
331 | opStr, vStr, err := splitComparatorVersion(ap) | ||
332 | if err != nil { | ||
333 | return nil, err | ||
334 | } | ||
335 | |||
336 | versionWildcardType := getWildcardType(vStr) | ||
337 | flatVersion := createVersionFromWildcard(vStr) | ||
338 | |||
339 | var resultOperator string | ||
340 | var shouldIncrementVersion bool | ||
341 | switch opStr { | ||
342 | case ">": | ||
343 | resultOperator = ">=" | ||
344 | shouldIncrementVersion = true | ||
345 | case ">=": | ||
346 | resultOperator = ">=" | ||
347 | case "<": | ||
348 | resultOperator = "<" | ||
349 | case "<=": | ||
350 | resultOperator = "<" | ||
351 | shouldIncrementVersion = true | ||
352 | case "", "=", "==": | ||
353 | newParts = append(newParts, ">="+flatVersion) | ||
354 | resultOperator = "<" | ||
355 | shouldIncrementVersion = true | ||
356 | case "!=", "!": | ||
357 | newParts = append(newParts, "<"+flatVersion) | ||
358 | resultOperator = ">=" | ||
359 | shouldIncrementVersion = true | ||
360 | } | ||
361 | |||
362 | var resultVersion string | ||
363 | if shouldIncrementVersion { | ||
364 | switch versionWildcardType { | ||
365 | case patchWildcard: | ||
366 | resultVersion, _ = incrementMinorVersion(flatVersion) | ||
367 | case minorWildcard: | ||
368 | resultVersion, _ = incrementMajorVersion(flatVersion) | ||
369 | } | ||
370 | } else { | ||
371 | resultVersion = flatVersion | ||
372 | } | ||
373 | |||
374 | ap = resultOperator + resultVersion | ||
375 | } | ||
376 | newParts = append(newParts, ap) | ||
377 | } | ||
378 | expandedParts = append(expandedParts, newParts) | ||
379 | } | ||
380 | |||
381 | return expandedParts, nil | ||
382 | } | ||
383 | |||
384 | func parseComparator(s string) comparator { | ||
385 | switch s { | ||
386 | case "==": | ||
387 | fallthrough | ||
388 | case "": | ||
389 | fallthrough | ||
390 | case "=": | ||
391 | return compEQ | ||
392 | case ">": | ||
393 | return compGT | ||
394 | case ">=": | ||
395 | return compGE | ||
396 | case "<": | ||
397 | return compLT | ||
398 | case "<=": | ||
399 | return compLE | ||
400 | case "!": | ||
401 | fallthrough | ||
402 | case "!=": | ||
403 | return compNE | ||
404 | } | ||
405 | |||
406 | return nil | ||
407 | } | ||
408 | |||
409 | // MustParseRange is like ParseRange but panics if the range cannot be parsed. | ||
410 | func MustParseRange(s string) Range { | ||
411 | r, err := ParseRange(s) | ||
412 | if err != nil { | ||
413 | panic(`semver: ParseRange(` + s + `): ` + err.Error()) | ||
414 | } | ||
415 | return r | ||
416 | } | ||
diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go new file mode 100644 index 0000000..8ee0842 --- /dev/null +++ b/vendor/github.com/blang/semver/semver.go | |||
@@ -0,0 +1,418 @@ | |||
1 | package semver | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "fmt" | ||
6 | "strconv" | ||
7 | "strings" | ||
8 | ) | ||
9 | |||
10 | const ( | ||
11 | numbers string = "0123456789" | ||
12 | alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" | ||
13 | alphanum = alphas + numbers | ||
14 | ) | ||
15 | |||
16 | // SpecVersion is the latest fully supported spec version of semver | ||
17 | var SpecVersion = Version{ | ||
18 | Major: 2, | ||
19 | Minor: 0, | ||
20 | Patch: 0, | ||
21 | } | ||
22 | |||
23 | // Version represents a semver compatible version | ||
24 | type Version struct { | ||
25 | Major uint64 | ||
26 | Minor uint64 | ||
27 | Patch uint64 | ||
28 | Pre []PRVersion | ||
29 | Build []string //No Precendence | ||
30 | } | ||
31 | |||
32 | // Version to string | ||
33 | func (v Version) String() string { | ||
34 | b := make([]byte, 0, 5) | ||
35 | b = strconv.AppendUint(b, v.Major, 10) | ||
36 | b = append(b, '.') | ||
37 | b = strconv.AppendUint(b, v.Minor, 10) | ||
38 | b = append(b, '.') | ||
39 | b = strconv.AppendUint(b, v.Patch, 10) | ||
40 | |||
41 | if len(v.Pre) > 0 { | ||
42 | b = append(b, '-') | ||
43 | b = append(b, v.Pre[0].String()...) | ||
44 | |||
45 | for _, pre := range v.Pre[1:] { | ||
46 | b = append(b, '.') | ||
47 | b = append(b, pre.String()...) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | if len(v.Build) > 0 { | ||
52 | b = append(b, '+') | ||
53 | b = append(b, v.Build[0]...) | ||
54 | |||
55 | for _, build := range v.Build[1:] { | ||
56 | b = append(b, '.') | ||
57 | b = append(b, build...) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return string(b) | ||
62 | } | ||
63 | |||
64 | // Equals checks if v is equal to o. | ||
65 | func (v Version) Equals(o Version) bool { | ||
66 | return (v.Compare(o) == 0) | ||
67 | } | ||
68 | |||
69 | // EQ checks if v is equal to o. | ||
70 | func (v Version) EQ(o Version) bool { | ||
71 | return (v.Compare(o) == 0) | ||
72 | } | ||
73 | |||
74 | // NE checks if v is not equal to o. | ||
75 | func (v Version) NE(o Version) bool { | ||
76 | return (v.Compare(o) != 0) | ||
77 | } | ||
78 | |||
79 | // GT checks if v is greater than o. | ||
80 | func (v Version) GT(o Version) bool { | ||
81 | return (v.Compare(o) == 1) | ||
82 | } | ||
83 | |||
84 | // GTE checks if v is greater than or equal to o. | ||
85 | func (v Version) GTE(o Version) bool { | ||
86 | return (v.Compare(o) >= 0) | ||
87 | } | ||
88 | |||
89 | // GE checks if v is greater than or equal to o. | ||
90 | func (v Version) GE(o Version) bool { | ||
91 | return (v.Compare(o) >= 0) | ||
92 | } | ||
93 | |||
94 | // LT checks if v is less than o. | ||
95 | func (v Version) LT(o Version) bool { | ||
96 | return (v.Compare(o) == -1) | ||
97 | } | ||
98 | |||
99 | // LTE checks if v is less than or equal to o. | ||
100 | func (v Version) LTE(o Version) bool { | ||
101 | return (v.Compare(o) <= 0) | ||
102 | } | ||
103 | |||
104 | // LE checks if v is less than or equal to o. | ||
105 | func (v Version) LE(o Version) bool { | ||
106 | return (v.Compare(o) <= 0) | ||
107 | } | ||
108 | |||
109 | // Compare compares Versions v to o: | ||
110 | // -1 == v is less than o | ||
111 | // 0 == v is equal to o | ||
112 | // 1 == v is greater than o | ||
113 | func (v Version) Compare(o Version) int { | ||
114 | if v.Major != o.Major { | ||
115 | if v.Major > o.Major { | ||
116 | return 1 | ||
117 | } | ||
118 | return -1 | ||
119 | } | ||
120 | if v.Minor != o.Minor { | ||
121 | if v.Minor > o.Minor { | ||
122 | return 1 | ||
123 | } | ||
124 | return -1 | ||
125 | } | ||
126 | if v.Patch != o.Patch { | ||
127 | if v.Patch > o.Patch { | ||
128 | return 1 | ||
129 | } | ||
130 | return -1 | ||
131 | } | ||
132 | |||
133 | // Quick comparison if a version has no prerelease versions | ||
134 | if len(v.Pre) == 0 && len(o.Pre) == 0 { | ||
135 | return 0 | ||
136 | } else if len(v.Pre) == 0 && len(o.Pre) > 0 { | ||
137 | return 1 | ||
138 | } else if len(v.Pre) > 0 && len(o.Pre) == 0 { | ||
139 | return -1 | ||
140 | } | ||
141 | |||
142 | i := 0 | ||
143 | for ; i < len(v.Pre) && i < len(o.Pre); i++ { | ||
144 | if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 { | ||
145 | continue | ||
146 | } else if comp == 1 { | ||
147 | return 1 | ||
148 | } else { | ||
149 | return -1 | ||
150 | } | ||
151 | } | ||
152 | |||
153 | // If all pr versions are the equal but one has further prversion, this one greater | ||
154 | if i == len(v.Pre) && i == len(o.Pre) { | ||
155 | return 0 | ||
156 | } else if i == len(v.Pre) && i < len(o.Pre) { | ||
157 | return -1 | ||
158 | } else { | ||
159 | return 1 | ||
160 | } | ||
161 | |||
162 | } | ||
163 | |||
164 | // Validate validates v and returns error in case | ||
165 | func (v Version) Validate() error { | ||
166 | // Major, Minor, Patch already validated using uint64 | ||
167 | |||
168 | for _, pre := range v.Pre { | ||
169 | if !pre.IsNum { //Numeric prerelease versions already uint64 | ||
170 | if len(pre.VersionStr) == 0 { | ||
171 | return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr) | ||
172 | } | ||
173 | if !containsOnly(pre.VersionStr, alphanum) { | ||
174 | return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr) | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | |||
179 | for _, build := range v.Build { | ||
180 | if len(build) == 0 { | ||
181 | return fmt.Errorf("Build meta data can not be empty %q", build) | ||
182 | } | ||
183 | if !containsOnly(build, alphanum) { | ||
184 | return fmt.Errorf("Invalid character(s) found in build meta data %q", build) | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return nil | ||
189 | } | ||
190 | |||
191 | // New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error | ||
192 | func New(s string) (vp *Version, err error) { | ||
193 | v, err := Parse(s) | ||
194 | vp = &v | ||
195 | return | ||
196 | } | ||
197 | |||
198 | // Make is an alias for Parse, parses version string and returns a validated Version or error | ||
199 | func Make(s string) (Version, error) { | ||
200 | return Parse(s) | ||
201 | } | ||
202 | |||
203 | // ParseTolerant allows for certain version specifications that do not strictly adhere to semver | ||
204 | // specs to be parsed by this library. It does so by normalizing versions before passing them to | ||
205 | // Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions | ||
206 | // with only major and minor components specified | ||
207 | func ParseTolerant(s string) (Version, error) { | ||
208 | s = strings.TrimSpace(s) | ||
209 | s = strings.TrimPrefix(s, "v") | ||
210 | |||
211 | // Split into major.minor.(patch+pr+meta) | ||
212 | parts := strings.SplitN(s, ".", 3) | ||
213 | if len(parts) < 3 { | ||
214 | if strings.ContainsAny(parts[len(parts)-1], "+-") { | ||
215 | return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data") | ||
216 | } | ||
217 | for len(parts) < 3 { | ||
218 | parts = append(parts, "0") | ||
219 | } | ||
220 | s = strings.Join(parts, ".") | ||
221 | } | ||
222 | |||
223 | return Parse(s) | ||
224 | } | ||
225 | |||
226 | // Parse parses version string and returns a validated Version or error | ||
227 | func Parse(s string) (Version, error) { | ||
228 | if len(s) == 0 { | ||
229 | return Version{}, errors.New("Version string empty") | ||
230 | } | ||
231 | |||
232 | // Split into major.minor.(patch+pr+meta) | ||
233 | parts := strings.SplitN(s, ".", 3) | ||
234 | if len(parts) != 3 { | ||
235 | return Version{}, errors.New("No Major.Minor.Patch elements found") | ||
236 | } | ||
237 | |||
238 | // Major | ||
239 | if !containsOnly(parts[0], numbers) { | ||
240 | return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0]) | ||
241 | } | ||
242 | if hasLeadingZeroes(parts[0]) { | ||
243 | return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0]) | ||
244 | } | ||
245 | major, err := strconv.ParseUint(parts[0], 10, 64) | ||
246 | if err != nil { | ||
247 | return Version{}, err | ||
248 | } | ||
249 | |||
250 | // Minor | ||
251 | if !containsOnly(parts[1], numbers) { | ||
252 | return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1]) | ||
253 | } | ||
254 | if hasLeadingZeroes(parts[1]) { | ||
255 | return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1]) | ||
256 | } | ||
257 | minor, err := strconv.ParseUint(parts[1], 10, 64) | ||
258 | if err != nil { | ||
259 | return Version{}, err | ||
260 | } | ||
261 | |||
262 | v := Version{} | ||
263 | v.Major = major | ||
264 | v.Minor = minor | ||
265 | |||
266 | var build, prerelease []string | ||
267 | patchStr := parts[2] | ||
268 | |||
269 | if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 { | ||
270 | build = strings.Split(patchStr[buildIndex+1:], ".") | ||
271 | patchStr = patchStr[:buildIndex] | ||
272 | } | ||
273 | |||
274 | if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 { | ||
275 | prerelease = strings.Split(patchStr[preIndex+1:], ".") | ||
276 | patchStr = patchStr[:preIndex] | ||
277 | } | ||
278 | |||
279 | if !containsOnly(patchStr, numbers) { | ||
280 | return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr) | ||
281 | } | ||
282 | if hasLeadingZeroes(patchStr) { | ||
283 | return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr) | ||
284 | } | ||
285 | patch, err := strconv.ParseUint(patchStr, 10, 64) | ||
286 | if err != nil { | ||
287 | return Version{}, err | ||
288 | } | ||
289 | |||
290 | v.Patch = patch | ||
291 | |||
292 | // Prerelease | ||
293 | for _, prstr := range prerelease { | ||
294 | parsedPR, err := NewPRVersion(prstr) | ||
295 | if err != nil { | ||
296 | return Version{}, err | ||
297 | } | ||
298 | v.Pre = append(v.Pre, parsedPR) | ||
299 | } | ||
300 | |||
301 | // Build meta data | ||
302 | for _, str := range build { | ||
303 | if len(str) == 0 { | ||
304 | return Version{}, errors.New("Build meta data is empty") | ||
305 | } | ||
306 | if !containsOnly(str, alphanum) { | ||
307 | return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str) | ||
308 | } | ||
309 | v.Build = append(v.Build, str) | ||
310 | } | ||
311 | |||
312 | return v, nil | ||
313 | } | ||
314 | |||
315 | // MustParse is like Parse but panics if the version cannot be parsed. | ||
316 | func MustParse(s string) Version { | ||
317 | v, err := Parse(s) | ||
318 | if err != nil { | ||
319 | panic(`semver: Parse(` + s + `): ` + err.Error()) | ||
320 | } | ||
321 | return v | ||
322 | } | ||
323 | |||
324 | // PRVersion represents a PreRelease Version | ||
325 | type PRVersion struct { | ||
326 | VersionStr string | ||
327 | VersionNum uint64 | ||
328 | IsNum bool | ||
329 | } | ||
330 | |||
331 | // NewPRVersion creates a new valid prerelease version | ||
332 | func NewPRVersion(s string) (PRVersion, error) { | ||
333 | if len(s) == 0 { | ||
334 | return PRVersion{}, errors.New("Prerelease is empty") | ||
335 | } | ||
336 | v := PRVersion{} | ||
337 | if containsOnly(s, numbers) { | ||
338 | if hasLeadingZeroes(s) { | ||
339 | return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s) | ||
340 | } | ||
341 | num, err := strconv.ParseUint(s, 10, 64) | ||
342 | |||
343 | // Might never be hit, but just in case | ||
344 | if err != nil { | ||
345 | return PRVersion{}, err | ||
346 | } | ||
347 | v.VersionNum = num | ||
348 | v.IsNum = true | ||
349 | } else if containsOnly(s, alphanum) { | ||
350 | v.VersionStr = s | ||
351 | v.IsNum = false | ||
352 | } else { | ||
353 | return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s) | ||
354 | } | ||
355 | return v, nil | ||
356 | } | ||
357 | |||
358 | // IsNumeric checks if prerelease-version is numeric | ||
359 | func (v PRVersion) IsNumeric() bool { | ||
360 | return v.IsNum | ||
361 | } | ||
362 | |||
363 | // Compare compares two PreRelease Versions v and o: | ||
364 | // -1 == v is less than o | ||
365 | // 0 == v is equal to o | ||
366 | // 1 == v is greater than o | ||
367 | func (v PRVersion) Compare(o PRVersion) int { | ||
368 | if v.IsNum && !o.IsNum { | ||
369 | return -1 | ||
370 | } else if !v.IsNum && o.IsNum { | ||
371 | return 1 | ||
372 | } else if v.IsNum && o.IsNum { | ||
373 | if v.VersionNum == o.VersionNum { | ||
374 | return 0 | ||
375 | } else if v.VersionNum > o.VersionNum { | ||
376 | return 1 | ||
377 | } else { | ||
378 | return -1 | ||
379 | } | ||
380 | } else { // both are Alphas | ||
381 | if v.VersionStr == o.VersionStr { | ||
382 | return 0 | ||
383 | } else if v.VersionStr > o.VersionStr { | ||
384 | return 1 | ||
385 | } else { | ||
386 | return -1 | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
391 | // PreRelease version to string | ||
392 | func (v PRVersion) String() string { | ||
393 | if v.IsNum { | ||
394 | return strconv.FormatUint(v.VersionNum, 10) | ||
395 | } | ||
396 | return v.VersionStr | ||
397 | } | ||
398 | |||
399 | func containsOnly(s string, set string) bool { | ||
400 | return strings.IndexFunc(s, func(r rune) bool { | ||
401 | return !strings.ContainsRune(set, r) | ||
402 | }) == -1 | ||
403 | } | ||
404 | |||
405 | func hasLeadingZeroes(s string) bool { | ||
406 | return len(s) > 1 && s[0] == '0' | ||
407 | } | ||
408 | |||
409 | // NewBuildVersion creates a new valid build version | ||
410 | func NewBuildVersion(s string) (string, error) { | ||
411 | if len(s) == 0 { | ||
412 | return "", errors.New("Buildversion is empty") | ||
413 | } | ||
414 | if !containsOnly(s, alphanum) { | ||
415 | return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s) | ||
416 | } | ||
417 | return s, nil | ||
418 | } | ||
diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go new file mode 100644 index 0000000..e18f880 --- /dev/null +++ b/vendor/github.com/blang/semver/sort.go | |||
@@ -0,0 +1,28 @@ | |||
1 | package semver | ||
2 | |||
3 | import ( | ||
4 | "sort" | ||
5 | ) | ||
6 | |||
7 | // Versions represents multiple versions. | ||
8 | type Versions []Version | ||
9 | |||
10 | // Len returns length of version collection | ||
11 | func (s Versions) Len() int { | ||
12 | return len(s) | ||
13 | } | ||
14 | |||
15 | // Swap swaps two versions inside the collection by its indices | ||
16 | func (s Versions) Swap(i, j int) { | ||
17 | s[i], s[j] = s[j], s[i] | ||
18 | } | ||
19 | |||
20 | // Less checks if version at index i is less than version at index j | ||
21 | func (s Versions) Less(i, j int) bool { | ||
22 | return s[i].LT(s[j]) | ||
23 | } | ||
24 | |||
25 | // Sort sorts a slice of versions | ||
26 | func Sort(versions []Version) { | ||
27 | sort.Sort(Versions(versions)) | ||
28 | } | ||
diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go new file mode 100644 index 0000000..eb4d802 --- /dev/null +++ b/vendor/github.com/blang/semver/sql.go | |||
@@ -0,0 +1,30 @@ | |||
1 | package semver | ||
2 | |||
3 | import ( | ||
4 | "database/sql/driver" | ||
5 | "fmt" | ||
6 | ) | ||
7 | |||
8 | // Scan implements the database/sql.Scanner interface. | ||
9 | func (v *Version) Scan(src interface{}) (err error) { | ||
10 | var str string | ||
11 | switch src := src.(type) { | ||
12 | case string: | ||
13 | str = src | ||
14 | case []byte: | ||
15 | str = string(src) | ||
16 | default: | ||
17 | return fmt.Errorf("Version.Scan: cannot convert %T to string.", src) | ||
18 | } | ||
19 | |||
20 | if t, err := Parse(str); err == nil { | ||
21 | *v = t | ||
22 | } | ||
23 | |||
24 | return | ||
25 | } | ||
26 | |||
27 | // Value implements the database/sql/driver.Valuer interface. | ||
28 | func (v Version) Value() (driver.Value, error) { | ||
29 | return v.String(), nil | ||
30 | } | ||