@@ -8,72 +8,70 @@ import (
88 "github.com/github/codeql-go/extractor/diagnostics"
99 "github.com/github/codeql-go/extractor/project"
1010 "github.com/github/codeql-go/extractor/toolchain"
11- "golang.org/x/mod/semver "
11+ "github.com/github/codeql-go/extractor/util "
1212)
1313
14- const minGoVersion = "1.11"
15- const maxGoVersion = "1.22"
14+ var minGoVersion = util . NewSemVer ( "1.11" )
15+ var maxGoVersion = util . NewSemVer ( "1.22" )
1616
1717type versionInfo struct {
18- goModVersion string // The version of Go found in the go directive in the `go.mod` file.
19- goModVersionFound bool // Whether a `go` directive was found in the `go.mod` file.
20- goEnvVersion string // The version of Go found in the environment.
21- goEnvVersionFound bool // Whether an installation of Go was found in the environment.
18+ goModVersion util.SemVer // The version of Go found in the go directive in the `go.mod` file.
19+ goEnvVersion util.SemVer // The version of Go found in the environment.
2220}
2321
2422func (v versionInfo ) String () string {
2523 return fmt .Sprintf (
26- "go.mod version: %s, go.mod directive found: %t, go env version: %s, go installation found: %t " ,
27- v .goModVersion , v .goModVersionFound , v . goEnvVersion , v . goEnvVersionFound )
24+ "go.mod version: %s, go env version: %s" ,
25+ v .goModVersion , v .goEnvVersion )
2826}
2927
3028// Check if `version` is lower than `minGoVersion`. Note that for this comparison we ignore the
3129// patch part of the version, so 1.20.1 and 1.20 are considered equal.
32- func belowSupportedRange (version string ) bool {
33- return semver . Compare ( semver . MajorMinor ("v" + version ), "v" + minGoVersion ) < 0
30+ func belowSupportedRange (version util. SemVer ) bool {
31+ return version . MajorMinor (). IsOlderThan ( minGoVersion . MajorMinor ())
3432}
3533
3634// Check if `version` is higher than `maxGoVersion`. Note that for this comparison we ignore the
3735// patch part of the version, so 1.20.1 and 1.20 are considered equal.
38- func aboveSupportedRange (version string ) bool {
39- return semver . Compare ( semver . MajorMinor ("v" + version ), "v" + maxGoVersion ) > 0
36+ func aboveSupportedRange (version util. SemVer ) bool {
37+ return version . MajorMinor (). IsNewerThan ( maxGoVersion . MajorMinor ())
4038}
4139
4240// Check if `version` is lower than `minGoVersion` or higher than `maxGoVersion`. Note that for
4341// this comparison we ignore the patch part of the version, so 1.20.1 and 1.20 are considered
4442// equal.
45- func outsideSupportedRange (version string ) bool {
43+ func outsideSupportedRange (version util. SemVer ) bool {
4644 return belowSupportedRange (version ) || aboveSupportedRange (version )
4745}
4846
4947// Assuming `v.goModVersionFound` is false, emit a diagnostic and return the version to install,
5048// or the empty string if we should not attempt to install a version of Go.
51- func getVersionWhenGoModVersionNotFound (v versionInfo ) (msg , version string ) {
52- if ! v . goEnvVersionFound {
49+ func getVersionWhenGoModVersionNotFound (v versionInfo ) (msg string , version util. SemVer ) {
50+ if v . goEnvVersion == nil {
5351 // There is no Go version installed in the environment. We have no indication which version
5452 // was intended to be used to build this project. Go versions are generally backwards
5553 // compatible, so we install the maximum supported version.
5654 msg = "No version of Go installed and no `go.mod` file found. Requesting the maximum " +
57- "supported version of Go (" + maxGoVersion + ")."
55+ "supported version of Go (" + maxGoVersion . String () + ")."
5856 version = maxGoVersion
5957 diagnostics .EmitNoGoModAndNoGoEnv (msg )
6058 } else if outsideSupportedRange (v .goEnvVersion ) {
6159 // The Go version installed in the environment is not supported. We have no indication
6260 // which version was intended to be used to build this project. Go versions are generally
6361 // backwards compatible, so we install the maximum supported version.
6462 msg = "No `go.mod` file found. The version of Go installed in the environment (" +
65- v .goEnvVersion + ") is outside of the supported range (" + minGoVersion + "-" +
66- maxGoVersion + "). Requesting the maximum supported version of Go (" + maxGoVersion +
63+ v .goEnvVersion . String () + ") is outside of the supported range (" + minGoVersion . String () + "-" +
64+ maxGoVersion . String () + "). Requesting the maximum supported version of Go (" + maxGoVersion . String () +
6765 ")."
6866 version = maxGoVersion
6967 diagnostics .EmitNoGoModAndGoEnvUnsupported (msg )
7068 } else {
7169 // The version of Go that is installed is supported. We have no indication which version
7270 // was intended to be used to build this project. We assume that the installed version is
7371 // suitable and do not install a version of Go.
74- msg = "No `go.mod` file found. Version " + v .goEnvVersion + " installed in the " +
72+ msg = "No `go.mod` file found. Version " + v .goEnvVersion . String () + " installed in the " +
7573 "environment is supported. Not requesting any version of Go."
76- version = ""
74+ version = nil
7775 diagnostics .EmitNoGoModAndGoEnvSupported (msg )
7876 }
7977
@@ -82,57 +80,57 @@ func getVersionWhenGoModVersionNotFound(v versionInfo) (msg, version string) {
8280
8381// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the
8482// version to install, or the empty string if we should not attempt to install a version of Go.
85- func getVersionWhenGoModVersionTooHigh (v versionInfo ) (msg , version string ) {
86- if ! v . goEnvVersionFound {
83+ func getVersionWhenGoModVersionTooHigh (v versionInfo ) (msg string , version util. SemVer ) {
84+ if v . goEnvVersion == nil {
8785 // The version in the `go.mod` file is above the supported range. There is no Go version
8886 // installed. We install the maximum supported version as a best effort.
89- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
90- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
87+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
88+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
9189 "). No version of Go installed. Requesting the maximum supported version of Go (" +
92- maxGoVersion + ")."
90+ maxGoVersion . String () + ")."
9391 version = maxGoVersion
9492 diagnostics .EmitGoModVersionTooHighAndNoGoEnv (msg )
9593 } else if aboveSupportedRange (v .goEnvVersion ) {
9694 // The version in the `go.mod` file is above the supported range. The version of Go that
9795 // is installed is above the supported range. We do not install a version of Go.
98- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
99- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
100- "). The version of Go installed in the environment (" + v .goEnvVersion +
101- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
96+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
97+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
98+ "). The version of Go installed in the environment (" + v .goEnvVersion . String () +
99+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
102100 "). Not requesting any version of Go."
103- version = ""
101+ version = nil
104102 diagnostics .EmitGoModVersionTooHighAndEnvVersionTooHigh (msg )
105103 } else if belowSupportedRange (v .goEnvVersion ) {
106104 // The version in the `go.mod` file is above the supported range. The version of Go that
107105 // is installed is below the supported range. We install the maximum supported version as
108106 // a best effort.
109- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
110- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
111- "). The version of Go installed in the environment (" + v .goEnvVersion +
112- ") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
113- "). Requesting the maximum supported version of Go (" + maxGoVersion + ")."
107+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
108+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
109+ "). The version of Go installed in the environment (" + v .goEnvVersion . String () +
110+ ") is below the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
111+ "). Requesting the maximum supported version of Go (" + maxGoVersion . String () + ")."
114112 version = maxGoVersion
115113 diagnostics .EmitGoModVersionTooHighAndEnvVersionTooLow (msg )
116- } else if semver . Compare ( "v" + maxGoVersion , "v" + v .goEnvVersion ) > 0 {
114+ } else if maxGoVersion . IsNewerThan ( v .goEnvVersion ) {
117115 // The version in the `go.mod` file is above the supported range. The version of Go that
118116 // is installed is supported and below the maximum supported version. We install the
119117 // maximum supported version as a best effort.
120- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
121- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
122- "). The version of Go installed in the environment (" + v .goEnvVersion +
123- ") is below the maximum supported version (" + maxGoVersion +
124- "). Requesting the maximum supported version of Go (" + maxGoVersion + ")."
118+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
119+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
120+ "). The version of Go installed in the environment (" + v .goEnvVersion . String () +
121+ ") is below the maximum supported version (" + maxGoVersion . String () +
122+ "). Requesting the maximum supported version of Go (" + maxGoVersion . String () + ")."
125123 version = maxGoVersion
126124 diagnostics .EmitGoModVersionTooHighAndEnvVersionBelowMax (msg )
127125 } else {
128126 // The version in the `go.mod` file is above the supported range. The version of Go that
129127 // is installed is the maximum supported version. We do not install a version of Go.
130- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
131- ") is above the supported range (" + minGoVersion + "-" + maxGoVersion +
132- "). The version of Go installed in the environment (" + v .goEnvVersion +
133- ") is the maximum supported version (" + maxGoVersion +
128+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
129+ ") is above the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
130+ "). The version of Go installed in the environment (" + v .goEnvVersion . String () +
131+ ") is the maximum supported version (" + maxGoVersion . String () +
134132 "). Not requesting any version of Go."
135- version = ""
133+ version = nil
136134 diagnostics .EmitGoModVersionTooHighAndEnvVersionMax (msg )
137135 }
138136
@@ -141,35 +139,35 @@ func getVersionWhenGoModVersionTooHigh(v versionInfo) (msg, version string) {
141139
142140// Assuming `v.goModVersion` is below the supported range, emit a diagnostic and return the
143141// version to install, or the empty string if we should not attempt to install a version of Go.
144- func getVersionWhenGoModVersionTooLow (v versionInfo ) (msg , version string ) {
145- if ! v . goEnvVersionFound {
142+ func getVersionWhenGoModVersionTooLow (v versionInfo ) (msg string , version util. SemVer ) {
143+ if v . goEnvVersion == nil {
146144 // There is no Go version installed. The version in the `go.mod` file is below the
147145 // supported range. Go versions are generally backwards compatible, so we install the
148146 // minimum supported version.
149- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
150- ") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
147+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
148+ ") is below the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
151149 "). No version of Go installed. Requesting the minimum supported version of Go (" +
152- minGoVersion + ")."
150+ minGoVersion . String () + ")."
153151 version = minGoVersion
154152 diagnostics .EmitGoModVersionTooLowAndNoGoEnv (msg )
155153 } else if outsideSupportedRange (v .goEnvVersion ) {
156154 // The version of Go that is installed is outside of the supported range. The version
157155 // in the `go.mod` file is below the supported range. Go versions are generally
158156 // backwards compatible, so we install the minimum supported version.
159- msg = "The version of Go found in the `go.mod` file (" + v .goModVersion +
160- ") is below the supported range (" + minGoVersion + "-" + maxGoVersion +
161- "). The version of Go installed in the environment (" + v .goEnvVersion +
162- ") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion + "). " +
163- "Requesting the minimum supported version of Go (" + minGoVersion + ")."
157+ msg = "The version of Go found in the `go.mod` file (" + v .goModVersion . String () +
158+ ") is below the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () +
159+ "). The version of Go installed in the environment (" + v .goEnvVersion . String () +
160+ ") is outside of the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () + "). " +
161+ "Requesting the minimum supported version of Go (" + minGoVersion . String () + ")."
164162 version = minGoVersion
165163 diagnostics .EmitGoModVersionTooLowAndEnvVersionUnsupported (msg )
166164 } else {
167165 // The version of Go that is installed is supported. The version in the `go.mod` file is
168166 // below the supported range. We do not install a version of Go.
169- msg = "The version of Go installed in the environment (" + v .goEnvVersion +
167+ msg = "The version of Go installed in the environment (" + v .goEnvVersion . String () +
170168 ") is supported and is high enough for the version found in the `go.mod` file (" +
171- v .goModVersion + "). Not requesting any version of Go."
172- version = ""
169+ v .goModVersion . String () + "). Not requesting any version of Go."
170+ version = nil
173171 diagnostics .EmitGoModVersionTooLowAndEnvVersionSupported (msg )
174172 }
175173
@@ -178,40 +176,40 @@ func getVersionWhenGoModVersionTooLow(v versionInfo) (msg, version string) {
178176
179177// Assuming `v.goModVersion` is in the supported range, emit a diagnostic and return the version
180178// to install, or the empty string if we should not attempt to install a version of Go.
181- func getVersionWhenGoModVersionSupported (v versionInfo ) (msg , version string ) {
182- if ! v . goEnvVersionFound {
179+ func getVersionWhenGoModVersionSupported (v versionInfo ) (msg string , version util. SemVer ) {
180+ if v . goEnvVersion == nil {
183181 // There is no Go version installed. The version in the `go.mod` file is supported.
184182 // We install the version from the `go.mod` file.
185183 msg = "No version of Go installed. Requesting the version of Go found in the `go.mod` " +
186- "file (" + v .goModVersion + ")."
184+ "file (" + v .goModVersion . String () + ")."
187185 version = v .goModVersion
188186 diagnostics .EmitGoModVersionSupportedAndNoGoEnv (msg )
189187 } else if outsideSupportedRange (v .goEnvVersion ) {
190188 // The version of Go that is installed is outside of the supported range. The version in
191189 // the `go.mod` file is supported. We install the version from the `go.mod` file.
192- msg = "The version of Go installed in the environment (" + v .goEnvVersion +
193- ") is outside of the supported range (" + minGoVersion + "-" + maxGoVersion + "). " +
190+ msg = "The version of Go installed in the environment (" + v .goEnvVersion . String () +
191+ ") is outside of the supported range (" + minGoVersion . String () + "-" + maxGoVersion . String () + "). " +
194192 "Requesting the version of Go from the `go.mod` file (" +
195- v .goModVersion + ")."
193+ v .goModVersion . String () + ")."
196194 version = v .goModVersion
197195 diagnostics .EmitGoModVersionSupportedAndGoEnvUnsupported (msg )
198- } else if semver . Compare ( "v" + v .goModVersion , "v" + v .goEnvVersion ) > 0 {
196+ } else if v .goModVersion . IsNewerThan ( v .goEnvVersion ) {
199197 // The version of Go that is installed is supported. The version in the `go.mod` file is
200198 // supported and is higher than the version that is installed. We install the version from
201199 // the `go.mod` file.
202- msg = "The version of Go installed in the environment (" + v .goEnvVersion +
203- ") is lower than the version found in the `go.mod` file (" + v .goModVersion +
204- "). Requesting the version of Go from the `go.mod` file (" + v .goModVersion + ")."
200+ msg = "The version of Go installed in the environment (" + v .goEnvVersion . String () +
201+ ") is lower than the version found in the `go.mod` file (" + v .goModVersion . String () +
202+ "). Requesting the version of Go from the `go.mod` file (" + v .goModVersion . String () + ")."
205203 version = v .goModVersion
206204 diagnostics .EmitGoModVersionSupportedHigherGoEnv (msg )
207205 } else {
208206 // The version of Go that is installed is supported. The version in the `go.mod` file is
209207 // supported and is lower than or equal to the version that is installed. We do not install
210208 // a version of Go.
211- msg = "The version of Go installed in the environment (" + v .goEnvVersion +
209+ msg = "The version of Go installed in the environment (" + v .goEnvVersion . String () +
212210 ") is supported and is high enough for the version found in the `go.mod` file (" +
213- v .goModVersion + "). Not requesting any version of Go."
214- version = ""
211+ v .goModVersion . String () + "). Not requesting any version of Go."
212+ version = nil
215213 diagnostics .EmitGoModVersionSupportedLowerEqualGoEnv (msg )
216214 }
217215
@@ -231,8 +229,8 @@ func getVersionWhenGoModVersionSupported(v versionInfo) (msg, version string) {
231229// | *In supported range* | No action | No action | Install version from go.mod if newer than installed | Install max supported if newer than installed |
232230// | *Above max supported* | Install max supported | Install min supported | Install version from go.mod | No action |
233231// +-----------------------+-----------------------+-----------------------+-----------------------------------------------------+------------------------------------------------+
234- func getVersionToInstall (v versionInfo ) (msg , version string ) {
235- if ! v . goModVersionFound {
232+ func getVersionToInstall (v versionInfo ) (msg string , version util. SemVer ) {
233+ if v . goModVersion == nil {
236234 return getVersionWhenGoModVersionNotFound (v )
237235 }
238236
@@ -249,12 +247,12 @@ func getVersionToInstall(v versionInfo) (msg, version string) {
249247
250248// Output some JSON to stdout specifying the version of Go to install, unless `version` is the
251249// empty string.
252- func outputEnvironmentJson (version string ) {
250+ func outputEnvironmentJson (version util. SemVer ) {
253251 var content string
254- if version == "" {
252+ if version == nil {
255253 content = `{ "go": {} }`
256254 } else {
257- content = `{ "go": { "version": "` + version + `" } }`
255+ content = `{ "go": { "version": "` + version . String () + `" } }`
258256 }
259257 _ , err := fmt .Fprint (os .Stdout , content )
260258
@@ -273,14 +271,10 @@ func IdentifyEnvironment() {
273271 defer project .RemoveTemporaryExtractorFiles ()
274272
275273 // Find the greatest Go version required by any of the workspaces.
276- greatestGoVersion := project .RequiredGoVersion (& workspaces )
277- v .goModVersion , v .goModVersionFound = greatestGoVersion .String (), greatestGoVersion != nil
274+ v .goModVersion = project .RequiredGoVersion (& workspaces )
278275
279276 // Find which, if any, version of Go is installed on the system already.
280- v .goEnvVersionFound = toolchain .IsInstalled ()
281- if v .goEnvVersionFound {
282- v .goEnvVersion = toolchain .GetEnvGoVersion ()[2 :]
283- }
277+ v .goEnvVersion = toolchain .GetEnvGoSemVer ()
284278
285279 // Determine which version of Go we should recommend to install.
286280 msg , versionToInstall := getVersionToInstall (v )
0 commit comments