Skip to content

Commit 1b82143

Browse files
committed
Go: Use SemVer type in toolchain package
1 parent 3b40302 commit 1b82143

File tree

4 files changed

+26
-31
lines changed

4 files changed

+26
-31
lines changed

go/extractor/cli/go-autobuilder/go-autobuilder.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ func getNeedGopath(workspace project.GoWorkspace, importpath string) bool {
156156
// Try to update `go.mod` and `go.sum` if the go version is >= 1.16.
157157
func tryUpdateGoModAndGoSum(workspace project.GoWorkspace) {
158158
// Go 1.16 and later won't automatically attempt to update go.mod / go.sum during package loading, so try to update them here:
159-
if workspace.ModMode != project.ModVendor && workspace.DepMode == project.GoGetWithModules && semver.Compare(toolchain.GetEnvGoSemVer(), "v1.16") >= 0 {
159+
v1_16 := util.NewSemVer("v1.16")
160+
if workspace.ModMode != project.ModVendor && workspace.DepMode == project.GoGetWithModules && toolchain.GetEnvGoSemVer().IsAtLeast(v1_16) {
160161
for _, goMod := range workspace.Modules {
161162
// stat go.mod and go.sum
162163
goModPath := goMod.Path
@@ -333,7 +334,7 @@ func buildWithoutCustomCommands(modMode project.ModMode) bool {
333334
log.Println("Build failed, continuing to install dependencies.")
334335

335336
shouldInstallDependencies = true
336-
} else if toolchain.DepErrors("./...", modMode.ArgsForGoVersion(toolchain.GetEnvGoSemVer())...) {
337+
} else if toolchain.DepErrors("./...", modMode.ArgsForGoVersion(toolchain.GetEnvGoSemVer().String())...) {
337338
log.Println("Dependencies are still not resolving after the build, continuing to install dependencies.")
338339

339340
shouldInstallDependencies = true
@@ -447,7 +448,7 @@ func extract(workspace project.GoWorkspace) bool {
447448

448449
extractorArgs := []string{}
449450
if workspace.DepMode == project.GoGetWithModules {
450-
extractorArgs = append(extractorArgs, workspace.ModMode.ArgsForGoVersion(toolchain.GetEnvGoSemVer())...)
451+
extractorArgs = append(extractorArgs, workspace.ModMode.ArgsForGoVersion(toolchain.GetEnvGoSemVer().String())...)
451452
}
452453

453454
if len(workspace.Modules) == 0 {
@@ -537,8 +538,9 @@ func installDependenciesAndBuild() {
537538

538539
// This diagnostic is not required if the system Go version is 1.21 or greater, since the
539540
// Go tooling should install required Go versions as needed.
540-
if semver.Compare(toolchain.GetEnvGoSemVer(), "v1.21.0") < 0 && greatestGoVersion.Found && semver.Compare("v"+greatestGoVersion.Version, toolchain.GetEnvGoSemVer()) > 0 {
541-
diagnostics.EmitNewerGoVersionNeeded(toolchain.GetEnvGoSemVer(), "v"+greatestGoVersion.Version)
541+
v1_21 := util.NewSemVer("v1.21.0")
542+
if toolchain.GetEnvGoSemVer().IsOlderThan(v1_21) && greatestGoVersion.Found && semver.Compare("v"+greatestGoVersion.Version, toolchain.GetEnvGoSemVer().String()) > 0 {
543+
diagnostics.EmitNewerGoVersionNeeded(toolchain.GetEnvGoSemVer().String(), "v"+greatestGoVersion.Version)
542544
if val, _ := os.LookupEnv("GITHUB_ACTIONS"); val == "true" {
543545
log.Printf(
544546
"A go.mod file requires version %s of Go, but version %s is installed. Consider adding an actions/setup-go step to your workflow.\n",

go/extractor/toolchain/BUILD.bazel

+2-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/extractor/toolchain/toolchain.go

+11-20
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"strings"
1212

1313
"github.com/github/codeql-go/extractor/util"
14-
"golang.org/x/mod/semver"
1514
)
1615

1716
// Check if Go is installed in the environment.
@@ -23,11 +22,11 @@ func IsInstalled() bool {
2322
// The default Go version that is available on a system and a set of all versions
2423
// that we know are installed on the system.
2524
var goVersion = ""
26-
var goVersions = map[string]struct{}{}
25+
var goVersions = map[util.SemVer]struct{}{}
2726

2827
// Adds an entry to the set of installed Go versions for the normalised `version` number.
29-
func addGoVersion(version string) {
30-
goVersions[semver.Canonical("v"+version)] = struct{}{}
28+
func addGoVersion(version util.SemVer) {
29+
goVersions[version] = struct{}{}
3130
}
3231

3332
// Returns the current Go version as returned by 'go version', e.g. go1.14.4
@@ -53,19 +52,19 @@ func GetEnvGoVersion() string {
5352
}
5453

5554
goVersion = parseGoVersion(string(out))
56-
addGoVersion(goVersion[2:])
55+
addGoVersion(util.NewSemVer(goVersion))
5756
}
5857
return goVersion
5958
}
6059

6160
// Determines whether, to our knowledge, `version` is available on the current system.
62-
func HasGoVersion(version string) bool {
63-
_, found := goVersions[semver.Canonical("v"+version)]
61+
func HasGoVersion(version util.SemVer) bool {
62+
_, found := goVersions[version]
6463
return found
6564
}
6665

6766
// Attempts to install the Go toolchain `version`.
68-
func InstallVersion(workingDir string, version string) bool {
67+
func InstallVersion(workingDir string, version util.SemVer) bool {
6968
// No need to install it if we know that it is already installed.
7069
if HasGoVersion(version) {
7170
return true
@@ -74,7 +73,7 @@ func InstallVersion(workingDir string, version string) bool {
7473
// Construct a command to invoke `go version` with `GOTOOLCHAIN=go1.N.0` to give
7574
// Go a valid toolchain version to download the toolchain we need; subsequent commands
7675
// should then work even with an invalid version that's still in `go.mod`
77-
toolchainArg := "GOTOOLCHAIN=go" + semver.Canonical("v" + version)[1:]
76+
toolchainArg := "GOTOOLCHAIN=go" + version.String()[1:]
7877
versionCmd := Version()
7978
versionCmd.Dir = workingDir
8079
versionCmd.Env = append(os.Environ(), toolchainArg)
@@ -107,20 +106,12 @@ func InstallVersion(workingDir string, version string) bool {
107106
}
108107

109108
// Returns the current Go version in semver format, e.g. v1.14.4
110-
func GetEnvGoSemVer() string {
109+
func GetEnvGoSemVer() util.SemVer {
111110
goVersion := GetEnvGoVersion()
112111
if !strings.HasPrefix(goVersion, "go") {
113112
log.Fatalf("Expected 'go version' output of the form 'go1.2.3'; got '%s'", goVersion)
114113
}
115-
// Go versions don't follow the SemVer format, but the only exception we normally care about
116-
// is release candidates; so this is a horrible hack to convert e.g. `go1.22rc1` into `go1.22-rc1`
117-
// which is compatible with the SemVer specification
118-
rcIndex := strings.Index(goVersion, "rc")
119-
if rcIndex != -1 {
120-
return semver.Canonical("v"+goVersion[2:rcIndex]) + "-" + goVersion[rcIndex:]
121-
} else {
122-
return semver.Canonical("v" + goVersion[2:])
123-
}
114+
return util.NewSemVer(goVersion)
124115
}
125116

126117
// The 'go version' command may output warnings on separate lines before
@@ -137,7 +128,7 @@ func parseGoVersion(data string) string {
137128

138129
// Returns a value indicating whether the system Go toolchain supports workspaces.
139130
func SupportsWorkspaces() bool {
140-
return semver.Compare(GetEnvGoSemVer(), "v1.18.0") >= 0
131+
return GetEnvGoSemVer().IsAtLeast(util.NewSemVer("v1.18.0"))
141132
}
142133

143134
// Run `go mod tidy -e` in the directory given by `path`.

go/extractor/toolchain/toolchain_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package toolchain
22

3-
import "testing"
3+
import (
4+
"testing"
5+
6+
"github.com/github/codeql-go/extractor/util"
7+
)
48

59
func TestParseGoVersion(t *testing.T) {
610
tests := map[string]string{
@@ -16,7 +20,7 @@ func TestParseGoVersion(t *testing.T) {
1620
}
1721

1822
func TestHasGoVersion(t *testing.T) {
19-
if HasGoVersion("1.21") {
23+
if HasGoVersion(util.NewSemVer("1.21")) {
2024
t.Error("Expected HasGoVersion(\"1.21\") to be false, but got true")
2125
}
2226
}

0 commit comments

Comments
 (0)