cmd/go/internal/modfetch: quiet read-only filesystem stat cache warnings

When stat cache updates fail due to read-only filesystems (such as
gomodfs), don't log the warning. It's harmless and not worth the spam.

Change-Id: I337b41e1958da89d904495fec6d61240c024da44
Reviewed-on: https://go-review.googlesource.com/c/go/+/750700
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Matloob <matloob@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Brad Fitzpatrick
2026-03-03 17:58:47 +00:00
parent b764d47e4d
commit 21c9de8c1d
2 changed files with 53 additions and 2 deletions

View File

@@ -15,9 +15,11 @@ import (
"math/rand"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
@@ -264,7 +266,7 @@ func (r *cachingRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
})
}
if err := writeDiskStat(ctx, file, info); err != nil {
if err := writeDiskStat(ctx, file, info); err != nil && !isErrReadOnlyFS(err) {
fmt.Fprintf(os.Stderr, "go: writing stat cache: %v\n", err)
}
}
@@ -321,7 +323,7 @@ func (r *cachingRepo) GoMod(ctx context.Context, version string) ([]byte, error)
if err := checkGoMod(r.fetcher, r.path, version, text); err != nil {
return text, err
}
if err := writeDiskGoMod(ctx, file, text); err != nil {
if err := writeDiskGoMod(ctx, file, text); err != nil && !isErrReadOnlyFS(err) {
fmt.Fprintf(os.Stderr, "go: writing go.mod cache: %v\n", err)
}
}
@@ -690,6 +692,24 @@ func writeDiskCache(ctx context.Context, file string, data []byte) error {
return nil
}
// isErrReadOnlyFS reports whether err is a read-only filesystem error
// (syscall.EROFS on Unix/wasip1, ERROR_NOT_SUPPORTED on Windows).
func isErrReadOnlyFS(err error) bool {
switch runtime.GOOS {
case "plan9":
return false
case "windows":
const ERROR_NOT_SUPPORTED = 50
return errors.Is(err, syscall.Errno(ERROR_NOT_SUPPORTED))
case "wasip1":
const EROFS = 69
return errors.Is(err, syscall.Errno(EROFS))
default: // unix and js
const EROFS = 30
return errors.Is(err, syscall.Errno(EROFS))
}
}
// tempFile creates a new temporary file with given permission bits.
func tempFile(ctx context.Context, dir, prefix string, perm fs.FileMode) (f *os.File, err error) {
for i := 0; i < 10000; i++ {

View File

@@ -0,0 +1,31 @@
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !plan9 && !windows
package modfetch
import (
"fmt"
"syscall"
"testing"
)
func TestIsErrReadOnlyFS(t *testing.T) {
if isErrReadOnlyFS(nil) {
t.Error("isErrReadOnlyFS(nil) = true, want false")
}
if isErrReadOnlyFS(fmt.Errorf("some error")) {
t.Error("isErrReadOnlyFS(non-EROFS) = true, want false")
}
if !isErrReadOnlyFS(syscall.EROFS) {
t.Error("isErrReadOnlyFS(syscall.EROFS) = false, want true")
}
if !isErrReadOnlyFS(fmt.Errorf("wrapped: %w", syscall.EROFS)) {
t.Error("isErrReadOnlyFS(wrapped EROFS) = false, want true")
}
if isErrReadOnlyFS(syscall.EACCES) {
t.Error("isErrReadOnlyFS(syscall.EACCES) = true, want false")
}
}