forked from git-lfs/git-lfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
103 lines (89 loc) · 2.21 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package locking
import (
"strings"
"github.com/git-lfs/git-lfs/tools/kv"
)
const (
// We want to use a single cache file for integrity, but to make it easy to
// list all locks, prefix the id->path map in a way we can identify (something
// that won't be in a path)
idKeyPrefix string = "*id*://"
)
type LockCache struct {
kv *kv.Store
}
func NewLockCache(filepath string) (*LockCache, error) {
kv, err := kv.NewStore(filepath)
if err != nil {
return nil, err
}
return &LockCache{kv}, nil
}
// Cache a successful lock for faster local lookup later
func (c *LockCache) Add(l Lock) error {
// Store reference in both directions
// Path -> Lock
c.kv.Set(l.Path, &l)
// EncodedId -> Lock (encoded so we can easily identify)
c.kv.Set(c.encodeIdKey(l.Id), &l)
return nil
}
// Remove a cached lock by path becuase it's been relinquished
func (c *LockCache) RemoveByPath(filePath string) error {
ilock := c.kv.Get(filePath)
if lock, ok := ilock.(*Lock); ok && lock != nil {
c.kv.Remove(lock.Path)
// Id as key is encoded
c.kv.Remove(c.encodeIdKey(lock.Id))
}
return nil
}
// Remove a cached lock by id because it's been relinquished
func (c *LockCache) RemoveById(id string) error {
// Id as key is encoded
idkey := c.encodeIdKey(id)
ilock := c.kv.Get(idkey)
if lock, ok := ilock.(*Lock); ok && lock != nil {
c.kv.Remove(idkey)
c.kv.Remove(lock.Path)
}
return nil
}
// Get the list of cached locked files
func (c *LockCache) Locks() []Lock {
var locks []Lock
c.kv.Visit(func(key string, val interface{}) bool {
// Only report file->id entries not reverse
if !c.isIdKey(key) {
lock := val.(*Lock)
locks = append(locks, *lock)
}
return true // continue
})
return locks
}
// Clear the cache
func (c *LockCache) Clear() {
c.kv.RemoveAll()
}
// Save the cache
func (c *LockCache) Save() error {
return c.kv.Save()
}
func (c *LockCache) encodeIdKey(id string) string {
// Safety against accidents
if !c.isIdKey(id) {
return idKeyPrefix + id
}
return id
}
func (c *LockCache) decodeIdKey(key string) string {
// Safety against accidents
if c.isIdKey(key) {
return key[len(idKeyPrefix):]
}
return key
}
func (c *LockCache) isIdKey(key string) bool {
return strings.HasPrefix(key, idKeyPrefix)
}