Skip to content

Commit

Permalink
md/go: fail go clean command when failed to find go cache directory
Browse files Browse the repository at this point in the history
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 golang#69997
  • Loading branch information
mneverov committed Nov 16, 2024
1 parent d0631b9 commit 69a6fb5
Show file tree
Hide file tree
Showing 9 changed files with 18 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/cmd/go/alldocs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cmd/go/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/go/internal/cache/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ 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, _, _ := DefaultDir()
if dir == "off" {
if defaultDirErr != nil {
base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr)
Expand Down Expand Up @@ -72,7 +72,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
Expand Down Expand Up @@ -101,5 +101,5 @@ func DefaultDir() (string, bool) {
defaultDir = filepath.Join(dir, "go-build")
})

return defaultDir, defaultDirChanged
return defaultDir, defaultDirChanged, defaultDirErr
}
10 changes: 8 additions & 2 deletions src/cmd/go/internal/clean/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
sh := work.NewShell("", fmt.Print)

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
Expand All @@ -180,7 +183,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 {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/envcmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,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":
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/help/helpdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ General-purpose environment variables:
GOBIN
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
The absolute path to the directory where the go command will store cached
information for reuse in future builds.
GOMODCACHE
The directory where the go command will store downloaded modules.
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/modindex/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,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
}
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,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)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/work/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,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)
}
Expand Down

0 comments on commit 69a6fb5

Please sign in to comment.