// OutputFile returns the name of the cache file storing output with the given OutputID.
func (c *DiskCache) OutputFile(out OutputID) string {
file := c.fileName(out, "d")
- isExecutable := c.markUsed(file)
- if isExecutable {
+ isDir := c.markUsed(file)
+ if isDir { // => cached executable
entries, err := os.ReadDir(file)
if err != nil {
return fmt.Sprintf("DO NOT USE - missing binary cache entry: %v", err)
// while still keeping the mtimes useful for cache trimming.
//
// markUsed reports whether the file is a directory (an executable cache entry).
-func (c *DiskCache) markUsed(file string) (isExecutable bool) {
+func (c *DiskCache) markUsed(file string) (isDir bool) {
info, err := os.Stat(file)
- if err == nil && c.now().Sub(info.ModTime()) < mtimeInterval {
- return info.IsDir()
+ if err != nil {
+ return false
+ }
+ if now := c.now(); now.Sub(info.ModTime()) >= mtimeInterval {
+ os.Chtimes(file, now, now)
}
- os.Chtimes(file, c.now(), c.now())
return info.IsDir()
}
--- /dev/null
+# Test that the go command does not panic if it tries to read
+# a file from the cache that has an index entry, but is missing
+# an entry for the output. This test creates that situation by
+# running a go list (creating index and output cache entries for
+# the module index) and then removing just the output entries.
+
+[short] skip 'runs go build'
+
+go build -o roe$GOEXE ./remove_output_entries.go
+
+# populate new cache
+env GOCACHE=$WORK/newcache
+go list runtime
+
+# remove output entries and check the panic doesn't happen
+exec ./roe$GOEXE $WORK/newcache
+go list runtime
+
+-- remove_output_entries.go --
+package main
+
+import (
+ "io/fs"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func main() {
+ cachedir := os.Args[1]
+ err := filepath.WalkDir(cachedir, func(path string, d fs.DirEntry, err error) error {
+ if strings.HasSuffix(path, "-d") { // output entries end in "-d"
+ if err := os.RemoveAll(path); err != nil {
+ return err
+ }
+ }
+ return nil
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+}
\ No newline at end of file