]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: fail go clean command when failed to find go cache directory
authorMax Neverov <neverov.max@gmail.com>
Tue, 18 Mar 2025 20:02:03 +0000 (20:02 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 20 Mar 2025 16:05:13 +0000 (09:05 -0700)
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>

src/cmd/go/alldocs.go
src/cmd/go/go_test.go
src/cmd/go/internal/cache/default.go
src/cmd/go/internal/clean/clean.go
src/cmd/go/internal/envcmd/env.go
src/cmd/go/internal/help/helpdoc.go
src/cmd/go/internal/modindex/read.go
src/cmd/go/internal/test/test.go
src/cmd/go/internal/work/shell.go
src/cmd/go/testdata/script/clean_cache_n.txt

index 7063a9f216f07c203d444424a3a019a2f0136b1c..ace9899250b44361da9840fa332a5c4525327710 100644 (file)
 //             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.
index 84e4b7abea9cf120f3ad57bb12d43ef1b39a8798..83323aeaad0e759ad21aa5dace71e342b11c0ba8 100644 (file)
@@ -197,7 +197,7 @@ func TestMain(m *testing.M) {
                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 {
index f8e5696cbd1e844a91296c8492594ed095e68025..eec2be9fa0a5f611c7b9154f0c3160beeec5017c 100644 (file)
@@ -34,11 +34,11 @@ 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() 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 {
@@ -71,7 +71,7 @@ var (
 // 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
@@ -100,5 +100,5 @@ func DefaultDir() (string, bool) {
                defaultDir = filepath.Join(dir, "go-build")
        })
 
-       return defaultDir, defaultDirChanged
+       return defaultDir, defaultDirChanged, defaultDirErr
 }
index 18c5ae23fcd814a32989a1c78b88c4d81ce86a19..63e2dfdbc7a783ef2570ef5c061cfd6777578309 100644 (file)
@@ -155,7 +155,10 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
        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
@@ -182,7 +185,10 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
                // 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 {
index f0a6989a579ccd4820f52a7caad3c32a63a9995f..b60e2adbe51611f6bafd349d0ea04f5ce593f7ed 100644 (file)
@@ -131,7 +131,7 @@ func MkEnv() []cfg.EnvVar {
                                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":
index e08b8c7a5ad57ad28a2ef622dd5fa03750f0397e..6101a45829931b6ff074371376ffa8aa0c3bcd0f 100644 (file)
@@ -507,7 +507,7 @@ General-purpose environment variables:
                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.
index 913f49994f28e6adfe78d38ec9da2510a5be5a92..d87fb06b57e173083bbd754df7e0cf1bf66b3312 100644 (file)
@@ -156,7 +156,7 @@ func GetPackage(modroot, pkgdir string) (*IndexPackage, error) {
 // 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
        }
index b842c2f48ecabdcc9d081d933786c3c4913f96dc..6c4a6a574d10efb9992b4dbe86736a6bec2b0eeb 100644 (file)
@@ -840,7 +840,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
        // 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)
index dd5a31c60668d8988edf52cb62ed38ea3f88f461..2604b074da9f73623665af925a0832ec129ebf55 100644 (file)
@@ -127,7 +127,7 @@ func (sh *Shell) moveOrCopyFile(dst, src string, perm fs.FileMode, force bool) e
        // 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)
        }
index b93134e6bb4db3dd8ab26efd3a1559b204c1d126..8ac9befa5b8036cd46bc9aecfa9b618c61322b8f 100644 (file)
@@ -20,6 +20,11 @@ go clean -cache
 ! 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