Skip to content
This repository was archived by the owner on Aug 25, 2018. It is now read-only.

Commit 05c4492

Browse files
committed
Add a cache for DeduceRemoteRepo
This skips the network ping, and speeds up for example gvt fetch camlistore.org/pkg/client by many minutes, since all fetches from camlistore.org after the first become local.
1 parent 49eea0d commit 05c4492

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

downloader.go

+52-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"strings"
45
"sync"
56

67
"github.com/FiloSottile/gvt/gbvendor"
@@ -19,14 +20,20 @@ type cacheEntry struct {
1920

2021
// Downloader acts as a cache for downloaded repositories
2122
type Downloader struct {
22-
mu sync.Mutex
23-
m map[cacheKey]*cacheEntry
23+
wcsMu sync.Mutex
24+
wcs map[cacheKey]*cacheEntry
25+
26+
reposMu sync.RWMutex
27+
repos map[string]vendor.RemoteRepo
28+
reposI map[string]vendor.RemoteRepo
2429
}
2530

2631
var GlobalDownloader = Downloader{}
2732

2833
func init() {
29-
GlobalDownloader.m = make(map[cacheKey]*cacheEntry)
34+
GlobalDownloader.wcs = make(map[cacheKey]*cacheEntry)
35+
GlobalDownloader.repos = make(map[string]vendor.RemoteRepo)
36+
GlobalDownloader.reposI = make(map[string]vendor.RemoteRepo)
3037
}
3138

3239
// Get returns a cached WorkingCopy, or runs RemoteRepo.Checkout
@@ -35,28 +42,28 @@ func (d *Downloader) Get(repo vendor.RemoteRepo, branch, tag, revision string) (
3542
url: repo.URL(), repoType: repo.Type(),
3643
branch: branch, tag: tag, revision: revision,
3744
}
38-
d.mu.Lock()
39-
if entry, ok := d.m[key]; ok {
40-
d.mu.Unlock()
45+
d.wcsMu.Lock()
46+
if entry, ok := d.wcs[key]; ok {
47+
d.wcsMu.Unlock()
4148
entry.wg.Wait()
4249
return entry.v, entry.err
4350
}
4451

4552
entry := &cacheEntry{}
4653
entry.wg.Add(1)
47-
d.m[key] = entry
48-
d.mu.Unlock()
54+
d.wcs[key] = entry
55+
d.wcsMu.Unlock()
4956

5057
entry.v, entry.err = repo.Checkout(branch, tag, revision)
5158
entry.wg.Done()
5259
return entry.v, entry.err
5360
}
5461

5562
func (d *Downloader) Flush() error {
56-
d.mu.Lock()
57-
defer d.mu.Unlock()
63+
d.wcsMu.Lock()
64+
defer d.wcsMu.Unlock()
5865

59-
for _, entry := range d.m {
66+
for _, entry := range d.wcs {
6067
entry.wg.Wait()
6168
if entry.err != nil {
6269
continue
@@ -67,3 +74,37 @@ func (d *Downloader) Flush() error {
6774
}
6875
return nil
6976
}
77+
78+
// DeduceRemoteRepo is a cached version of vendor.DeduceRemoteRepo
79+
func (d *Downloader) DeduceRemoteRepo(path string, insecure bool) (vendor.RemoteRepo, string, error) {
80+
cache := d.repos
81+
if insecure {
82+
cache = d.reposI
83+
}
84+
85+
d.reposMu.RLock()
86+
for p, repo := range cache {
87+
if path == p || strings.HasPrefix(path, p+"/") {
88+
d.reposMu.RUnlock()
89+
extra := strings.Trim(strings.TrimPrefix(path, p), "/")
90+
return repo, extra, nil
91+
}
92+
}
93+
d.reposMu.RUnlock()
94+
95+
repo, extra, err := vendor.DeduceRemoteRepo(path, insecure)
96+
if err != nil {
97+
return repo, extra, err
98+
}
99+
100+
if !strings.HasSuffix(path, extra) {
101+
// Shouldn't happen, but in case just bypass the cache
102+
return repo, extra, err
103+
}
104+
basePath := strings.Trim(strings.TrimSuffix(path, extra), "/")
105+
d.reposMu.Lock()
106+
cache[basePath] = repo
107+
d.reposMu.Unlock()
108+
109+
return repo, extra, err
110+
}

fetch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func fetchRecursive(m *vendor.Manifest, fullPath string, level int) error {
159159

160160
// Find and download the repository
161161

162-
repo, extra, err := vendor.DeduceRemoteRepo(fullPath, insecure)
162+
repo, extra, err := GlobalDownloader.DeduceRemoteRepo(fullPath, insecure)
163163
if err != nil {
164164
return err
165165
}

0 commit comments

Comments
 (0)