Skip to content

Commit a6023db

Browse files
Bryan C. Millsgopherbot
Bryan C. Mills
authored andcommitted
[release-branch.go1.21] cmd/go/internal/modfetch/codehost: add new git tags before statLocal instead of after
gitRepo.statLocal reports tag and version information. If we are statting a hash that corresponds to a tag, we need to add that tag before calling statLocal so that it can be included in that information. For #53955. For #56881. For #64586 Change-Id: I69a71428e6ed9096d4cb8ed1bb79531415ff06c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/547155 Auto-Submit: Bryan Mills <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Matloob <[email protected]> (cherry picked from commit 7b5a373) Reviewed-on: https://go-review.googlesource.com/c/go/+/585815 Reviewed-by: Sam Thanawalla <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]>
1 parent 0fa334d commit a6023db

File tree

2 files changed

+82
-9
lines changed

2 files changed

+82
-9
lines changed

src/cmd/go/internal/modfetch/codehost/git.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"os/exec"
1919
"path/filepath"
2020
"runtime"
21+
"slices"
2122
"sort"
2223
"strconv"
2324
"strings"
@@ -154,7 +155,7 @@ type gitRepo struct {
154155
refsErr error
155156

156157
localTagsOnce sync.Once
157-
localTags map[string]bool
158+
localTags sync.Map // map[string]bool
158159
}
159160

160161
const (
@@ -166,7 +167,6 @@ const (
166167

167168
// loadLocalTags loads tag references from the local git cache
168169
// into the map r.localTags.
169-
// Should only be called as r.localTagsOnce.Do(r.loadLocalTags).
170170
func (r *gitRepo) loadLocalTags(ctx context.Context) {
171171
// The git protocol sends all known refs and ls-remote filters them on the client side,
172172
// so we might as well record both heads and tags in one shot.
@@ -176,10 +176,9 @@ func (r *gitRepo) loadLocalTags(ctx context.Context) {
176176
return
177177
}
178178

179-
r.localTags = make(map[string]bool)
180179
for _, line := range strings.Split(string(out), "\n") {
181180
if line != "" {
182-
r.localTags[line] = true
181+
r.localTags.Store(line, true)
183182
}
184183
}
185184
}
@@ -430,7 +429,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
430429
// Maybe rev is a tag we already have locally.
431430
// (Note that we're excluding branches, which can be stale.)
432431
r.localTagsOnce.Do(func() { r.loadLocalTags(ctx) })
433-
if r.localTags[rev] {
432+
if _, ok := r.localTags.Load(rev); ok {
434433
return r.statLocal(ctx, rev, "refs/tags/"+rev)
435434
}
436435

@@ -506,11 +505,18 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
506505
// Either way, try a local stat before falling back to network I/O.
507506
if !didStatLocal {
508507
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)
512518
}
513-
return info, nil
519+
return info, err
514520
}
515521
}
516522

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Regression test for https://go.dev/issue/53955.
2+
# New remote tags were erroneously added to the local clone of a repo
3+
# only *after* extracting version information for a locally-cached commit,
4+
# causing the version information to have incomplete Tags and Version fields.
5+
6+
[short] skip 'constructs a local git repo'
7+
[!git] skip
8+
[!net:github.com] skip 'does not actually use github.com because of insteadOf, but silence network check just in case'
9+
10+
env GIT_CONFIG_GLOBAL=$WORK/.gitconfig
11+
env GIT_ALLOW_PROTOCOL=file
12+
env GOPRIVATE=github.com/golang/issue53955
13+
14+
[!GOOS:windows] exec git config --global 'url.file://'$WORK'/repo.insteadOf' 'https://github.com/golang/issue53955'
15+
[GOOS:windows] exec git config --global 'url.file:///'$WORK'/repo.insteadOf' 'https://github.com/golang/issue53955'
16+
17+
cd $WORK/repo
18+
19+
env GIT_AUTHOR_NAME='Go Gopher'
20+
env GIT_AUTHOR_EMAIL='[email protected]'
21+
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
22+
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
23+
24+
exec git init
25+
26+
env GIT_COMMITTER_DATE=2022-07-19T11:07:00-04:00
27+
env GIT_AUTHOR_DATE=2022-07-19T11:07:00-04:00
28+
exec git add go.mod issue53955.go
29+
exec git commit -m 'initial commit'
30+
exec git branch -m main
31+
exec git tag v1.0.9
32+
33+
env GIT_COMMITTER_DATE=2022-07-19T11:07:01-04:00
34+
env GIT_AUTHOR_DATE=2022-07-19T11:07:01-04:00
35+
exec git add extra.go
36+
exec git commit -m 'next commit'
37+
exec git show-ref --tags --heads
38+
cmp stdout $WORK/.git-refs-1
39+
40+
cd $WORK/m
41+
go get -x github.com/golang/issue53955@2cb3d49f
42+
stderr '^go: added github.com/golang/issue53955 v1.0.10-0.20220719150701-2cb3d49f8874$'
43+
44+
cd $WORK/repo
45+
exec git tag v1.0.10
46+
47+
cd $WORK/m
48+
go get -x github.com/golang/[email protected]
49+
! stderr 'v1\.0\.10 is not a tag'
50+
stderr '^go: upgraded github.com/golang/issue53955 v.* => v1\.0\.10$'
51+
52+
-- $WORK/repo/go.mod --
53+
module github.com/golang/issue53955
54+
55+
go 1.18
56+
-- $WORK/repo/issue53955.go --
57+
package issue53955
58+
-- $WORK/repo/extra.go --
59+
package issue53955
60+
-- $WORK/.git-refs-1 --
61+
2cb3d49f8874b9362ed0ddd2a6512e4108bbf6b1 refs/heads/main
62+
050526ebf5883191e990529eb3cc9345abaf838c refs/tags/v1.0.9
63+
-- $WORK/m/go.mod --
64+
module m
65+
66+
go 1.18
67+
-- $WORK/.gitconfig --

0 commit comments

Comments
 (0)