Skip to content

Commit 6a7a28d

Browse files
committed
goenv, builder: parse patch version in Go version string
1 parent 1e44312 commit 6a7a28d

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

builder/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
4343
// compiled with the latest Go version.
4444
// This may be a bit too aggressive: if the newer version doesn't change the
4545
// Go language we will most likely be able to compile it.
46-
buildMajor, buildMinor, err := goenv.Parse(runtime.Version())
46+
buildMajor, buildMinor, _, err := goenv.Parse(runtime.Version())
4747
if err != nil {
4848
return nil, err
4949
}

goenv/version.go

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,44 @@ func GetGorootVersion() (major, minor int, err error) {
3434
if err != nil {
3535
return 0, 0, err
3636
}
37-
return Parse(s)
37+
major, minor, _, err = Parse(s)
38+
return major, minor, err
3839
}
3940

4041
// Parse parses the Go version (like "go1.3.2") in the parameter and return the
41-
// major and minor version: 1 and 3 in this example. If there is an error, (0,
42-
// 0) and an error will be returned.
43-
func Parse(version string) (major, minor int, err error) {
42+
// major, minor, and patch version: 1, 3, and 2 in this example.
43+
// If there is an error, (0, 0, 0) and an error will be returned.
44+
func Parse(version string) (major, minor, patch int, err error) {
4445
if version == "" || version[:2] != "go" {
45-
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
46+
return 0, 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
4647
}
4748

4849
parts := strings.Split(version[2:], ".")
4950
if len(parts) < 2 {
50-
return 0, 0, errors.New("could not parse Go version: version has less than two parts")
51+
return 0, 0, 0, errors.New("could not parse Go version: version has less than two parts")
5152
}
5253

5354
// Ignore the errors, we don't really handle errors here anyway.
5455
var trailing string
55-
n, err := fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing)
56-
if n == 2 && err == io.EOF {
56+
n, err := fmt.Sscanf(version, "go%d.%d.%d%s", &major, &minor, &patch, &trailing)
57+
if n == 2 {
58+
n, err = fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing)
59+
}
60+
if n >= 2 && err == io.EOF {
5761
// Means there were no trailing characters (i.e., not an alpha/beta)
5862
err = nil
5963
}
6064
if err != nil {
61-
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
65+
return 0, 0, 0, fmt.Errorf("failed to parse version: %s", err)
6266
}
6367

64-
return major, minor, nil
68+
return major, minor, patch, nil
6569
}
6670

6771
// WantGoVersion returns true if Go version s is >= major and minor.
6872
// Returns false if s is not a valid Go version string. See [Parse] for more information.
6973
func WantGoVersion(s string, major, minor int) bool {
70-
ma, mi, err := Parse(s)
74+
ma, mi, _, err := Parse(s)
7175
if err != nil {
7276
return false
7377
}
@@ -80,8 +84,8 @@ func WantGoVersion(s string, major, minor int) bool {
8084
// and compared lexicographically.
8185
// See [Parse] for more information.
8286
func Compare(a, b string) int {
83-
aMajor, aMinor, _ := Parse(a)
84-
bMajor, bMinor, _ := Parse(b)
87+
aMajor, aMinor, aPatch, _ := Parse(a)
88+
bMajor, bMinor, bPatch, _ := Parse(b)
8589
switch {
8690
case aMajor < bMajor:
8791
return -1
@@ -91,6 +95,10 @@ func Compare(a, b string) int {
9195
return -1
9296
case aMinor > bMinor:
9397
return +1
98+
case aPatch < bPatch:
99+
return -1
100+
case aPatch > bPatch:
101+
return +1
94102
default:
95103
return strings.Compare(a, b)
96104
}

goenv/version_test.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,33 @@ func TestParse(t *testing.T) {
77
v string
88
major int
99
minor int
10+
patch int
1011
wantErr bool
1112
}{
12-
{"", 0, 0, true},
13-
{"go", 0, 0, true},
14-
{"go1", 0, 0, true},
15-
{"go.0", 0, 0, true},
16-
{"go1.0", 1, 0, false},
17-
{"go1.1", 1, 1, false},
18-
{"go1.23", 1, 23, false},
19-
{"go1.23.5", 1, 23, false},
20-
{"go1.23.5-rc6", 1, 23, false},
21-
{"go2.0", 2, 0, false},
13+
{"", 0, 0, 0, true},
14+
{"go", 0, 0, 0, true},
15+
{"go1", 0, 0, 0, true},
16+
{"go.0", 0, 0, 0, true},
17+
{"go1.0", 1, 0, 0, false},
18+
{"go1.1", 1, 1, 0, false},
19+
{"go1.23", 1, 23, 0, false},
20+
{"go1.23.5", 1, 23, 5, false},
21+
{"go1.23.5-rc6", 1, 23, 5, false},
22+
{"go2.0", 2, 0, 0, false},
23+
{"go2.0.15", 2, 0, 15, false},
2224
}
2325
for _, tt := range tests {
2426
t.Run(tt.v, func(t *testing.T) {
25-
major, minor, err := Parse(tt.v)
27+
major, minor, patch, err := Parse(tt.v)
2628
if err == nil && tt.wantErr {
2729
t.Errorf("Parse(%q): expected err != nil", tt.v)
2830
}
2931
if err != nil && !tt.wantErr {
3032
t.Errorf("Parse(%q): expected err == nil", tt.v)
3133
}
32-
if major != tt.major || minor != tt.minor {
33-
t.Errorf("Parse(%q): expected %d, %d, nil; got %d, %d, %v",
34-
tt.v, tt.major, tt.minor, major, minor, err)
34+
if major != tt.major || minor != tt.minor || patch != tt.patch {
35+
t.Errorf("Parse(%q): expected %d, %d, %d, nil; got %d, %d, %d, %v",
36+
tt.v, tt.major, tt.minor, tt.patch, major, minor, patch, err)
3537
}
3638
})
3739
}
@@ -84,7 +86,8 @@ func TestCompare(t *testing.T) {
8486
{"go1.1.0", "go1.2.0", -1},
8587
{"go1.2.0", "go1.1.0", 1},
8688
{"go1.2.0", "go2.3.0", -1},
87-
// {"go1.23.2", "go1.23.10", -1}, // FIXME: parse patch number
89+
{"go1.23.2", "go1.23.10", -1},
90+
{"go0.1.22", "go1.23.101", -1},
8891
}
8992
for _, tt := range tests {
9093
t.Run(tt.a+" "+tt.b, func(t *testing.T) {

0 commit comments

Comments
 (0)