code: func (c *ObjectLRU) Put(obj plumbing.EncodedObject) {
  	c.mut.Lock()
  	defer c.mut.Unlock()
  
  	if c.cache == nil {
  		c.actualSize = 0
  		c.cache = make(map[interface{}]*list.Element, 1000)
  		c.ll = list.New()
  	}
  
  	objSize := FileSize(obj.Size())
  	key := obj.Hash()
  	if ee, ok := c.cache[key]; ok {
  		oldObj := ee.Value.(plumbing.EncodedObject)
  		// in this case objSize is a delta: new size - old size
  		objSize -= FileSize(oldObj.Size())
  		c.ll.MoveToFront(ee)
  		ee.Value = obj
  	} else {
  		if objSize > c.MaxSize {
  			return
  		}
  		ee := c.ll.PushFront(obj)
  		c.cache[key] = ee
  	}
  
  	c.actualSize += objSize
  	for c.actualSize > c.MaxSize {
  		last := c.ll.Back()
  		if last == nil {
  			c.actualSize = 0
  			break
  		}
  
  		lastObj := last.Value.(plumbing.EncodedObject)
  		lastSize := FileSize(lastObj.Size())
  
  		c.ll.Remove(last)
  		delete(c.cache, lastObj.Hash())
  		c.actualSize -= lastSize
  	}
  }
docs: // Put puts an object into the cache. If the object is already in the cache, it
  // will be marked as used. Otherwise, it will be inserted. A single object might
  // be evicted to make room for the new object.