@@ -61,11 +61,19 @@ var goVersion = ""
61
61
// Returns the current Go version as returned by 'go version', e.g. go1.14.4
62
62
func getEnvGoVersion () string {
63
63
if goVersion == "" {
64
- gover , err := exec .Command ("go" , "version" ).CombinedOutput ()
64
+ // Since Go 1.21, running 'go version' in a directory with a 'go.mod' file will attempt to
65
+ // download the version of Go specified in there. That may either fail or result in us just
66
+ // being told what's already in 'go.mod'. Setting 'GOTOOLCHAIN' to 'local' will force it
67
+ // to use the local Go toolchain instead.
68
+ cmd := exec .Command ("go" , "version" )
69
+ cmd .Env = append (os .Environ (), "GOTOOLCHAIN=local" )
70
+ out , err := cmd .CombinedOutput ()
71
+
65
72
if err != nil {
66
73
log .Fatalf ("Unable to run the go command, is it installed?\n Error: %s" , err .Error ())
67
74
}
68
- goVersion = parseGoVersion (string (gover ))
75
+
76
+ goVersion = parseGoVersion (string (out ))
69
77
}
70
78
return goVersion
71
79
}
@@ -367,8 +375,15 @@ func getDepMode(emitDiagnostics bool) (DependencyInstallerMode, string) {
367
375
return GoGetNoModules , "."
368
376
}
369
377
378
+ type GoVersionInfo struct {
379
+ // The version string, if any
380
+ Version string
381
+ // A value indicating whether a version string was found
382
+ Found bool
383
+ }
384
+
370
385
// Tries to open `go.mod` and read a go directive, returning the version and whether it was found.
371
- func tryReadGoDirective (buildInfo BuildInfo ) ( string , bool ) {
386
+ func tryReadGoDirective (buildInfo BuildInfo ) GoVersionInfo {
372
387
if buildInfo .DepMode == GoGetWithModules {
373
388
versionRe := regexp .MustCompile (`(?m)^go[ \t\r]+([0-9]+\.[0-9]+(\.[0-9]+)?)$` )
374
389
goMod , err := os .ReadFile (filepath .Join (buildInfo .BaseDir , "go.mod" ))
@@ -378,12 +393,12 @@ func tryReadGoDirective(buildInfo BuildInfo) (string, bool) {
378
393
matches := versionRe .FindSubmatch (goMod )
379
394
if matches != nil {
380
395
if len (matches ) > 1 {
381
- return string (matches [1 ]), true
396
+ return GoVersionInfo { string (matches [1 ]), true }
382
397
}
383
398
}
384
399
}
385
400
}
386
- return "" , false
401
+ return GoVersionInfo { "" , false }
387
402
}
388
403
389
404
// Returns the appropriate ModMode for the current project
@@ -771,13 +786,15 @@ func installDependenciesAndBuild() {
771
786
os .Setenv ("GO111MODULE" , "auto" )
772
787
}
773
788
774
- goModVersion , goModVersionFound := tryReadGoDirective (buildInfo )
789
+ goVersionInfo := tryReadGoDirective (buildInfo )
775
790
776
- if goModVersionFound && semver .Compare ("v" + goModVersion , getEnvGoSemVer ()) > 0 {
791
+ // This diagnostic is not required if the system Go version is 1.21 or greater, since the
792
+ // Go tooling should install required Go versions as needed.
793
+ if semver .Compare (getEnvGoSemVer (), "v1.21.0" ) < 0 && goVersionInfo .Found && semver .Compare ("v" + goVersionInfo .Version , getEnvGoSemVer ()) > 0 {
777
794
diagnostics .EmitNewerGoVersionNeeded ()
778
795
}
779
796
780
- fixGoVendorIssues (& buildInfo , goModVersionFound )
797
+ fixGoVendorIssues (& buildInfo , goVersionInfo . Found )
781
798
782
799
tryUpdateGoModAndGoSum (buildInfo )
783
800
@@ -1092,7 +1109,8 @@ func isGoInstalled() bool {
1092
1109
func identifyEnvironment () {
1093
1110
var v versionInfo
1094
1111
buildInfo := getBuildInfo (false )
1095
- v .goModVersion , v .goModVersionFound = tryReadGoDirective (buildInfo )
1112
+ goVersionInfo := tryReadGoDirective (buildInfo )
1113
+ v .goModVersion , v .goModVersionFound = goVersionInfo .Version , goVersionInfo .Found
1096
1114
1097
1115
v .goEnvVersionFound = isGoInstalled ()
1098
1116
if v .goEnvVersionFound {
0 commit comments