Currently, if computing of the go cache directory fails it does not expose the error. Commands like go clean, exec, modindex that use go cache directory continue execution producing incorrect or no result. This patch adds an error to the return values such that it can be validated on call sites. It also introduces such validation in go clean -cache command to fail execution in case when error occurred.
Fixes #69997
Change-Id: I53fd1ec67f0a6bd8a367e785dcb145a673c084dc
GitHub-Last-Rev:
e2063d10db7bb969bcbc8993761e3b38bb420938
GitHub-Pull-Request: golang/go#70392
Reviewed-on: https://go-review.googlesource.com/c/go/+/628596
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Matloob <matloob@golang.org>
// The directory where 'go install' will install a command.
// GOCACHE
// The directory where the go command will store cached
-// information for reuse in future builds.
+// information for reuse in future builds. Must be an absolute path.
// GOCACHEPROG
// A command (with optional space-separated flags) that implements an
// external go command build cache.
defer removeAll(testTmpDir)
}
- testGOCACHE, _ = cache.DefaultDir()
+ testGOCACHE, _, _ = cache.DefaultDir()
if testenv.HasGoBuild() {
testBin = filepath.Join(testTmpDir, "testbin")
if err := os.Mkdir(testBin, 0777); err != nil {
// initDefaultCache does the work of finding the default cache
// the first time Default is called.
func initDefaultCache() Cache {
- dir, _ := DefaultDir()
+ dir, _, err := DefaultDir()
+ if err != nil {
+ base.Fatalf("build cache is required, but could not be located: %v", err)
+ }
if dir == "off" {
- if defaultDirErr != nil {
- base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr)
- }
base.Fatalf("build cache is disabled by GOCACHE=off, but required as of Go 1.12")
}
if err := os.MkdirAll(dir, 0o777); err != nil {
// DefaultDir returns the effective GOCACHE setting.
// It returns "off" if the cache is disabled,
// and reports whether the effective value differs from GOCACHE.
-func DefaultDir() (string, bool) {
+func DefaultDir() (string, bool, error) {
// Save the result of the first call to DefaultDir for later use in
// initDefaultCache. cmd/go/main.go explicitly sets GOCACHE so that
// subprocesses will inherit it, but that means initDefaultCache can't
defaultDir = filepath.Join(dir, "go-build")
})
- return defaultDir, defaultDirChanged
+ return defaultDir, defaultDirChanged, defaultDirErr
}
sh := work.NewShell("", &load.TextPrinter{Writer: os.Stdout})
if cleanCache {
- dir, _ := cache.DefaultDir()
+ dir, _, err := cache.DefaultDir()
+ if err != nil {
+ base.Fatal(err)
+ }
if dir != "off" {
// Remove the cache subdirectories but not the top cache directory.
// The top cache directory may have been created with special permissions
// Instead of walking through the entire cache looking for test results,
// we write a file to the cache indicating that all test results from before
// right now are to be ignored.
- dir, _ := cache.DefaultDir()
+ dir, _, err := cache.DefaultDir()
+ if err != nil {
+ base.Fatal(err)
+ }
if dir != "off" {
f, err := lockedfile.Edit(filepath.Join(dir, "testexpire.txt"))
if err == nil {
env[i].Changed = true
}
case "GOCACHE":
- env[i].Value, env[i].Changed = cache.DefaultDir()
+ env[i].Value, env[i].Changed, _ = cache.DefaultDir()
case "GOTOOLCHAIN":
env[i].Value, env[i].Changed = cfg.EnvOrAndChanged("GOTOOLCHAIN", "")
case "GODEBUG":
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
- information for reuse in future builds.
+ information for reuse in future builds. Must be an absolute path.
GOCACHEPROG
A command (with optional space-separated flags) that implements an
external go command build cache.
// using the index, for instance because the index is disabled, or the package
// is not in a module.
func GetModule(modroot string) (*Module, error) {
- dir, _ := cache.DefaultDir()
+ dir, _, _ := cache.DefaultDir()
if !enabled || dir == "off" {
return nil, errDisabled
}
// Read testcache expiration time, if present.
// (We implement go clean -testcache by writing an expiration date
// instead of searching out and deleting test result cache entries.)
- if dir, _ := cache.DefaultDir(); dir != "off" {
+ if dir, _, _ := cache.DefaultDir(); dir != "off" {
if data, _ := lockedfile.Read(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' {
if t, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64); err == nil {
testCacheExpire = time.Unix(0, t)
// Otherwise fall back to standard copy.
// If the source is in the build cache, we need to copy it.
- dir, _ := cache.DefaultDir()
+ dir, _, _ := cache.DefaultDir()
if strings.HasPrefix(src, dir) {
return sh.CopyFile(dst, src, perm, force)
}
! go clean -cache .
stderr 'go: clean -cache cannot be used with package arguments'
+# GOCACHE must be an absolute path.
+env GOCACHE=.
+! go clean -cache
+stderr 'go: GOCACHE is not an absolute path'
+
-- main.go --
package main