Skip to content

Commit ab4ba01

Browse files
committed
add GOROOT/api eval fallback logic to goenv
1 parent c3c09e9 commit ab4ba01

File tree

2 files changed

+69
-15
lines changed

2 files changed

+69
-15
lines changed

builder/env.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func getGorootVersion(goroot string) (int, int, error) {
5656
}
5757

5858
if !strings.HasPrefix(s, "go") {
59-
return 0, 0, fmt.Errorf("%s: version does not start with 'go' prefix", errPrefix)
59+
return 0, 0, fmt.Errorf("%s: [%s] version does not start with 'go' prefix", s, errPrefix)
6060
}
6161

6262
parts := strings.Split(s[2:], ".")

goenv/version.go

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,88 @@ var (
2020
GitSha1 string
2121
)
2222

23+
// parseGorootVersion returns the major and minor version for a given Go version
24+
// string of the form `goX.Y.Z`.
25+
// Returns (0, 0) if the version cannot be determined.
26+
func parseGorootVersion(version string) (int, int, error) {
27+
var (
28+
maj, min int
29+
pch string
30+
)
31+
n, err := fmt.Sscanf(version, "go%d.%d%s", &maj, &min, &pch)
32+
if n == 2 && io.EOF == err {
33+
// Means there were no trailing characters (i.e., not an alpha/beta)
34+
err = nil
35+
}
36+
if nil != err {
37+
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
38+
}
39+
return maj, min, nil
40+
}
41+
2342
// GetGorootVersion returns the major and minor version for a given GOROOT path.
24-
// If the goroot cannot be determined, (0, 0) is returned.
25-
func GetGorootVersion(goroot string) (major, minor int, err error) {
43+
// If the version cannot be determined, (0, 0) is returned.
44+
func GetGorootVersion(goroot string) (int, int, error) {
45+
const errPrefix = "could not parse Go version"
2646
s, err := GorootVersionString(goroot)
2747
if err != nil {
2848
return 0, 0, err
2949
}
3050

31-
if s == "" || s[:2] != "go" {
32-
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
51+
if "" == s {
52+
return 0, 0, fmt.Errorf("%s: version string is empty", errPrefix)
53+
}
54+
55+
if strings.HasPrefix(s, "devel") {
56+
maj, min, err := getGorootApiVersion(goroot)
57+
if nil != err {
58+
return 0, 0, fmt.Errorf("%s: invalid GOROOT API version: %s", errPrefix, err)
59+
}
60+
return maj, min, nil
61+
}
62+
63+
if !strings.HasPrefix(s, "go") {
64+
return 0, 0, fmt.Errorf("%s: version does not start with 'go' prefix", errPrefix)
3365
}
3466

3567
parts := strings.Split(s[2:], ".")
3668
if len(parts) < 2 {
37-
return 0, 0, errors.New("could not parse Go version: version has less than two parts")
69+
return 0, 0, fmt.Errorf("%s: version has less than two parts", errPrefix)
3870
}
3971

40-
// Ignore the errors, we don't really handle errors here anyway.
41-
var trailing string
42-
n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing)
43-
if n == 2 && err == io.EOF {
44-
// Means there were no trailing characters (i.e., not an alpha/beta)
45-
err = nil
72+
return parseGorootVersion(s)
73+
}
74+
75+
// getGorootApiVersion returns the major and minor version of the Go API files
76+
// defined for a given GOROOT path.
77+
// If the version cannot be determined, (0, 0) is returned.
78+
func getGorootApiVersion(goroot string) (int, int, error) {
79+
info, err := ioutil.ReadDir(filepath.Join(goroot, "api"))
80+
if nil != err {
81+
return 0, 0, fmt.Errorf("could not read API feature directory: %s", err)
4682
}
47-
if err != nil {
48-
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
83+
maj, min := -1, -1
84+
for _, f := range info {
85+
if !strings.HasPrefix(f.Name(), "go") || f.IsDir() {
86+
continue
87+
}
88+
vers := strings.TrimSuffix(f.Name(), filepath.Ext(f.Name()))
89+
part := strings.Split(vers[2:], ".")
90+
if len(part) < 2 {
91+
continue
92+
}
93+
vmaj, vmin, err := parseGorootVersion(vers)
94+
if nil != err {
95+
continue
96+
}
97+
if vmaj >= maj && vmin > min {
98+
maj, min = vmaj, vmin
99+
}
100+
}
101+
if maj < 0 || min < 0 {
102+
return 0, 0, errors.New("no valid API feature files")
49103
}
50-
return
104+
return maj, min, nil
51105
}
52106

53107
// GorootVersionString returns the version string as reported by the Go

0 commit comments

Comments
 (0)