Skip to content

Commit db91cad

Browse files
authored
Add Go version support (#13)
1 parent 1c4c8c9 commit db91cad

File tree

5 files changed

+198
-3
lines changed

5 files changed

+198
-3
lines changed

cmd/parseversion/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ func main() {
3838
switch typ {
3939
case "generic":
4040
parsed, err = version.ParseGeneric(ver)
41+
case "go":
42+
parsed, err = version.ParseGo(ver)
4143
case "semver":
4244
parsed, err = version.ParseSemVer(ver)
4345
case "perl":
@@ -89,6 +91,9 @@ The following version types are available:
8991
* semver - A version following the semver specification (https://semver.org/)
9092
* python - A Python PEP440 or legacy version
9193
* perl - A Perl module version
94+
* php - A PHP module version
95+
* ruby - A Ruby module version
96+
* go - A Golang module version
9297
* generic - Anything not covered by another type, such as C libraries, etc.
9398
`
9499

pkg/version/go.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package version
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
)
8+
9+
// 14 digits of YYYYMMDDhhmmss-12 hex digits for commit
10+
var golangCommitSuffixRegEx = regexp.MustCompile(`([-\.]\d{14})-[a-f0-9]{12}$`)
11+
12+
func ParseGo(version string) (*Version, error) {
13+
version, err := normalizeGo(version)
14+
if err != nil {
15+
return nil, err
16+
}
17+
18+
v, err := ParseGeneric(version)
19+
if err != nil {
20+
return nil, err
21+
}
22+
v.ParsedAs = Go
23+
return v, nil
24+
}
25+
26+
func normalizeGo(version string) (string, error) {
27+
trimmed := strings.TrimPrefix(version, "v")
28+
29+
if trimmed == version {
30+
return "", fmt.Errorf("Invalid Go version: %v", version)
31+
}
32+
33+
trimmedSuffix := golangCommitSuffixRegEx.ReplaceAllString(trimmed, "${1}")
34+
35+
return trimmedSuffix, nil
36+
}

pkg/version/go_test.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package version
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
var equalGoVersions = [][]string{
11+
{
12+
"v0.0.0", "v000", "v0",
13+
},
14+
{
15+
"v1", "v000001", "v1.0", "v1.0.0", "v1.0 ",
16+
},
17+
{
18+
"v1.2.b1", "v1.2.b.1",
19+
},
20+
{
21+
"v1.2", "v1.2.0",
22+
},
23+
{
24+
"v5", "v5.0.0",
25+
},
26+
}
27+
28+
func TestParseGoEqual(t *testing.T) {
29+
for _, versions := range equalGoVersions {
30+
for i := 0; i < len(versions)-1; i++ {
31+
v1 := parseGoOrFatal(t, versions[i])
32+
v2 := parseGoOrFatal(t, versions[i+1])
33+
assert.True(
34+
t,
35+
Compare(v1, v2) == 0,
36+
"%v and %v should be equal, but '%v' != '%v'", versions[i], versions[i+1], v1, v2,
37+
)
38+
}
39+
}
40+
}
41+
42+
var invalidGoVersions = []string{
43+
"whatever",
44+
"junk",
45+
"1.0\n2.0",
46+
"1..2",
47+
"1.ウ",
48+
"1.2 3.4",
49+
"2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e.",
50+
}
51+
52+
func TestParseGoInvalid(t *testing.T) {
53+
for _, invalidString := range invalidGoVersions {
54+
v, err := ParseGo(invalidString)
55+
assert.Nil(t, v)
56+
assert.Error(t, err, "%v should fail to parse", invalidString)
57+
}
58+
}
59+
60+
var goTestStrings = []string{
61+
"v0.beta.1",
62+
"v0",
63+
"v1",
64+
"v1.1",
65+
"v1.2",
66+
"v1.2.3",
67+
"v1.3",
68+
"v1.8.2",
69+
"v1.9.3",
70+
"v2.9",
71+
"v5",
72+
"v5.1",
73+
"v5.3",
74+
"v6",
75+
"v9.8.7",
76+
"v9.8.8",
77+
"v22.1.50.0",
78+
}
79+
80+
func TestParseGoOrdering(t *testing.T) {
81+
for i := 0; i < len(goTestStrings)-1; i++ {
82+
v1 := parseGoOrFatal(t, goTestStrings[i])
83+
v2 := parseGoOrFatal(t, goTestStrings[i+1])
84+
assert.True(
85+
t,
86+
Compare(v1, v2) < 0,
87+
"%v should be less than %v", goTestStrings[i], goTestStrings[i+1],
88+
)
89+
}
90+
}
91+
92+
func TestParseGo(t *testing.T) {
93+
tests := []struct {
94+
name string
95+
version string
96+
expected []string
97+
}{
98+
{"Numbers", "v0", []string{"0"}},
99+
{"Numbers", "v1", []string{"1"}},
100+
{"Numbers", "v1.0", []string{"1"}},
101+
{"Numbers", "v0.92", []string{"0", "92"}},
102+
{"Numbers", "v1-1.2", []string{"1", "1", "2"}},
103+
{"Sequential Dots", "v1..2", []string{"1", "2"}},
104+
{"Sequential Dashes", "v1--2", []string{"1", "2"}},
105+
{"Sequential Dot Dash", "v1.-2", []string{"1", "2"}},
106+
{"Uppercase A", "vA1", []string{"65", "1"}},
107+
{"Lowercase a", "va1", []string{"97", "1"}},
108+
{"Single Unicode", "v小1", []string{"23567", "1"}},
109+
{"Ascii Word", "v1.0bet", []string{"1", "0", "98.00000001010000000116"}},
110+
{"Unicode Word", "v小寸-1.1", []string{"23567.0000023544", "1", "1"}},
111+
{"Unicode Separators", "v1 2\u20013\u2002\u20034", []string{"1", "2", "3", "4"}},
112+
{"Normalizes Unicode", "ve\u0301", []string{"233"}},
113+
{
114+
"Splits On Space",
115+
"v10 Generic 142910-17",
116+
[]string{
117+
"10",
118+
"71.000000010100000001100000000101000000011400000001050000000099",
119+
"142910",
120+
"17",
121+
},
122+
},
123+
{"Drops Leading Zeros", "v100.02.01", []string{"100", "2", "1"}},
124+
{"Pre-Release Identifier", "v1.0-alpha", []string{"1", "0", "-26"}},
125+
{"Pre-Release Identifier Ignores Case", "v1.0-AlPHa", []string{"1", "0", "-26"}},
126+
{"Pre-Release Identifier In Middle", "v1.0-alpha.1", []string{"1", "0", "-26", "1"}},
127+
{"2 Pre-Release Identifiers", "v1.0-alpha.beta", []string{"1", "0", "-26", "-25"}},
128+
{"Pre-Release Identifier Beta", "v1.0-beta", []string{"1", "0", "-25"}},
129+
{"Pre-Release Identifier RC", "v1.0-rc", []string{"1", "0", "-1"}},
130+
{"Timestamp-commits", "v1.2.3-20191109021931-daa7c04131f5", []string{"1", "2", "3", "20191109021931"}},
131+
{"Timestamp-dot-commits", "v1.23.456.789.20191109021931-caa7c04131f6", []string{"1", "23", "456", "789", "20191109021931"}},
132+
{"Timestamp-svn-commits", "v1.23.456.789-20191109021931-000000001234", []string{"1", "23", "456", "789", "20191109021931"}},
133+
{"Timestamp-svn-dot-commits", "v9.87.654.321.20191109021931-000000001234", []string{"9", "87", "654", "321", "20191109021931"}},
134+
}
135+
136+
for _, tt := range tests {
137+
t.Run(tt.name, func(t *testing.T) {
138+
actual := parseGoOrFatal(t, tt.version)
139+
assert.Equal(t, Go, actual.ParsedAs, "got expected ParsedAs value")
140+
assertDecimalEqualString(t, tt.expected, actual.Decimal)
141+
assertDecimalEqualDecimal(t, tt.expected, actual.Decimal)
142+
})
143+
}
144+
}
145+
146+
147+
func parseGoOrFatal(t *testing.T, v string) *Version {
148+
ver, err := ParseGo(v)
149+
require.NoError(t, err, "no error parsing %v as a go version", v)
150+
return ver
151+
}

pkg/version/parsedas_enumer.go

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/version/version.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ const (
6363
PythonPEP440
6464
// Ruby is for Ruby versions.
6565
Ruby
66+
// Go is for Go versions.
67+
Go
6668
)
6769

6870
// Version is the struct returned from all parsing funcs.

0 commit comments

Comments
 (0)