cmd/go: set default GOTOOLCHAIN in GOROOT/go.env

As part of the work for #57179 we moved configurable defaults
to GOROOT/go.env, so that packagers don't have to modify
source code to change those defaults. Since packagers may want
to modify GOTOOLCHAIN's default, move it to go.env too.

This CL modifies 'go env' to print GOTOOLCHAIN by default.
It also refines CL 496957 from yesterday to recognize any env
var in either go.env or the user go/env, not just the user go/env.
When I put GOTOOLCHAIN in go.env, but before I added it to
the default printing list, 'go env GOTOOLCHAIN' was printing
an empty string, and it was incredibly confusing.

For #57001.
Fixes #60361 while we're here.

Also includes a fix for a review comment on CL 497079 that I forgot to mail.

Change-Id: I7b904d9202f05af789aaa33aed93f903b515aa28
Reviewed-on: https://go-review.googlesource.com/c/go/+/497437
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Russ Cox <rsc@golang.org>
This commit is contained in:
Russ Cox 2023-05-23 12:37:01 -04:00
parent 807cce479f
commit a6a25869f0
5 changed files with 45 additions and 15 deletions

4
go.env
View File

@ -6,3 +6,7 @@
# See https://proxy.golang.org for details.
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/s/gotoolchain for details.
GOTOOLCHAIN=auto

View File

@ -70,7 +70,13 @@ func switchGoToolchain() {
gotoolchain := cfg.Getenv("GOTOOLCHAIN")
if gotoolchain == "" {
gotoolchain = "auto"
// cfg.Getenv should fall back to $GOROOT/go.env,
// so this should not happen, unless a packager
// has deleted the GOTOOLCHAIN line from go.env.
// It can also happen if GOROOT is missing or broken,
// in which case best to let the go command keep running
// and diagnose the problem.
return
}
gotoolchain, min, haveMin := strings.Cut(gotoolchain, "+")
@ -306,6 +312,9 @@ func goInstallVersion() (m module.Version, goVers string, ok bool) {
break
}
if a == "-" {
break
}
if a == "--" {
if i+1 < len(args) {
arg = args[i+1]
}

View File

@ -387,6 +387,11 @@ func Getenv(key string) string {
// CanGetenv reports whether key is a valid go/env configuration key.
func CanGetenv(key string) bool {
envCache.once.Do(initEnvCache)
if _, ok := envCache.m[key]; ok {
// Assume anything in the user file or go.env file is valid.
return true
}
return strings.Contains(cfg.KnownEnv, "\t"+key+"\n")
}

View File

@ -100,6 +100,7 @@ func MkEnv() []cfg.EnvVar {
{Name: "GOROOT", Value: cfg.GOROOT},
{Name: "GOSUMDB", Value: cfg.GOSUMDB},
{Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")},
{Name: "GOTOOLCHAIN", Value: cfg.Getenv("GOTOOLCHAIN")},
{Name: "GOTOOLDIR", Value: build.ToolDir},
{Name: "GOVCS", Value: cfg.GOVCS},
{Name: "GOVERSION", Value: runtime.Version()},
@ -145,13 +146,16 @@ func envOr(name, def string) string {
return def
}
func findEnv(env []cfg.EnvVar, envFile map[string]string, name string) string {
func findEnv(env []cfg.EnvVar, name string) string {
for _, e := range env {
if e.Name == name {
return e.Value
}
}
return envFile[name]
if cfg.CanGetenv(name) {
return cfg.Getenv(name)
}
return ""
}
// ExtraEnvVars returns environment variables that should not leak into child processes.
@ -252,7 +256,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
env := cfg.CmdEnv
env = append(env, ExtraEnvVars()...)
envFile := readEnvFile()
if err := fsys.Init(base.Cwd()); err != nil {
base.Fatalf("go: %v", err)
@ -290,13 +293,13 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
if *envJson {
var es []cfg.EnvVar
for _, name := range args {
e := cfg.EnvVar{Name: name, Value: findEnv(env, envFile, name)}
e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
es = append(es, e)
}
printEnvAsJSON(es)
} else {
for _, name := range args {
fmt.Printf("%s\n", findEnv(env, envFile, name))
fmt.Printf("%s\n", findEnv(env, name))
}
}
return
@ -596,6 +599,7 @@ func readEnvFile() map[string]string {
lines := readEnvFileLines(false)
m := make(map[string]string)
for _, line := range lines {
line = strings.TrimRight(line, "\r\n")
key := lineToKey(line)
if key == "" {
continue

View File

@ -1,14 +1,27 @@
# Plain go version
go version
! stdout go1\.999
# Default should be auto
env GOTOOLCHAIN=
go env GOTOOLCHAIN
stdout auto
go env
stdout GOTOOLCHAIN=.?auto.?
# GOTOOLCHAIN from network, does not exist
env GOTOOLCHAIN=go1.9999x
! go version
stderr 'go: download go1.9999x for .*: toolchain not available'
[short] skip
env GOTOOLCHAIN=
mkdir $WORK/bin
[!GOOS:plan9] env PATH=$WORK/bin${:}$PATH
[GOOS:plan9] env path=$WORK/bin${:}$path
go build -o $WORK/bin/ ./go1.999testpath.go # adds .exe extension implicitly on Windows
# Plain go version
go version
! stdout go1\.999
# GOTOOLCHAIN from PATH
env GOTOOLCHAIN=go1.999testpath
go version
@ -21,11 +34,6 @@ go version
stdout 'go1.999testpath here!'
env GODEBUG=
# GOTOOLCHAIN from network, does not exist
env GOTOOLCHAIN=go1.9999x
! go version
stderr 'go: download go1.9999x for .*: toolchain not available'
# GOTOOLCHAIN from network
[!exec:/bin/sh] stop 'the fake proxy serves shell scripts instead of binaries'
env GOTOOLCHAIN=go1.999testmod