cmd/go: if unable to initialize cache, just disable it

Fixes #23638

Change-Id: I51967290448217f371fc7aba9259918ee9857143
Reviewed-on: https://go-review.googlesource.com/91097
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 0838482..b2053f5 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -5373,6 +5373,26 @@
 	}
 }
 
+func TestNoCache(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("no unwritable directories on %s", runtime.GOOS)
+	}
+	if os.Getuid() == 0 {
+		t.Skip("skipping test because running as root")
+	}
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.parallel()
+	tg.tempFile("triv.go", `package main; func main() {}`)
+	tg.must(os.MkdirAll(tg.path("unwritable"), 0555))
+	tg.setenv("HOME", tg.path(filepath.Join("unwritable", "home")))
+	tg.unsetenv("GOCACHE")
+	tg.run("build", "-o", tg.path("triv"), tg.path("triv.go"))
+	tg.grepStderr("disabling cache", "did not disable cache")
+}
+
 func TestTestVet(t *testing.T) {
 	tooSlow(t)
 	tg := testgo(t)
diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go
index 8285f78..9728376 100644
--- a/src/cmd/go/internal/cache/default.go
+++ b/src/cmd/go/internal/cache/default.go
@@ -5,7 +5,7 @@
 package cache
 
 import (
-	"cmd/go/internal/base"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -40,7 +40,8 @@
 		return
 	}
 	if err := os.MkdirAll(dir, 0777); err != nil {
-		base.Fatalf("initializing cache in $GOCACHE: %s", err)
+		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 {
 		// Best effort.
@@ -49,7 +50,8 @@
 
 	c, err := Open(dir)
 	if err != nil {
-		base.Fatalf("initializing cache in $GOCACHE: %s", err)
+		fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
+		return
 	}
 	defaultCache = c
 }