blob: 3fb76aa4baae93e95ed61d6980c2b6f3371a6cfd [file] [log] [blame]
package main
import (
"sync"
"github.com/FiloSottile/gvt/gbvendor"
)
type cacheKey struct {
url, repoType string
branch, tag, revision string
}
type cacheEntry struct {
wg sync.WaitGroup
v vendor.WorkingCopy
err error
}
// Downloader acts as a cache for downloaded repositories
type Downloader struct {
mu sync.Mutex
m map[cacheKey]*cacheEntry
}
var GlobalDownloader = Downloader{}
func init() {
GlobalDownloader.m = make(map[cacheKey]*cacheEntry)
}
// Get returns a cached WorkingCopy, or runs RemoteRepo.Checkout
func (d *Downloader) Get(repo vendor.RemoteRepo, branch, tag, revision string) (vendor.WorkingCopy, error) {
key := cacheKey{
url: repo.URL(), repoType: repo.Type(),
branch: branch, tag: tag, revision: revision,
}
d.mu.Lock()
if entry, ok := d.m[key]; ok {
d.mu.Unlock()
entry.wg.Wait()
return entry.v, entry.err
}
entry := &cacheEntry{}
entry.wg.Add(1)
d.m[key] = entry
d.mu.Unlock()
entry.v, entry.err = repo.Checkout(branch, tag, revision)
entry.wg.Done()
return entry.v, entry.err
}
func (d *Downloader) Flush() error {
d.mu.Lock()
defer d.mu.Unlock()
for _, entry := range d.m {
entry.wg.Wait()
if entry.err != nil {
continue
}
if err := entry.v.Destroy(); err != nil {
return err
}
}
return nil
}