mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-18 14:34:52 +02:00
Make the paths returned by DiskCache stable even if the parent entry is removed/pruned for the life of the process
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user