| 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] |
| } |