@@ -12,7 +12,6 @@ import (
12
12
"bytes"
13
13
"crypto/sha256"
14
14
"encoding/hex"
15
- "errors"
16
15
"fmt"
17
16
"io"
18
17
"io/ioutil"
@@ -22,6 +21,8 @@ import (
22
21
"strings"
23
22
"time"
24
23
24
+ "github.com/pkg/errors"
25
+
25
26
"github.com/golangci/golangci-lint/internal/renameio"
26
27
)
27
28
@@ -144,47 +145,56 @@ func (c *Cache) get(id ActionID) (Entry, error) {
144
145
missing := func () (Entry , error ) {
145
146
return Entry {}, errMissing
146
147
}
147
- f , err := os .Open (c .fileName (id , "a" ))
148
+ failed := func (err error ) (Entry , error ) {
149
+ return Entry {}, err
150
+ }
151
+ fileName := c .fileName (id , "a" )
152
+ f , err := os .Open (fileName )
148
153
if err != nil {
149
- return missing ()
154
+ if os .IsNotExist (err ) {
155
+ return missing ()
156
+ }
157
+ return failed (err )
150
158
}
151
159
defer f .Close ()
152
160
entry := make ([]byte , entrySize + 1 ) // +1 to detect whether f is too long
153
- if n , err := io .ReadFull (f , entry ); n != entrySize || err != io .ErrUnexpectedEOF {
154
- return missing ( )
161
+ if n , readErr := io .ReadFull (f , entry ); n != entrySize || readErr != io .ErrUnexpectedEOF {
162
+ return failed ( fmt . Errorf ( "read %d/%d bytes from %s with error %s" , n , entrySize , fileName , readErr ) )
155
163
}
156
164
if entry [0 ] != 'v' || entry [1 ] != '1' || entry [2 ] != ' ' || entry [3 + hexSize ] != ' ' || entry [3 + hexSize + 1 + hexSize ] != ' ' || entry [3 + hexSize + 1 + hexSize + 1 + 20 ] != ' ' || entry [entrySize - 1 ] != '\n' {
157
- return missing ( )
165
+ return failed ( fmt . Errorf ( "bad data in %s" , fileName ) )
158
166
}
159
167
eid , entry := entry [3 :3 + hexSize ], entry [3 + hexSize :]
160
168
eout , entry := entry [1 :1 + hexSize ], entry [1 + hexSize :]
161
169
esize , entry := entry [1 :1 + 20 ], entry [1 + 20 :]
162
- etime , entry := entry [1 : 1 + 20 ], entry [ 1 + 20 : ]
170
+ etime := entry [1 : 1 + 20 ]
163
171
var buf [HashSize ]byte
164
- if _ , err : = hex .Decode (buf [:], eid ); err != nil || buf != id {
165
- return missing ( )
172
+ if _ , err = hex .Decode (buf [:], eid ); err != nil || buf != id {
173
+ return failed ( errors . Wrapf ( err , "failed to hex decode eid data in %s" , fileName ) )
166
174
}
167
- if _ , err : = hex .Decode (buf [:], eout ); err != nil {
168
- return missing ( )
175
+ if _ , err = hex .Decode (buf [:], eout ); err != nil {
176
+ return failed ( errors . Wrapf ( err , "failed to hex decode eout data in %s" , fileName ) )
169
177
}
170
178
i := 0
171
179
for i < len (esize ) && esize [i ] == ' ' {
172
180
i ++
173
181
}
174
182
size , err := strconv .ParseInt (string (esize [i :]), 10 , 64 )
175
183
if err != nil || size < 0 {
176
- return missing ( )
184
+ return failed ( fmt . Errorf ( "failed to parse esize int from %s with error %s" , fileName , err ) )
177
185
}
178
186
i = 0
179
187
for i < len (etime ) && etime [i ] == ' ' {
180
188
i ++
181
189
}
182
190
tm , err := strconv .ParseInt (string (etime [i :]), 10 , 64 )
183
191
if err != nil || tm < 0 {
184
- return missing ( )
192
+ return failed ( fmt . Errorf ( "failed to parse etime int from %s with error %s" , fileName , err ) )
185
193
}
186
194
187
- c .used (c .fileName (id , "a" ))
195
+ if err = c .used (fileName ); err != nil {
196
+ return failed (errors .Wrapf (err , "failed to mark %s as used" , fileName ))
197
+ }
188
198
189
199
return Entry {buf , size , time .Unix (0 , tm )}, nil
190
200
}
@@ -196,7 +206,12 @@ func (c *Cache) GetFile(id ActionID) (file string, entry Entry, err error) {
196
206
if err != nil {
197
207
return "" , Entry {}, err
198
208
}
199
- file = c .OutputFile (entry .OutputID )
209
+
210
+ file , err = c .OutputFile (entry .OutputID )
211
+ if err != nil {
212
+ return "" , Entry {}, err
213
+ }
214
+
200
215
info , err := os .Stat (file )
201
216
if err != nil || info .Size () != entry .Size {
202
217
return "" , Entry {}, errMissing
@@ -212,18 +227,29 @@ func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) {
212
227
if err != nil {
213
228
return nil , entry , err
214
229
}
215
- data , _ := ioutil .ReadFile (c .OutputFile (entry .OutputID ))
230
+ outputFile , err := c .OutputFile (entry .OutputID )
231
+ if err != nil {
232
+ return nil , entry , err
233
+ }
234
+
235
+ data , err := ioutil .ReadFile (outputFile )
236
+ if err != nil {
237
+ return nil , entry , err
238
+ }
239
+
216
240
if sha256 .Sum256 (data ) != entry .OutputID {
217
241
return nil , entry , errMissing
218
242
}
219
243
return data , entry , nil
220
244
}
221
245
222
246
// OutputFile returns the name of the cache file storing output with the given OutputID.
223
- func (c * Cache ) OutputFile (out OutputID ) string {
247
+ func (c * Cache ) OutputFile (out OutputID ) ( string , error ) {
224
248
file := c .fileName (out , "d" )
225
- c .used (file )
226
- return file
249
+ if err := c .used (file ); err != nil {
250
+ return "" , err
251
+ }
252
+ return file , nil
227
253
}
228
254
229
255
// Time constants for cache expiration.
@@ -253,12 +279,21 @@ const (
253
279
// mtime is more than an hour old. This heuristic eliminates
254
280
// nearly all of the mtime updates that would otherwise happen,
255
281
// while still keeping the mtimes useful for cache trimming.
256
- func (c * Cache ) used (file string ) {
282
+ func (c * Cache ) used (file string ) error {
257
283
info , err := os .Stat (file )
258
- if err == nil && c . now (). Sub ( info . ModTime ()) < mtimeInterval {
259
- return
284
+ if err != nil {
285
+ return errors . Wrapf ( err , "failed to stat file %s" , file )
260
286
}
261
- os .Chtimes (file , c .now (), c .now ())
287
+
288
+ if c .now ().Sub (info .ModTime ()) < mtimeInterval {
289
+ return nil
290
+ }
291
+
292
+ if err := os .Chtimes (file , c .now (), c .now ()); err != nil {
293
+ return errors .Wrapf (err , "failed to change time of file %s" , file )
294
+ }
295
+
296
+ return nil
262
297
}
263
298
264
299
// Trim removes old cache entries that are likely not to be reused.
@@ -285,7 +320,7 @@ func (c *Cache) Trim() {
285
320
286
321
// Ignore errors from here: if we don't write the complete timestamp, the
287
322
// cache will appear older than it is, and we'll trim it again next time.
288
- renameio .WriteFile (filepath .Join (c .dir , "trim.txt" ), []byte (fmt .Sprintf ("%d" , now .Unix ())), 0666 )
323
+ _ = renameio .WriteFile (filepath .Join (c .dir , "trim.txt" ), []byte (fmt .Sprintf ("%d" , now .Unix ())), 0666 )
289
324
}
290
325
291
326
// trimSubdir trims a single cache subdirectory.
@@ -367,7 +402,9 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
367
402
os .Remove (file )
368
403
return err
369
404
}
370
- os .Chtimes (file , c .now (), c .now ()) // mainly for tests
405
+ if err = os .Chtimes (file , c .now (), c .now ()); err != nil { // mainly for tests
406
+ return errors .Wrapf (err , "failed to change time of file %s" , file )
407
+ }
371
408
372
409
return nil
373
410
}
@@ -421,9 +458,12 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error {
421
458
info , err := os .Stat (name )
422
459
if err == nil && info .Size () == size {
423
460
// Check hash.
424
- if f , err := os .Open (name ); err == nil {
461
+ if f , openErr := os .Open (name ); openErr == nil {
425
462
h := sha256 .New ()
426
- io .Copy (h , f )
463
+ if _ , copyErr := io .Copy (h , f ); copyErr != nil {
464
+ return errors .Wrap (copyErr , "failed to copy to sha256" )
465
+ }
466
+
427
467
f .Close ()
428
468
var out2 OutputID
429
469
h .Sum (out2 [:0 ])
@@ -456,44 +496,49 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error {
456
496
// before returning, to avoid leaving bad bytes in the file.
457
497
458
498
// Copy file to f, but also into h to double-check hash.
459
- if _ , err : = file .Seek (0 , 0 ); err != nil {
460
- f .Truncate (0 )
499
+ if _ , err = file .Seek (0 , 0 ); err != nil {
500
+ _ = f .Truncate (0 )
461
501
return err
462
502
}
463
503
h := sha256 .New ()
464
504
w := io .MultiWriter (f , h )
465
- if _ , err : = io .CopyN (w , file , size - 1 ); err != nil {
466
- f .Truncate (0 )
505
+ if _ , err = io .CopyN (w , file , size - 1 ); err != nil {
506
+ _ = f .Truncate (0 )
467
507
return err
468
508
}
469
509
// Check last byte before writing it; writing it will make the size match
470
510
// what other processes expect to find and might cause them to start
471
511
// using the file.
472
512
buf := make ([]byte , 1 )
473
- if _ , err : = file .Read (buf ); err != nil {
474
- f .Truncate (0 )
513
+ if _ , err = file .Read (buf ); err != nil {
514
+ _ = f .Truncate (0 )
475
515
return err
476
516
}
477
- h .Write (buf )
517
+ if n , wErr := h .Write (buf ); n != len (buf ) {
518
+ return fmt .Errorf ("wrote to hash %d/%d bytes with error %s" , n , len (buf ), wErr )
519
+ }
520
+
478
521
sum := h .Sum (nil )
479
522
if ! bytes .Equal (sum , out [:]) {
480
- f .Truncate (0 )
523
+ _ = f .Truncate (0 )
481
524
return fmt .Errorf ("file content changed underfoot" )
482
525
}
483
526
484
527
// Commit cache file entry.
485
- if _ , err : = f .Write (buf ); err != nil {
486
- f .Truncate (0 )
528
+ if _ , err = f .Write (buf ); err != nil {
529
+ _ = f .Truncate (0 )
487
530
return err
488
531
}
489
- if err : = f .Close (); err != nil {
532
+ if err = f .Close (); err != nil {
490
533
// Data might not have been written,
491
534
// but file may look like it is the right size.
492
535
// To be extra careful, remove cached file.
493
536
os .Remove (name )
494
537
return err
495
538
}
496
- os .Chtimes (name , c .now (), c .now ()) // mainly for tests
539
+ if err = os .Chtimes (name , c .now (), c .now ()); err != nil { // mainly for tests
540
+ return errors .Wrapf (err , "failed to change time of file %s" , name )
541
+ }
497
542
498
543
return nil
499
544
}
0 commit comments