@@ -8,72 +8,70 @@ import (
8
8
"github.com/github/codeql-go/extractor/diagnostics"
9
9
"github.com/github/codeql-go/extractor/project"
10
10
"github.com/github/codeql-go/extractor/toolchain"
11
- "golang.org/x/mod/semver "
11
+ "github.com/github/codeql-go/extractor/util "
12
12
)
13
13
14
- const minGoVersion = "1.11"
15
- const maxGoVersion = "1.22"
14
+ var minGoVersion = util . NewSemVer ( "1.11" )
15
+ var maxGoVersion = util . NewSemVer ( "1.22" )
16
16
17
17
type 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.
22
20
}
23
21
24
22
func (v versionInfo ) String () string {
25
23
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 )
28
26
}
29
27
30
28
// Check if `version` is lower than `minGoVersion`. Note that for this comparison we ignore the
31
29
// 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 ())
34
32
}
35
33
36
34
// Check if `version` is higher than `maxGoVersion`. Note that for this comparison we ignore the
37
35
// 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 ())
40
38
}
41
39
42
40
// Check if `version` is lower than `minGoVersion` or higher than `maxGoVersion`. Note that for
43
41
// this comparison we ignore the patch part of the version, so 1.20.1 and 1.20 are considered
44
42
// equal.
45
- func outsideSupportedRange (version string ) bool {
43
+ func outsideSupportedRange (version util. SemVer ) bool {
46
44
return belowSupportedRange (version ) || aboveSupportedRange (version )
47
45
}
48
46
49
47
// Assuming `v.goModVersionFound` is false, emit a diagnostic and return the version to install,
50
48
// 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 {
53
51
// There is no Go version installed in the environment. We have no indication which version
54
52
// was intended to be used to build this project. Go versions are generally backwards
55
53
// compatible, so we install the maximum supported version.
56
54
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 () + ")."
58
56
version = maxGoVersion
59
57
diagnostics .EmitNoGoModAndNoGoEnv (msg )
60
58
} else if outsideSupportedRange (v .goEnvVersion ) {
61
59
// The Go version installed in the environment is not supported. We have no indication
62
60
// which version was intended to be used to build this project. Go versions are generally
63
61
// backwards compatible, so we install the maximum supported version.
64
62
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 () +
67
65
")."
68
66
version = maxGoVersion
69
67
diagnostics .EmitNoGoModAndGoEnvUnsupported (msg )
70
68
} else {
71
69
// The version of Go that is installed is supported. We have no indication which version
72
70
// was intended to be used to build this project. We assume that the installed version is
73
71
// 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 " +
75
73
"environment is supported. Not requesting any version of Go."
76
- version = ""
74
+ version = nil
77
75
diagnostics .EmitNoGoModAndGoEnvSupported (msg )
78
76
}
79
77
@@ -82,57 +80,57 @@ func getVersionWhenGoModVersionNotFound(v versionInfo) (msg, version string) {
82
80
83
81
// Assuming `v.goModVersion` is above the supported range, emit a diagnostic and return the
84
82
// 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 {
87
85
// The version in the `go.mod` file is above the supported range. There is no Go version
88
86
// 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 () +
91
89
"). No version of Go installed. Requesting the maximum supported version of Go (" +
92
- maxGoVersion + ")."
90
+ maxGoVersion . String () + ")."
93
91
version = maxGoVersion
94
92
diagnostics .EmitGoModVersionTooHighAndNoGoEnv (msg )
95
93
} else if aboveSupportedRange (v .goEnvVersion ) {
96
94
// The version in the `go.mod` file is above the supported range. The version of Go that
97
95
// 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 () +
102
100
"). Not requesting any version of Go."
103
- version = ""
101
+ version = nil
104
102
diagnostics .EmitGoModVersionTooHighAndEnvVersionTooHigh (msg )
105
103
} else if belowSupportedRange (v .goEnvVersion ) {
106
104
// The version in the `go.mod` file is above the supported range. The version of Go that
107
105
// is installed is below the supported range. We install the maximum supported version as
108
106
// 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 () + ")."
114
112
version = maxGoVersion
115
113
diagnostics .EmitGoModVersionTooHighAndEnvVersionTooLow (msg )
116
- } else if semver . Compare ( "v" + maxGoVersion , "v" + v .goEnvVersion ) > 0 {
114
+ } else if maxGoVersion . IsNewerThan ( v .goEnvVersion ) {
117
115
// The version in the `go.mod` file is above the supported range. The version of Go that
118
116
// is installed is supported and below the maximum supported version. We install the
119
117
// 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 () + ")."
125
123
version = maxGoVersion
126
124
diagnostics .EmitGoModVersionTooHighAndEnvVersionBelowMax (msg )
127
125
} else {
128
126
// The version in the `go.mod` file is above the supported range. The version of Go that
129
127
// 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 () +
134
132
"). Not requesting any version of Go."
135
- version = ""
133
+ version = nil
136
134
diagnostics .EmitGoModVersionTooHighAndEnvVersionMax (msg )
137
135
}
138
136
@@ -141,35 +139,35 @@ func getVersionWhenGoModVersionTooHigh(v versionInfo) (msg, version string) {
141
139
142
140
// Assuming `v.goModVersion` is below the supported range, emit a diagnostic and return the
143
141
// 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 {
146
144
// There is no Go version installed. The version in the `go.mod` file is below the
147
145
// supported range. Go versions are generally backwards compatible, so we install the
148
146
// 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 () +
151
149
"). No version of Go installed. Requesting the minimum supported version of Go (" +
152
- minGoVersion + ")."
150
+ minGoVersion . String () + ")."
153
151
version = minGoVersion
154
152
diagnostics .EmitGoModVersionTooLowAndNoGoEnv (msg )
155
153
} else if outsideSupportedRange (v .goEnvVersion ) {
156
154
// The version of Go that is installed is outside of the supported range. The version
157
155
// in the `go.mod` file is below the supported range. Go versions are generally
158
156
// 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 () + ")."
164
162
version = minGoVersion
165
163
diagnostics .EmitGoModVersionTooLowAndEnvVersionUnsupported (msg )
166
164
} else {
167
165
// The version of Go that is installed is supported. The version in the `go.mod` file is
168
166
// 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 () +
170
168
") 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
173
171
diagnostics .EmitGoModVersionTooLowAndEnvVersionSupported (msg )
174
172
}
175
173
@@ -178,40 +176,40 @@ func getVersionWhenGoModVersionTooLow(v versionInfo) (msg, version string) {
178
176
179
177
// Assuming `v.goModVersion` is in the supported range, emit a diagnostic and return the version
180
178
// 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 {
183
181
// There is no Go version installed. The version in the `go.mod` file is supported.
184
182
// We install the version from the `go.mod` file.
185
183
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 () + ")."
187
185
version = v .goModVersion
188
186
diagnostics .EmitGoModVersionSupportedAndNoGoEnv (msg )
189
187
} else if outsideSupportedRange (v .goEnvVersion ) {
190
188
// The version of Go that is installed is outside of the supported range. The version in
191
189
// 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 () + "). " +
194
192
"Requesting the version of Go from the `go.mod` file (" +
195
- v .goModVersion + ")."
193
+ v .goModVersion . String () + ")."
196
194
version = v .goModVersion
197
195
diagnostics .EmitGoModVersionSupportedAndGoEnvUnsupported (msg )
198
- } else if semver . Compare ( "v" + v .goModVersion , "v" + v .goEnvVersion ) > 0 {
196
+ } else if v .goModVersion . IsNewerThan ( v .goEnvVersion ) {
199
197
// The version of Go that is installed is supported. The version in the `go.mod` file is
200
198
// supported and is higher than the version that is installed. We install the version from
201
199
// 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 () + ")."
205
203
version = v .goModVersion
206
204
diagnostics .EmitGoModVersionSupportedHigherGoEnv (msg )
207
205
} else {
208
206
// The version of Go that is installed is supported. The version in the `go.mod` file is
209
207
// supported and is lower than or equal to the version that is installed. We do not install
210
208
// 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 () +
212
210
") 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
215
213
diagnostics .EmitGoModVersionSupportedLowerEqualGoEnv (msg )
216
214
}
217
215
@@ -231,8 +229,8 @@ func getVersionWhenGoModVersionSupported(v versionInfo) (msg, version string) {
231
229
// | *In supported range* | No action | No action | Install version from go.mod if newer than installed | Install max supported if newer than installed |
232
230
// | *Above max supported* | Install max supported | Install min supported | Install version from go.mod | No action |
233
231
// +-----------------------+-----------------------+-----------------------+-----------------------------------------------------+------------------------------------------------+
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 {
236
234
return getVersionWhenGoModVersionNotFound (v )
237
235
}
238
236
@@ -249,12 +247,12 @@ func getVersionToInstall(v versionInfo) (msg, version string) {
249
247
250
248
// Output some JSON to stdout specifying the version of Go to install, unless `version` is the
251
249
// empty string.
252
- func outputEnvironmentJson (version string ) {
250
+ func outputEnvironmentJson (version util. SemVer ) {
253
251
var content string
254
- if version == "" {
252
+ if version == nil {
255
253
content = `{ "go": {} }`
256
254
} else {
257
- content = `{ "go": { "version": "` + version + `" } }`
255
+ content = `{ "go": { "version": "` + version . String () + `" } }`
258
256
}
259
257
_ , err := fmt .Fprint (os .Stdout , content )
260
258
@@ -273,14 +271,10 @@ func IdentifyEnvironment() {
273
271
defer project .RemoveTemporaryExtractorFiles ()
274
272
275
273
// 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 )
278
275
279
276
// 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 ()
284
278
285
279
// Determine which version of Go we should recommend to install.
286
280
msg , versionToInstall := getVersionToInstall (v )
0 commit comments