1
1
package main
2
2
3
3
import (
4
+ "strings"
4
5
"sync"
5
6
6
7
"github.com/FiloSottile/gvt/gbvendor"
@@ -19,14 +20,20 @@ type cacheEntry struct {
19
20
20
21
// Downloader acts as a cache for downloaded repositories
21
22
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
24
29
}
25
30
26
31
var GlobalDownloader = Downloader {}
27
32
28
33
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 )
30
37
}
31
38
32
39
// Get returns a cached WorkingCopy, or runs RemoteRepo.Checkout
@@ -35,28 +42,28 @@ func (d *Downloader) Get(repo vendor.RemoteRepo, branch, tag, revision string) (
35
42
url : repo .URL (), repoType : repo .Type (),
36
43
branch : branch , tag : tag , revision : revision ,
37
44
}
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 ()
41
48
entry .wg .Wait ()
42
49
return entry .v , entry .err
43
50
}
44
51
45
52
entry := & cacheEntry {}
46
53
entry .wg .Add (1 )
47
- d .m [key ] = entry
48
- d .mu .Unlock ()
54
+ d .wcs [key ] = entry
55
+ d .wcsMu .Unlock ()
49
56
50
57
entry .v , entry .err = repo .Checkout (branch , tag , revision )
51
58
entry .wg .Done ()
52
59
return entry .v , entry .err
53
60
}
54
61
55
62
func (d * Downloader ) Flush () error {
56
- d .mu .Lock ()
57
- defer d .mu .Unlock ()
63
+ d .wcsMu .Lock ()
64
+ defer d .wcsMu .Unlock ()
58
65
59
- for _ , entry := range d .m {
66
+ for _ , entry := range d .wcs {
60
67
entry .wg .Wait ()
61
68
if entry .err != nil {
62
69
continue
@@ -67,3 +74,37 @@ func (d *Downloader) Flush() error {
67
74
}
68
75
return nil
69
76
}
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
+ }
0 commit comments