Skip to content

Commit 0d527b2

Browse files
committed
Go: Keep track of all installed toolchains that we know of
1 parent 96a6dd7 commit 0d527b2

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

go/extractor/toolchain/toolchain.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ func IsInstalled() bool {
1616
return err == nil
1717
}
1818

19+
// The default Go version that is available on a system and a set of all versions
20+
// that we know are installed on the system.
1921
var goVersion = ""
22+
var goVersions = map[string]struct{}{}
23+
24+
// Adds an entry to the set of installed Go versions for the normalised `version` number.
25+
func addGoVersion(version string) {
26+
goVersions[semver.Canonical(version)] = struct{}{}
27+
}
2028

2129
// Returns the current Go version as returned by 'go version', e.g. go1.14.4
2230
func GetEnvGoVersion() string {
@@ -34,10 +42,57 @@ func GetEnvGoVersion() string {
3442
}
3543

3644
goVersion = parseGoVersion(string(out))
45+
addGoVersion(goVersion)
3746
}
3847
return goVersion
3948
}
4049

50+
// Determines whether, to our knowledge, `version` is available on the current system.
51+
func HasGoVersion(version string) bool {
52+
_, found := goVersions[semver.Canonical(version)]
53+
return found
54+
}
55+
56+
// Attempts to install the Go toolchain `version`.
57+
func InstallVersion(workingDir string, version string) bool {
58+
// No need to install it if we know that it is already installed.
59+
if HasGoVersion(version) {
60+
return true
61+
}
62+
63+
// Construct a command to invoke `go version` with `GOTOOLCHAIN=go1.N.0` to give
64+
// Go a valid toolchain version to download the toolchain we need; subsequent commands
65+
// should then work even with an invalid version that's still in `go.mod`
66+
toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical(version)
67+
versionCmd := Version()
68+
versionCmd.Dir = workingDir
69+
versionCmd.Env = append(os.Environ(), toolchainArg)
70+
71+
log.Printf(
72+
"Trying to install Go %s using its canonical representation in `%s`.",
73+
version,
74+
workingDir,
75+
)
76+
77+
// Run the command. If something goes wrong, report it to the log and signal failure
78+
// to the caller.
79+
if versionErr := versionCmd.Run(); versionErr != nil {
80+
log.Printf(
81+
"Failed to invoke `%s go version` in %s: %s\n",
82+
toolchainArg,
83+
versionCmd.Dir,
84+
versionErr.Error(),
85+
)
86+
87+
return false
88+
}
89+
90+
// Add the version to the set of versions that we know are installed and signal
91+
// success to the caller.
92+
addGoVersion(version)
93+
return true
94+
}
95+
4196
// Returns the current Go version in semver format, e.g. v1.14.4
4297
func GetEnvGoSemVer() string {
4398
goVersion := GetEnvGoVersion()

0 commit comments

Comments
 (0)