@@ -18,6 +18,7 @@ import (
18
18
"os/exec"
19
19
"path/filepath"
20
20
"runtime"
21
+ "slices"
21
22
"sort"
22
23
"strconv"
23
24
"strings"
@@ -154,7 +155,7 @@ type gitRepo struct {
154
155
refsErr error
155
156
156
157
localTagsOnce sync.Once
157
- localTags map [string ]bool
158
+ localTags sync. Map // map[string]bool
158
159
}
159
160
160
161
const (
@@ -166,7 +167,6 @@ const (
166
167
167
168
// loadLocalTags loads tag references from the local git cache
168
169
// into the map r.localTags.
169
- // Should only be called as r.localTagsOnce.Do(r.loadLocalTags).
170
170
func (r * gitRepo ) loadLocalTags (ctx context.Context ) {
171
171
// The git protocol sends all known refs and ls-remote filters them on the client side,
172
172
// so we might as well record both heads and tags in one shot.
@@ -176,10 +176,9 @@ func (r *gitRepo) loadLocalTags(ctx context.Context) {
176
176
return
177
177
}
178
178
179
- r .localTags = make (map [string ]bool )
180
179
for _ , line := range strings .Split (string (out ), "\n " ) {
181
180
if line != "" {
182
- r .localTags [ line ] = true
181
+ r .localTags . Store ( line , true )
183
182
}
184
183
}
185
184
}
@@ -430,7 +429,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
430
429
// Maybe rev is a tag we already have locally.
431
430
// (Note that we're excluding branches, which can be stale.)
432
431
r .localTagsOnce .Do (func () { r .loadLocalTags (ctx ) })
433
- if r .localTags [ rev ] {
432
+ if _ , ok := r .localTags . Load ( rev ); ok {
434
433
return r .statLocal (ctx , rev , "refs/tags/" + rev )
435
434
}
436
435
@@ -506,11 +505,18 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
506
505
// Either way, try a local stat before falling back to network I/O.
507
506
if ! didStatLocal {
508
507
if info , err := r .statLocal (ctx , rev , hash ); err == nil {
509
- if after , found := strings .CutPrefix (ref , "refs/tags/" ); found {
510
- // Make sure tag exists, so it will be in localTags next time the go command is run.
511
- Run (ctx , r .dir , "git" , "tag" , after , hash )
508
+ tag , fromTag := strings .CutPrefix (ref , "refs/tags/" )
509
+ if fromTag && ! slices .Contains (info .Tags , tag ) {
510
+ // The local repo includes the commit hash we want, but it is missing
511
+ // the corresponding tag. Add that tag and try again.
512
+ _ , err := Run (ctx , r .dir , "git" , "tag" , tag , hash )
513
+ if err != nil {
514
+ return nil , err
515
+ }
516
+ r .localTags .Store (tag , true )
517
+ return r .statLocal (ctx , rev , ref )
512
518
}
513
- return info , nil
519
+ return info , err
514
520
}
515
521
}
516
522
0 commit comments