golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/watchflakes/internal/cache/cache.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package cache implements a simple file-based cache. 6 package cache 7 8 import ( 9 "fmt" 10 "io" 11 "os" 12 "path/filepath" 13 "time" 14 ) 15 16 // A Cache is a directory holding cached data. 17 type Cache struct { 18 dir string 19 disabled bool 20 } 21 22 // Disabled returns a Cache that is always empty. 23 // Reads always return no result, and writes succeed but are discarded. 24 func Disabled() *Cache { 25 return &Cache{disabled: true} 26 } 27 28 // Create returns a cache using the named subdirectory 29 // of the user's cache directory. 30 // For example, on macOS, Create("myprog") uses $HOME/Library/Caches/myprog. 31 // Create creates the directory if it does not already exist. 32 func Create(name string) (*Cache, error) { 33 dir, err := os.UserCacheDir() 34 if err != nil { 35 return nil, err 36 } 37 dir = filepath.Join(dir, name) 38 if err := os.MkdirAll(dir, 0777); err != nil { 39 return nil, err 40 } 41 return &Cache{dir: dir}, nil 42 } 43 44 // Read reads the file with the given name in the cache. 45 // It returns the file content, its last modification time, 46 // and any error encountered. 47 // If the file does not exist in the cache, Read returns nil, time.Time{}, nil. 48 func (c *Cache) Read(name string) ([]byte, time.Time, error) { 49 if c.disabled { 50 return nil, time.Time{}, nil 51 } 52 if c.dir == "" { 53 return nil, time.Time{}, fmt.Errorf("use of zero Cache") 54 } 55 f, err := os.Open(filepath.Join(c.dir, name)) 56 if err != nil { 57 if os.IsNotExist(err) { 58 err = nil 59 } 60 return nil, time.Time{}, err 61 } 62 defer f.Close() 63 info, err := f.Stat() 64 if err != nil { 65 return nil, time.Time{}, err 66 } 67 data, err := io.ReadAll(f) 68 if err != nil { 69 return nil, time.Time{}, err 70 } 71 return data, info.ModTime(), nil 72 } 73 74 // Write writes data to the file with the given name in the cache. 75 func (c *Cache) Write(name string, data []byte) error { 76 if c.disabled { 77 return nil 78 } 79 if c.dir == "" { 80 return fmt.Errorf("use of zero Cache") 81 } 82 return os.WriteFile(filepath.Join(c.dir, name), data, 0666) 83 }