github.com/2lambda123/git-lfs@v2.5.2+incompatible/locking/cache.go (about)

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