@@ -17,6 +17,14 @@ import (
17
17
"github.com/golangci/golangci-lint/pkg/timeutils"
18
18
)
19
19
20
+ type HashMode int
21
+
22
+ const (
23
+ HashModeNeedOnlySelf HashMode = iota
24
+ HashModeNeedDirectDeps
25
+ HashModeNeedAllDeps
26
+ )
27
+
20
28
// Cache is a per-package data cache. A cached data is invalidated when
21
29
// package or it's dependencies change.
22
30
type Cache struct {
@@ -46,7 +54,7 @@ func (c *Cache) Trim() {
46
54
})
47
55
}
48
56
49
- func (c * Cache ) Put (pkg * packages.Package , key string , data interface {}) error {
57
+ func (c * Cache ) Put (pkg * packages.Package , mode HashMode , key string , data interface {}) error {
50
58
var err error
51
59
buf := & bytes.Buffer {}
52
60
c .sw .TrackStage ("gob" , func () {
@@ -59,7 +67,7 @@ func (c *Cache) Put(pkg *packages.Package, key string, data interface{}) error {
59
67
var aID cache.ActionID
60
68
61
69
c .sw .TrackStage ("key build" , func () {
62
- aID , err = c .pkgActionID (pkg )
70
+ aID , err = c .pkgActionID (pkg , mode )
63
71
if err == nil {
64
72
subkey , subkeyErr := cache .Subkey (aID , key )
65
73
if subkeyErr != nil {
@@ -85,11 +93,11 @@ func (c *Cache) Put(pkg *packages.Package, key string, data interface{}) error {
85
93
86
94
var ErrMissing = errors .New ("missing data" )
87
95
88
- func (c * Cache ) Get (pkg * packages.Package , key string , data interface {}) error {
96
+ func (c * Cache ) Get (pkg * packages.Package , mode HashMode , key string , data interface {}) error {
89
97
var aID cache.ActionID
90
98
var err error
91
99
c .sw .TrackStage ("key build" , func () {
92
- aID , err = c .pkgActionID (pkg )
100
+ aID , err = c .pkgActionID (pkg , mode )
93
101
if err == nil {
94
102
subkey , subkeyErr := cache .Subkey (aID , key )
95
103
if subkeyErr != nil {
@@ -125,8 +133,8 @@ func (c *Cache) Get(pkg *packages.Package, key string, data interface{}) error {
125
133
return nil
126
134
}
127
135
128
- func (c * Cache ) pkgActionID (pkg * packages.Package ) (cache.ActionID , error ) {
129
- hash , err := c .packageHash (pkg )
136
+ func (c * Cache ) pkgActionID (pkg * packages.Package , mode HashMode ) (cache.ActionID , error ) {
137
+ hash , err := c .packageHash (pkg , mode )
130
138
if err != nil {
131
139
return cache.ActionID {}, errors .Wrap (err , "failed to get package hash" )
132
140
}
@@ -144,12 +152,19 @@ func (c *Cache) pkgActionID(pkg *packages.Package) (cache.ActionID, error) {
144
152
// packageHash computes a package's hash. The hash is based on all Go
145
153
// files that make up the package, as well as the hashes of imported
146
154
// packages.
147
- func (c * Cache ) packageHash (pkg * packages.Package ) (string , error ) {
148
- cachedHash , ok := c .pkgHashes .Load (pkg )
155
+ func (c * Cache ) packageHash (pkg * packages.Package , mode HashMode ) (string , error ) {
156
+ type hashResults map [HashMode ]string
157
+ hashResI , ok := c .pkgHashes .Load (pkg )
149
158
if ok {
150
- return cachedHash .(string ), nil
159
+ hashRes := hashResI .(hashResults )
160
+ if _ , ok := hashRes [mode ]; ! ok {
161
+ return "" , fmt .Errorf ("no mode %d in hash result" , mode )
162
+ }
163
+ return hashRes [mode ], nil
151
164
}
152
165
166
+ hashRes := hashResults {}
167
+
153
168
key , err := cache .NewHash ("package hash" )
154
169
if err != nil {
155
170
return "" , errors .Wrap (err , "failed to make a hash" )
@@ -158,13 +173,15 @@ func (c *Cache) packageHash(pkg *packages.Package) (string, error) {
158
173
fmt .Fprintf (key , "pkgpath %s\n " , pkg .PkgPath )
159
174
for _ , f := range pkg .CompiledGoFiles {
160
175
c .ioSem <- struct {}{}
161
- h , err := cache .FileHash (f )
176
+ h , fErr := cache .FileHash (f )
162
177
<- c .ioSem
163
- if err != nil {
164
- return "" , errors .Wrapf (err , "failed to calculate file %s hash" , f )
178
+ if fErr != nil {
179
+ return "" , errors .Wrapf (fErr , "failed to calculate file %s hash" , f )
165
180
}
166
181
fmt .Fprintf (key , "file %s %x\n " , f , h )
167
182
}
183
+ curSum := key .Sum ()
184
+ hashRes [HashModeNeedOnlySelf ] = hex .EncodeToString (curSum [:])
168
185
169
186
imps := make ([]* packages.Package , 0 , len (pkg .Imports ))
170
187
for _ , imp := range pkg .Imports {
@@ -173,20 +190,40 @@ func (c *Cache) packageHash(pkg *packages.Package) (string, error) {
173
190
sort .Slice (imps , func (i , j int ) bool {
174
191
return imps [i ].PkgPath < imps [j ].PkgPath
175
192
})
176
- for _ , dep := range imps {
177
- if dep .PkgPath == "unsafe" {
178
- continue
179
- }
180
193
181
- depHash , err := c .packageHash (dep )
182
- if err != nil {
183
- return "" , errors .Wrapf (err , "failed to calculate hash for dependency %s" , dep .Name )
194
+ calcDepsHash := func (depMode HashMode ) error {
195
+ for _ , dep := range imps {
196
+ if dep .PkgPath == "unsafe" {
197
+ continue
198
+ }
199
+
200
+ depHash , depErr := c .packageHash (dep , depMode )
201
+ if depErr != nil {
202
+ return errors .Wrapf (depErr , "failed to calculate hash for dependency %s with mode %d" , dep .Name , depMode )
203
+ }
204
+
205
+ fmt .Fprintf (key , "import %s %s\n " , dep .PkgPath , depHash )
184
206
}
207
+ return nil
208
+ }
209
+
210
+ if err := calcDepsHash (HashModeNeedOnlySelf ); err != nil {
211
+ return "" , err
212
+ }
185
213
186
- fmt .Fprintf (key , "import %s %s\n " , dep .PkgPath , depHash )
214
+ curSum = key .Sum ()
215
+ hashRes [HashModeNeedDirectDeps ] = hex .EncodeToString (curSum [:])
216
+
217
+ if err := calcDepsHash (HashModeNeedAllDeps ); err != nil {
218
+ return "" , err
219
+ }
220
+ curSum = key .Sum ()
221
+ hashRes [HashModeNeedAllDeps ] = hex .EncodeToString (curSum [:])
222
+
223
+ if _ , ok := hashRes [mode ]; ! ok {
224
+ return "" , fmt .Errorf ("invalid mode %d" , mode )
187
225
}
188
- h := key .Sum ()
189
- ret := hex .EncodeToString (h [:])
190
- c .pkgHashes .Store (pkg , ret )
191
- return ret , nil
226
+
227
+ c .pkgHashes .Store (pkg , hashRes )
228
+ return hashRes [mode ], nil
192
229
}
0 commit comments