vendored go-semver
Juan Batiz-Benet committed
Oct 9, 2014 at 20:01 UTC
afec2d3d2391e99e9688261d8492ff3836cc9b53
5 files changed
+418
-1
Godeps/Godeps.json
+4
@@ -46,6 +46,10 @@
46
"ImportPath": "github.com/camlistore/lock",
47
"Rev": "ae27720f340952636b826119b58130b9c1a847a0"
48
},
49
+ {
50
+ "ImportPath": "github.com/coreos/go-semver/semver",
51
+ "Rev": "6fe83ccda8fb9b7549c9ab4ba47f47858bc950aa"
52
+ },
53
{
54
"ImportPath": "github.com/gonuts/flag",
55
"Rev": "741a6cbd37a30dedc93f817e7de6aaf0ca38a493"
Godeps/_workspace/src/github.com/coreos/go-semver/semver/semver.go
new
+202
@@ -0,0 +1,202 @@
1
+package semver
2
+
3
+import (
4
+ "bytes"
5
+ "errors"
6
+ "fmt"
7
+ "strconv"
8
+ "strings"
9
+)
10
+
11
+type Version struct {
12
+ Major int64
13
+ Minor int64
14
+ Patch int64
15
+ PreRelease PreRelease
16
+ Metadata string
17
+}
18
+
19
+type PreRelease string
20
+
21
+func splitOff(input *string, delim string) (val string) {
22
+ parts := strings.SplitN(*input, delim, 2)
23
+
24
+ if len(parts) == 2 {
25
+ *input = parts[0]
26
+ val = parts[1]
27
+ }
28
+
29
+ return val
30
+}
31
+
32
+func NewVersion(version string) (*Version, error) {
33
+ v := Version{}
34
+
35
+ dotParts := strings.SplitN(version, ".", 3)
36
+
37
+ if len(dotParts) != 3 {
38
+ return nil, errors.New(fmt.Sprintf("%s is not in dotted-tri format", version))
39
+ }
40
+
41
+ v.Metadata = splitOff(&dotParts[2], "+")
42
+ v.PreRelease = PreRelease(splitOff(&dotParts[2], "-"))
43
+
44
+ parsed := make([]int64, 3, 3)
45
+
46
+ for i, v := range dotParts[:3] {
47
+ val, err := strconv.ParseInt(v, 10, 64)
48
+ parsed[i] = val
49
+ if err != nil {
50
+ return nil, err
51
+ }
52
+ }
53
+
54
+ v.Major = parsed[0]
55
+ v.Minor = parsed[1]
56
+ v.Patch = parsed[2]
57
+
58
+ return &v, nil
59
+}
60
+
61
+func (v *Version) String() string {
62
+ var buffer bytes.Buffer
63
+
64
+ base := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
65
+ buffer.WriteString(base)
66
+
67
+ if v.PreRelease != "" {
68
+ buffer.WriteString(fmt.Sprintf("-%s", v.PreRelease))
69
+ }
70
+
71
+ if v.Metadata != "" {
72
+ buffer.WriteString(fmt.Sprintf("+%s", v.Metadata))
73
+ }
74
+
75
+ return buffer.String()
76
+}
77
+
78
+func (v *Version) LessThan(versionB Version) bool {
79
+ versionA := *v
80
+ cmp := recursiveCompare(versionA.Slice(), versionB.Slice())
81
+
82
+ if cmp == 0 {
83
+ cmp = preReleaseCompare(versionA, versionB)
84
+ }
85
+
86
+ if cmp == -1 {
87
+ return true
88
+ }
89
+
90
+ return false
91
+}
92
+
93
+/* Slice converts the comparable parts of the semver into a slice of strings */
94
+func (v *Version) Slice() []int64 {
95
+ return []int64{v.Major, v.Minor, v.Patch}
96
+}
97
+
98
+func (p *PreRelease) Slice() []string {
99
+ preRelease := string(*p)
100
+ return strings.Split(preRelease, ".")
101
+}
102
+
103
+func preReleaseCompare(versionA Version, versionB Version) int {
104
+ a := versionA.PreRelease
105
+ b := versionB.PreRelease
106
+
107
+ /* Handle the case where if two versions are otherwise equal it is the
108
+ * one without a PreRelease that is greater */
109
+ if len(a) == 0 && (len(b) > 0) {
110
+ return 1
111
+ } else if len(b) == 0 && (len(a) > 0) {
112
+ return -1
113
+ }
114
+
115
+ // If there is a prelease, check and compare each part.
116
+ return recursivePreReleaseCompare(a.Slice(), b.Slice())
117
+}
118
+
119
+func recursiveCompare(versionA []int64, versionB []int64) int {
120
+ if len(versionA) == 0 {
121
+ return 0
122
+ }
123
+
124
+ a := versionA[0]
125
+ b := versionB[0]
126
+
127
+ if a > b {
128
+ return 1
129
+ } else if a < b {
130
+ return -1
131
+ }
132
+
133
+ return recursiveCompare(versionA[1:], versionB[1:])
134
+}
135
+
136
+func recursivePreReleaseCompare(versionA []string, versionB []string) int {
137
+ // Handle slice length disparity.
138
+ if len(versionA) == 0 {
139
+ // Nothing to compare too, so we return 0
140
+ return 0
141
+ } else if len(versionB) == 0 {
142
+ // We're longer than versionB so return 1.
143
+ return 1
144
+ }
145
+
146
+ a := versionA[0]
147
+ b := versionB[0]
148
+
149
+ aInt := false; bInt := false
150
+
151
+ aI, err := strconv.Atoi(versionA[0])
152
+ if err == nil {
153
+ aInt = true
154
+ }
155
+
156
+ bI, err := strconv.Atoi(versionB[0])
157
+ if err == nil {
158
+ bInt = true
159
+ }
160
+
161
+ // Handle Integer Comparison
162
+ if aInt && bInt {
163
+ if aI > bI {
164
+ return 1
165
+ } else if aI < bI {
166
+ return -1
167
+ }
168
+ }
169
+
170
+ // Handle String Comparison
171
+ if a > b {
172
+ return 1
173
+ } else if a < b {
174
+ return -1
175
+ }
176
+
177
+ return recursivePreReleaseCompare(versionA[1:], versionB[1:])
178
+}
179
+
180
+// BumpMajor increments the Major field by 1 and resets all other fields to their default values
181
+func (v *Version) BumpMajor() {
182
+ v.Major += 1
183
+ v.Minor = 0
184
+ v.Patch = 0
185
+ v.PreRelease = PreRelease("")
186
+ v.Metadata = ""
187
+}
188
+
189
+// BumpMinor increments the Minor field by 1 and resets all other fields to their default values
190
+func (v *Version) BumpMinor() {
191
+ v.Minor += 1
192
+ v.Patch = 0
193
+ v.PreRelease = PreRelease("")
194
+ v.Metadata = ""
195
+}
196
+
197
+// BumpPatch increments the Patch field by 1 and resets all other fields to their default values
198
+func (v *Version) BumpPatch() {
199
+ v.Patch += 1
200
+ v.PreRelease = PreRelease("")
201
+ v.Metadata = ""
202
+}
Godeps/_workspace/src/github.com/coreos/go-semver/semver/semver_test.go
new
+187
@@ -0,0 +1,187 @@
1
+package semver
2
+
3
+import (
4
+ "math/rand"
5
+ "testing"
6
+ "time"
7
+)
8
+
9
+type fixture struct {
10
+ greaterVersion string
11
+ lesserVersion string
12
+}
13
+
14
+var fixtures = []fixture{
15
+ fixture{"0.0.0", "0.0.0-foo"},
16
+ fixture{"0.0.1", "0.0.0"},
17
+ fixture{"1.0.0", "0.9.9"},
18
+ fixture{"0.10.0", "0.9.0"},
19
+ fixture{"0.99.0", "0.10.0"},
20
+ fixture{"2.0.0", "1.2.3"},
21
+ fixture{"0.0.0", "0.0.0-foo"},
22
+ fixture{"0.0.1", "0.0.0"},
23
+ fixture{"1.0.0", "0.9.9"},
24
+ fixture{"0.10.0", "0.9.0"},
25
+ fixture{"0.99.0", "0.10.0"},
26
+ fixture{"2.0.0", "1.2.3"},
27
+ fixture{"0.0.0", "0.0.0-foo"},
28
+ fixture{"0.0.1", "0.0.0"},
29
+ fixture{"1.0.0", "0.9.9"},
30
+ fixture{"0.10.0", "0.9.0"},
31
+ fixture{"0.99.0", "0.10.0"},
32
+ fixture{"2.0.0", "1.2.3"},
33
+ fixture{"1.2.3", "1.2.3-asdf"},
34
+ fixture{"1.2.3", "1.2.3-4"},
35
+ fixture{"1.2.3", "1.2.3-4-foo"},
36
+ fixture{"1.2.3-5-foo", "1.2.3-5"},
37
+ fixture{"1.2.3-5", "1.2.3-4"},
38
+ fixture{"1.2.3-5-foo", "1.2.3-5-Foo"},
39
+ fixture{"3.0.0", "2.7.2+asdf"},
40
+ fixture{"3.0.0+foobar", "2.7.2"},
41
+ fixture{"1.2.3-a.10", "1.2.3-a.5"},
42
+ fixture{"1.2.3-a.b", "1.2.3-a.5"},
43
+ fixture{"1.2.3-a.b", "1.2.3-a"},
44
+ fixture{"1.2.3-a.b.c.10.d.5", "1.2.3-a.b.c.5.d.100"},
45
+ fixture{"1.0.0", "1.0.0-rc.1"},
46
+ fixture{"1.0.0-rc.2", "1.0.0-rc.1"},
47
+ fixture{"1.0.0-rc.1", "1.0.0-beta.11"},
48
+ fixture{"1.0.0-beta.11", "1.0.0-beta.2"},
49
+ fixture{"1.0.0-beta.2", "1.0.0-beta"},
50
+ fixture{"1.0.0-beta", "1.0.0-alpha.beta"},
51
+ fixture{"1.0.0-alpha.beta", "1.0.0-alpha.1"},
52
+ fixture{"1.0.0-alpha.1", "1.0.0-alpha"},
53
+}
54
+
55
+func TestCompare(t *testing.T) {
56
+ for _, v := range fixtures {
57
+ gt, err := NewVersion(v.greaterVersion)
58
+ if err != nil {
59
+ t.Error(err)
60
+ }
61
+
62
+ lt, err := NewVersion(v.lesserVersion)
63
+ if err != nil {
64
+ t.Error(err)
65
+ }
66
+
67
+ if gt.LessThan(*lt) == true {
68
+ t.Errorf("%s should not be less than %s", gt, lt)
69
+ }
70
+ }
71
+}
72
+
73
+func testString(t *testing.T, orig string, version *Version) {
74
+ if orig != version.String() {
75
+ t.Errorf("%s != %s", orig, version)
76
+ }
77
+}
78
+
79
+func TestString(t *testing.T) {
80
+ for _, v := range fixtures {
81
+ gt, err := NewVersion(v.greaterVersion)
82
+ if err != nil {
83
+ t.Error(err)
84
+ }
85
+ testString(t, v.greaterVersion, gt)
86
+
87
+ lt, err := NewVersion(v.lesserVersion)
88
+ if err != nil {
89
+ t.Error(err)
90
+ }
91
+ testString(t, v.lesserVersion, lt)
92
+ }
93
+}
94
+
95
+func shuffleStringSlice(src []string) []string {
96
+ dest := make([]string, len(src))
97
+ rand.Seed(time.Now().Unix())
98
+ perm := rand.Perm(len(src))
99
+ for i, v := range perm {
100
+ dest[v] = src[i]
101
+ }
102
+ return dest
103
+}
104
+
105
+func TestSort(t *testing.T) {
106
+ sortedVersions := []string{"1.0.0", "1.0.2", "1.2.0", "3.1.1"}
107
+ unsortedVersions := shuffleStringSlice(sortedVersions)
108
+
109
+ semvers := []*Version{}
110
+ for _, v := range unsortedVersions {
111
+ sv, err := NewVersion(v)
112
+ if err != nil {
113
+ t.Fatal(err)
114
+ }
115
+ semvers = append(semvers, sv)
116
+ }
117
+
118
+ Sort(semvers)
119
+
120
+ for idx, sv := range semvers {
121
+ if sv.String() != sortedVersions[idx] {
122
+ t.Fatalf("incorrect sort at index %v", idx)
123
+ }
124
+ }
125
+}
126
+
127
+func TestBumpMajor(t *testing.T) {
128
+ version, _ := NewVersion("1.0.0")
129
+ version.BumpMajor()
130
+ if version.Major != 2 {
131
+ t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
132
+ }
133
+
134
+ version, _ = NewVersion("1.5.2")
135
+ version.BumpMajor()
136
+ if version.Minor != 0 && version.Patch != 0 {
137
+ t.Fatalf("bumping major on 1.5.2 resulted in %v", version)
138
+ }
139
+
140
+ version, _ = NewVersion("1.0.0+build.1-alpha.1")
141
+ version.BumpMajor()
142
+ if version.PreRelease != "" && version.PreRelease != "" {
143
+ t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
144
+ }
145
+}
146
+
147
+func TestBumpMinor(t *testing.T) {
148
+ version, _ := NewVersion("1.0.0")
149
+ version.BumpMinor()
150
+
151
+ if version.Major != 1 {
152
+ t.Fatalf("bumping minor on 1.0.0 resulted in %v", version)
153
+ }
154
+
155
+ if version.Minor != 1 {
156
+ t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
157
+ }
158
+
159
+ version, _ = NewVersion("1.0.0+build.1-alpha.1")
160
+ version.BumpMinor()
161
+ if version.PreRelease != "" && version.PreRelease != "" {
162
+ t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
163
+ }
164
+}
165
+
166
+func TestBumpPatch(t *testing.T) {
167
+ version, _ := NewVersion("1.0.0")
168
+ version.BumpPatch()
169
+
170
+ if version.Major != 1 {
171
+ t.Fatalf("bumping minor on 1.0.0 resulted in %v", version)
172
+ }
173
+
174
+ if version.Minor != 0 {
175
+ t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
176
+ }
177
+
178
+ if version.Patch != 1 {
179
+ t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
180
+ }
181
+
182
+ version, _ = NewVersion("1.0.0+build.1-alpha.1")
183
+ version.BumpPatch()
184
+ if version.PreRelease != "" && version.PreRelease != "" {
185
+ t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
186
+ }
187
+}
Godeps/_workspace/src/github.com/coreos/go-semver/semver/sort.go
new
+24
@@ -0,0 +1,24 @@
1
+package semver
2
+
3
+import (
4
+ "sort"
5
+)
6
+
7
+type Versions []*Version
8
+
9
+func (s Versions) Len() int {
10
+ return len(s)
11
+}
12
+
13
+func (s Versions) Swap(i, j int) {
14
+ s[i], s[j] = s[j], s[i]
15
+}
16
+
17
+func (s Versions) Less(i, j int) bool {
18
+ return s[i].LessThan(*s[j])
19
+}
20
+
21
+// Sort sorts the given slice of Version
22
+func Sort(versions []*Version) {
23
+ sort.Sort(Versions(versions))
24
+}
updates/updates.go
+1
-1
@@ -6,7 +6,7 @@ import (
6
"net/http"
7
"os"
8
9
- "github.com/coreos/go-semver/semver"
9
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/coreos/go-semver/semver"
10
u "github.com/jbenet/go-ipfs/util"
11
)
12