github.com/evanw/esbuild@v0.21.4/internal/cache/cache_fs.go (about)

     1  package cache
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/evanw/esbuild/internal/fs"
     7  )
     8  
     9  // This cache uses information from the "stat" syscall to try to avoid re-
    10  // reading files from the file system during subsequent builds if the file
    11  // hasn't changed. The assumption is reading the file metadata is faster than
    12  // reading the file contents.
    13  
    14  type FSCache struct {
    15  	entries map[string]*fsEntry
    16  	mutex   sync.Mutex
    17  }
    18  
    19  type fsEntry struct {
    20  	contents       string
    21  	modKey         fs.ModKey
    22  	isModKeyUsable bool
    23  }
    24  
    25  func (c *FSCache) ReadFile(fs fs.FS, path string) (contents string, canonicalError error, originalError error) {
    26  	entry := func() *fsEntry {
    27  		c.mutex.Lock()
    28  		defer c.mutex.Unlock()
    29  		return c.entries[path]
    30  	}()
    31  
    32  	// If the file's modification key hasn't changed since it was cached, assume
    33  	// the contents of the file are also the same and skip reading the file.
    34  	modKey, modKeyErr := fs.ModKey(path)
    35  	if entry != nil && entry.isModKeyUsable && modKeyErr == nil && entry.modKey == modKey {
    36  		return entry.contents, nil, nil
    37  	}
    38  
    39  	contents, err, originalError := fs.ReadFile(path)
    40  	if err != nil {
    41  		return "", err, originalError
    42  	}
    43  
    44  	c.mutex.Lock()
    45  	defer c.mutex.Unlock()
    46  	c.entries[path] = &fsEntry{
    47  		contents:       contents,
    48  		modKey:         modKey,
    49  		isModKeyUsable: modKeyErr == nil,
    50  	}
    51  	return contents, nil, nil
    52  }