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  }