From 0c319ee4fe655e3c8e7bf72bce572c989f565a53 Mon Sep 17 00:00:00 2001 From: Zev Goldstein Date: Sun, 8 Jul 2018 22:31:28 -0400 Subject: [PATCH] cmd/go/internal/cache: squelch cache init warnings when $HOME is / Docker sets $HOME to / when running with a UID that doesn't exist within the container. This not uncommon on CI servers. Fixes #26280 Change-Id: Ic7ff62b41403fe6e7c0cef12814667ef73f6c954 Reviewed-on: https://go-review.googlesource.com/122487 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/cache/default.go | 37 +++++++--- .../go/internal/cache/default_unix_test.go | 67 +++++++++++++++++++ 2 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 src/cmd/go/internal/cache/default_unix_test.go diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go index 9728376225..02fc1e896f 100644 --- a/src/cmd/go/internal/cache/default.go +++ b/src/cmd/go/internal/cache/default.go @@ -35,12 +35,14 @@ See golang.org to learn more about Go. // initDefaultCache does the work of finding the default cache // the first time Default is called. func initDefaultCache() { - dir := DefaultDir() + dir, showWarnings := defaultDir() if dir == "off" { return } if err := os.MkdirAll(dir, 0777); err != nil { - fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + if showWarnings { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + } return } if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { @@ -50,7 +52,9 @@ func initDefaultCache() { c, err := Open(dir) if err != nil { - fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + if showWarnings { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + } return } defaultCache = c @@ -59,14 +63,24 @@ func initDefaultCache() { // DefaultDir returns the effective GOCACHE setting. // It returns "off" if the cache is disabled. func DefaultDir() string { + dir, _ := defaultDir() + return dir +} + +// defaultDir returns the effective GOCACHE setting. +// It returns "off" if the cache is disabled. +// The second return value reports whether warnings should +// be shown if the cache fails to initialize. +func defaultDir() (string, bool) { dir := os.Getenv("GOCACHE") if dir != "" { - return dir + return dir, true } // Compute default location. // TODO(rsc): This code belongs somewhere else, // like maybe ioutil.CacheDir or os.CacheDir. + showWarnings := true switch runtime.GOOS { case "windows": dir = os.Getenv("LocalAppData") @@ -76,20 +90,20 @@ func DefaultDir() string { dir = os.Getenv("AppData") } if dir == "" { - return "off" + return "off", true } case "darwin": dir = os.Getenv("HOME") if dir == "" { - return "off" + return "off", true } dir += "/Library/Caches" case "plan9": dir = os.Getenv("home") if dir == "" { - return "off" + return "off", true } // Plan 9 has no established per-user cache directory, // but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix. @@ -101,10 +115,15 @@ func DefaultDir() string { if dir == "" { dir = os.Getenv("HOME") if dir == "" { - return "off" + return "off", true + } + if dir == "/" { + // probably docker run with -u flag + // https://golang.org/issue/26280 + showWarnings = false } dir += "/.cache" } } - return filepath.Join(dir, "go-build") + return filepath.Join(dir, "go-build"), showWarnings } diff --git a/src/cmd/go/internal/cache/default_unix_test.go b/src/cmd/go/internal/cache/default_unix_test.go new file mode 100644 index 0000000000..a207497a42 --- /dev/null +++ b/src/cmd/go/internal/cache/default_unix_test.go @@ -0,0 +1,67 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !windows,!darwin,!plan9 + +package cache + +import ( + "os" + "strings" + "testing" +) + +func TestDefaultDir(t *testing.T) { + goCacheDir := "/tmp/test-go-cache" + xdgCacheDir := "/tmp/test-xdg-cache" + homeDir := "/tmp/test-home" + + // undo env changes when finished + defer func(GOCACHE, XDG_CACHE_HOME, HOME string) { + os.Setenv("GOCACHE", GOCACHE) + os.Setenv("XDG_CACHE_HOME", XDG_CACHE_HOME) + os.Setenv("HOME", HOME) + }(os.Getenv("GOCACHE"), os.Getenv("XDG_CACHE_HOME"), os.Getenv("HOME")) + + os.Setenv("GOCACHE", goCacheDir) + os.Setenv("XDG_CACHE_HOME", xdgCacheDir) + os.Setenv("HOME", homeDir) + + dir, showWarnings := defaultDir() + if dir != goCacheDir { + t.Errorf("Cache DefaultDir %q should be $GOCACHE %q", dir, goCacheDir) + } + if !showWarnings { + t.Error("Warnings should be shown when $GOCACHE is set") + } + + os.Unsetenv("GOCACHE") + dir, showWarnings = defaultDir() + if !strings.HasPrefix(dir, xdgCacheDir+"/") { + t.Errorf("Cache DefaultDir %q should be under $XDG_CACHE_HOME %q when $GOCACHE is unset", dir, xdgCacheDir) + } + if !showWarnings { + t.Error("Warnings should be shown when $XDG_CACHE_HOME is set") + } + + os.Unsetenv("XDG_CACHE_HOME") + dir, showWarnings = defaultDir() + if !strings.HasPrefix(dir, homeDir+"/.cache/") { + t.Errorf("Cache DefaultDir %q should be under $HOME/.cache %q when $GOCACHE and $XDG_CACHE_HOME are unset", dir, homeDir+"/.cache") + } + if !showWarnings { + t.Error("Warnings should be shown when $HOME is not /") + } + + os.Unsetenv("HOME") + if dir, _ := defaultDir(); dir != "off" { + t.Error("Cache not disabled when $GOCACHE, $XDG_CACHE_HOME, and $HOME are unset") + } + + os.Setenv("HOME", "/") + if _, showWarnings := defaultDir(); showWarnings { + // https://golang.org/issue/26280 + t.Error("Cache initalization warnings should be squelched when $GOCACHE and $XDG_CACHE_HOME are unset and $HOME is /") + } +}