forked from buildpacks/pack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
version.go
125 lines (98 loc) · 2.46 KB
/
version.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
package api
import (
"fmt"
"regexp"
"strconv"
"github.com/pkg/errors"
"github.com/buildpacks/pack/internal/style"
)
var regex = regexp.MustCompile(`^v?(\d+)\.(\d*)$`)
type Version struct {
major,
minor uint64
}
func MustParse(v string) *Version {
version, err := NewVersion(v)
if err != nil {
panic(err)
}
return version
}
func NewVersion(v string) (*Version, error) {
matches := regex.FindAllStringSubmatch(v, -1)
if len(matches) == 0 {
return nil, errors.Errorf("could not parse %s as version", style.Symbol(v))
}
var (
major, minor uint64
err error
)
if len(matches[0]) == 3 {
major, err = strconv.ParseUint(matches[0][1], 10, 64)
if err != nil {
return nil, errors.Wrapf(err, "parsing major %s", style.Symbol(matches[0][1]))
}
minor, err = strconv.ParseUint(matches[0][2], 10, 64)
if err != nil {
return nil, errors.Wrapf(err, "parsing minor %s", style.Symbol(matches[0][2]))
}
} else {
return nil, errors.Errorf("could not parse version %s", style.Symbol(v))
}
return &Version{major: major, minor: minor}, nil
}
func (v *Version) String() string {
return fmt.Sprintf("%d.%d", v.major, v.minor)
}
// MarshalText makes Version satisfy the encoding.TextMarshaler interface.
func (v *Version) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}
// UnmarshalText makes Version satisfy the encoding.TextUnmarshaler interface.
func (v *Version) UnmarshalText(text []byte) error {
s := string(text)
parsedVersion, err := NewVersion(s)
if err != nil {
return errors.Wrapf(err, "invalid api version %s", s)
}
v.major = parsedVersion.major
v.minor = parsedVersion.minor
return nil
}
// SupportsVersion determines whether this version supports a given version. If comparing two pre-stable (major == 0)
// versions, minors must match exactly. Otherwise, this minor must be greater than or equal to the given minor. Majors
// must always match.
func (v *Version) SupportsVersion(o *Version) bool {
if v.Equal(o) {
return true
}
if v.major != 0 {
return v.major == o.major && v.minor >= o.minor
}
return false
}
func (v *Version) Equal(o *Version) bool {
if o != nil {
return v.Compare(o) == 0
}
return o == nil && v == nil
}
func (v *Version) Compare(o *Version) int {
if v.major != o.major {
if v.major < o.major {
return -1
}
if v.major > o.major {
return 1
}
}
if v.minor != o.minor {
if v.minor < o.minor {
return -1
}
if v.minor > o.minor {
return 1
}
}
return 0
}