Skip to content

Commit

Permalink
cmd/go: display helpful error when module cache can't be created
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
julieqiu committed Apr 12, 2021
1 parent 117b1c8 commit 51a47b7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/cmd/go/internal/modfetch/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ func GoMod(path, rev string) ([]byte, error) {
if _, info, err := readDiskStat(path, rev); err == nil {
rev = info.Version
} else {
if errors.Is(err, statCacheErr) {
return nil, err
}
err := TryProxies(func(proxy string) error {
info, err := Lookup(proxy, path).Stat(rev)
if err == nil {
Expand Down Expand Up @@ -706,15 +709,42 @@ func rewriteVersionList(dir string) (err error) {
return nil
}

var (
statCacheOnce sync.Once
statCacheErr error
)

// checkCacheDir checks if the directory specified by GOMODCACHE exists. An
// error is returned if it does not.
func checkCacheDir() error {
if cfg.GOMODCACHE == "" {
// modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
// is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
return fmt.Errorf("internal error: cfg.GOMODCACHE not set")
}

if !filepath.IsAbs(cfg.GOMODCACHE) {
return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE)
}
return nil

// os.Stat is slow on Windows, so we only call it once to prevent unnecessary
// I/O every time this function is called.
statCacheOnce.Do(func() {
fi, err := os.Stat(cfg.GOMODCACHE)
if err != nil {
if !os.IsNotExist(err) {
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
return
}
if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil {
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
return
}
return
}
if !fi.IsDir() {
statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE)
return
}
})
return statCacheErr
}
7 changes: 7 additions & 0 deletions src/cmd/go/testdata/script/mod_gomodcache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ env GOMODCACHE=$WORK/modcache
go mod download rsc.io/[email protected]
exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info

# Test error when cannot create GOMODCACHE directory
env GOMODCACHE=$WORK/modcachefile
! go install example.com/cmd/[email protected]
stderr 'go: could not create module cache'

# Test that the following work even with GO111MODULE=off
env GO111MODULE=off

Expand All @@ -58,3 +63,5 @@ go clean -modcache

-- go.mod --
module m

-- $WORK/modcachefile --

0 comments on commit 51a47b7

Please sign in to comment.