package locking
import (
"strings"
"github.com/git-lfs/git-lfs/v3/tools/kv"
)
const (
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
}
func (c *LockCache) Add(l Lock) error {
c.kv.Set(l.Path, &l)
c.kv.Set(c.encodeIdKey(l.Id), &l)
return nil
}
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)
c.kv.Remove(c.encodeIdKey(lock.Id))
}
return nil
}
func (c *LockCache) RemoveById(id string) error {
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
}
func (c *LockCache) Locks() []Lock {
var locks []Lock
c.kv.Visit(func(key string, val interface{}) bool {
if !c.isIdKey(key) {
lock := val.(*Lock)
locks = append(locks, *lock)
}
return true
})
return locks
}
func (c *LockCache) Clear() {
c.kv.RemoveAll()
}
func (c *LockCache) Save() error {
return c.kv.Save()
}
func (c *LockCache) encodeIdKey(id string) string {
if !c.isIdKey(id) {
return idKeyPrefix + id
}
return id
}
func (c *LockCache) decodeIdKey(key string) string {
if c.isIdKey(key) {
return key[len(idKeyPrefix):]
}
return key
}
func (c *LockCache) isIdKey(key string) bool {
return strings.HasPrefix(key, idKeyPrefix)
}