blob: 2cd5d51d84989403195478fddef80f2ac9c29372 [file] [log] [blame]
package cache
import (
"sync"
"github.com/Masterminds/glide/msg"
"github.com/Masterminds/semver"
)
// Provide an in memory cache of imported project information.
var defaultMemCache = newMemCache()
// MemPut put a version into the in memory cache for a name.
// This will silently ignore non-semver and make sure the latest
// is stored.
func MemPut(name, version string) {
defaultMemCache.put(name, version)
}
// MemTouched returns true if the cache was touched for a name.
func MemTouched(name string) bool {
return defaultMemCache.touched(name)
}
// MemTouch notes if a name has been looked at.
func MemTouch(name string) {
defaultMemCache.touch(name)
}
// MemLatest returns the latest, that is most recent, semver release. This
// may be a blank string if no put value
func MemLatest(name string) string {
return defaultMemCache.getLatest(name)
}
// MemSetCurrent is used to set the current version in use.
func MemSetCurrent(name, version string) {
defaultMemCache.setCurrent(name, version)
}
// MemCurrent is used to get the current version in use.
func MemCurrent(name string) string {
return defaultMemCache.current(name)
}
// An in memory cache.
type memCache struct {
sync.RWMutex
latest map[string]string
t map[string]bool
versions map[string][]string
c map[string]string
}
func newMemCache() *memCache {
return &memCache{
latest: make(map[string]string),
t: make(map[string]bool),
versions: make(map[string][]string),
c: make(map[string]string),
}
}
func (m *memCache) setCurrent(name, version string) {
m.Lock()
defer m.Unlock()
if m.c[name] == "" {
m.c[name] = version
} else {
// If we already have a version try to see if the new or old one is
// semver and use that one.
_, err := semver.NewVersion(m.c[name])
if err != nil {
_, err2 := semver.NewVersion(version)
if err2 == nil {
m.c[name] = version
}
}
}
}
func (m *memCache) current(name string) string {
m.RLock()
defer m.RUnlock()
return m.c[name]
}
func (m *memCache) put(name, version string) {
m.Lock()
defer m.Unlock()
m.t[name] = true
sv, err := semver.NewVersion(version)
if err != nil {
msg.Debug("Ignoring %s version %s: %s", name, version, err)
return
}
latest, found := m.latest[name]
if found {
lv, err := semver.NewVersion(latest)
if err == nil {
if sv.GreaterThan(lv) {
m.latest[name] = version
}
}
} else {
m.latest[name] = version
}
found = false
for _, v := range m.versions[name] {
if v == version {
found = true
}
}
if !found {
m.versions[name] = append(m.versions[name], version)
}
}
func (m *memCache) touch(name string) {
m.Lock()
defer m.Unlock()
m.t[name] = true
}
func (m *memCache) touched(name string) bool {
m.RLock()
defer m.RUnlock()
return m.t[name]
}
func (m *memCache) getLatest(name string) string {
m.RLock()
defer m.RUnlock()
return m.latest[name]
}