diff --git a/tools/disk_cache/api.go b/tools/disk_cache/api.go index 33adc4594..8a7614b85 100644 --- a/tools/disk_cache/api.go +++ b/tools/disk_cache/api.go @@ -1,15 +1,10 @@ package disk_cache import ( - "crypto/sha256" - "encoding/hex" "fmt" "os" - "path/filepath" "sync" "time" - - "github.com/kovidgoyal/kitty/tools/utils" ) var _ = fmt.Print @@ -34,35 +29,15 @@ type DiskCache struct { entries Metadata entry_map map[string]*Entry entries_mod_time time.Time + get_dir string } func NewDiskCache(path string, max_size int64) (dc *DiskCache, err error) { - if path, err = filepath.Abs(path); err != nil { - return - } - if err = os.MkdirAll(path, 0o700); err != nil { - return - } - dc = &DiskCache{Path: path, MaxSize: max_size} - err = dc.prune() - return + return new_disk_cache(path, max_size) } func KeyForPath(path string) (key string, err error) { - if path, err = filepath.EvalSymlinks(path); err != nil { - return - } - if path, err = filepath.Abs(path); err != nil { - return - } - - s, err := os.Stat(path) - if err != nil { - return - } - data := fmt.Sprintf("%s\x00%d\x00%d", path, s.Size(), s.ModTime().UnixNano()) - sum := sha256.Sum256(utils.UnsafeStringToBytes(data)) - return hex.EncodeToString(sum[:]), nil + return key_for_path(path) } func (dc *DiskCache) Get(key string, items ...string) map[string]string { diff --git a/tools/disk_cache/implementation.go b/tools/disk_cache/implementation.go index e989839d3..d6d2bf92d 100644 --- a/tools/disk_cache/implementation.go +++ b/tools/disk_cache/implementation.go @@ -1,7 +1,8 @@ package disk_cache import ( - "bytes" + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "os" @@ -14,6 +15,43 @@ import ( var _ = fmt.Print +func new_disk_cache(path string, max_size int64) (dc *DiskCache, err error) { + if path, err = filepath.Abs(path); err != nil { + return + } + if err = os.MkdirAll(path, 0o700); err != nil { + return + } + dc = &DiskCache{Path: path, MaxSize: max_size} + dc.lock() + defer dc.unlock() + if err = dc.prune(); err != nil { + return + } + if dc.get_dir, err = os.MkdirTemp(dc.Path, "getdir-*"); err != nil { + return + } + err = utils.AtExitRmtree(dc.get_dir) + return +} + +func key_for_path(path string) (key string, err error) { + if path, err = filepath.EvalSymlinks(path); err != nil { + return + } + if path, err = filepath.Abs(path); err != nil { + return + } + + s, err := os.Stat(path) + if err != nil { + return + } + data := fmt.Sprintf("%s\x00%d\x00%d", path, s.Size(), s.ModTime().UnixNano()) + sum := sha256.Sum256(utils.UnsafeStringToBytes(data)) + return hex.EncodeToString(sum[:]), nil +} + func (dc *DiskCache) lock() (err error) { dc.lock_mutex.Lock() defer dc.lock_mutex.Unlock() @@ -141,7 +179,16 @@ func (dc *DiskCache) get(key string, items []string) map[string]string { if s, err := os.Stat(p); err != nil || s.IsDir() { continue } - ans[x] = p + dest := filepath.Join(dc.get_dir, key+"-"+x) + if err := os.Link(p, dest); err != nil { + os.Remove(dest) + if err := os.Link(p, dest); err != nil { + dest = "" + } + } + if dest != "" { + ans[x] = dest + } } dc.update_last_used(key) return ans @@ -240,7 +287,7 @@ func (dc *DiskCache) add(key string, items map[string][]byte) (err error) { } changed -= before } else { - if err = utils.AtomicWriteFile(p, bytes.NewReader(data), 0o700); err != nil { + if err = os.WriteFile(p, data, 0o700); err != nil { return } changed += int64(len(data)) - before