Skip to content

Commit 51a47b7

Browse files
committed
cmd/go: display helpful error when module cache can't be created
Previously when the module cache specified by GOMODCACHE could not be created an unhelpful message would be printed multiple times. This happened because we were fetching several things in parallel then failing to write them because we can't create the module cache. We now check if the module cache can be created before fetching. If not, the following message is printed: go: could not create module cache Fixes #45113 Change-Id: Ic9cec787411335edc7f4d0614fde7eaa8a957fb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/304571 Trust: Julie Qiu <[email protected]> Run-TryBot: Julie Qiu <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 117b1c8 commit 51a47b7

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/cmd/go/internal/modfetch/cache.go

+32-2
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ func GoMod(path, rev string) ([]byte, error) {
347347
if _, info, err := readDiskStat(path, rev); err == nil {
348348
rev = info.Version
349349
} else {
350+
if errors.Is(err, statCacheErr) {
351+
return nil, err
352+
}
350353
err := TryProxies(func(proxy string) error {
351354
info, err := Lookup(proxy, path).Stat(rev)
352355
if err == nil {
@@ -706,15 +709,42 @@ func rewriteVersionList(dir string) (err error) {
706709
return nil
707710
}
708711

712+
var (
713+
statCacheOnce sync.Once
714+
statCacheErr error
715+
)
716+
717+
// checkCacheDir checks if the directory specified by GOMODCACHE exists. An
718+
// error is returned if it does not.
709719
func checkCacheDir() error {
710720
if cfg.GOMODCACHE == "" {
711721
// modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
712722
// is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
713723
return fmt.Errorf("internal error: cfg.GOMODCACHE not set")
714724
}
715-
716725
if !filepath.IsAbs(cfg.GOMODCACHE) {
717726
return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE)
718727
}
719-
return nil
728+
729+
// os.Stat is slow on Windows, so we only call it once to prevent unnecessary
730+
// I/O every time this function is called.
731+
statCacheOnce.Do(func() {
732+
fi, err := os.Stat(cfg.GOMODCACHE)
733+
if err != nil {
734+
if !os.IsNotExist(err) {
735+
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
736+
return
737+
}
738+
if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil {
739+
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
740+
return
741+
}
742+
return
743+
}
744+
if !fi.IsDir() {
745+
statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE)
746+
return
747+
}
748+
})
749+
return statCacheErr
720750
}

src/cmd/go/testdata/script/mod_gomodcache.txt

+7
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ env GOMODCACHE=$WORK/modcache
4747
go mod download rsc.io/[email protected]
4848
exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info
4949

50+
# Test error when cannot create GOMODCACHE directory
51+
env GOMODCACHE=$WORK/modcachefile
52+
! go install example.com/cmd/[email protected]
53+
stderr 'go: could not create module cache'
54+
5055
# Test that the following work even with GO111MODULE=off
5156
env GO111MODULE=off
5257

@@ -58,3 +63,5 @@ go clean -modcache
5863

5964
-- go.mod --
6065
module m
66+
67+
-- $WORK/modcachefile --

0 commit comments

Comments
 (0)