-
Notifications
You must be signed in to change notification settings - Fork 3
/
semver.go
142 lines (111 loc) · 3.12 KB
/
semver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// The semver package provides utilities for managing
// and comparing semantic version values.
package semver
import (
"errors"
"reflect"
"strings"
)
// Type representing a semantic version value.
type Version struct {
Major string
Minor string
Patch string
Pre string
Build string
}
// Construct a new Version struct from a version string like "1.2.4".
// If the version string cannot be parsed then this function will return
// nil for the version and an error.
func New(versionString string) (*Version, error) {
pieces := strings.Split(versionString, ".")
if len(pieces) != 3 {
return nil, errors.New("semver: Malformed version (too short or too long).")
}
version := new(Version)
version.Major = pieces[0]
version.Minor = pieces[1]
last := pieces[2]
build := SplitLast(&last, "+")
pre := SplitLast(&last, "-")
version.Patch = last
version.Build = build
version.Pre = pre
return version, nil
}
// Parse a Version struct from a version string like "1.2.4".
// If the version string cannot be parsed then this function will
// panic.
func FromString(versionString string) (version *Version) {
version, err := New(versionString)
if err != nil {
panic("Malformed version (too short or too long).")
}
return
}
func SplitLast(last *string, delimiter string) (value string) {
if strings.Contains(*last, delimiter) {
pieces := strings.Split(*last, delimiter)
*last = pieces[0]
value = pieces[1]
}
return value
}
// Comparison methods
func (v *Version) LessThan(otherVersion *Version) bool {
return v.compareTo(otherVersion) == -1
}
func (v *Version) GreaterThan(otherVersion *Version) bool {
return v.compareTo(otherVersion) == 1
}
func (v *Version) Equal(otherVersion *Version) bool {
return v.compareTo(otherVersion) == 0
}
func (v *Version) NotEqual(otherVersion *Version) bool {
return v.compareTo(otherVersion) != 0
}
func (v *Version) GreaterThanOrEqual(otherVersion *Version) bool {
return v.compareTo(otherVersion) != -1
}
func (v *Version) LessThanOrEqual(otherVersion *Version) bool {
return v.compareTo(otherVersion) != 1
}
func (v *Version) PessimisticGreaterThan(otherVersion *Version) bool {
versionArrayA := v.Array()
versionArrayB := otherVersion.Array()
if reflect.DeepEqual(versionArrayA, versionArrayB) {
return true
}
if (otherVersion.Minor == "0") && (v.Major == otherVersion.Major) {
return true
}
if (v.Major == otherVersion.Major) && (v.Minor == otherVersion.Minor) && (v.Patch >= otherVersion.Patch) {
return true
}
return false
}
// Utility methods
func (v *Version) Array() []string {
return []string{v.Major, v.Minor, v.Patch, v.Pre}
}
func (v *Version) compareTo(otherVersion *Version) int {
return v.compareRecursive(v.Array(), otherVersion.Array())
}
func (v *Version) compareRecursive(versionA []string, versionB []string) int {
if reflect.DeepEqual(versionA, versionB) {
return 0
}
if (len(versionA) == 0) && (len(versionB) > 0) {
return -1
} else if (len(versionA) > 0) && (len(versionB) == 0) {
return 1
}
a := versionA[0]
b := versionB[0]
if a > b {
return 1
} else if a < b {
return -1
}
return v.compareRecursive(versionA[1:], versionB[1:])
}