Skip to content

Commit b4872ea

Browse files
committed
cmd/go: fix go get go@badversion
It was panicking instead of printing a nice error. Fixes #61258. Fixes #61259. Change-Id: Ia30853db5bc7f1f2a4c7e91169c659ae2b79adcb Reviewed-on: https://go-review.googlesource.com/c/go/+/509097 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
1 parent 8735039 commit b4872ea

File tree

4 files changed

+67
-17
lines changed

4 files changed

+67
-17
lines changed

src/cmd/go/internal/modfetch/toolchain.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ func (r *toolchainRepo) Versions(ctx context.Context, prefix string) (*Versions,
6060
}
6161
}
6262

63+
// Always include our own version.
64+
// This means that the development branch of Go 1.21 (say) will allow 'go get [email protected]'
65+
// even though there are no Go 1.21 releases yet.
66+
// Once there is a release, 1.21 will be treated as a query matching the latest available release.
67+
// Before then, 1.21 will be treated as a query that resolves to this entry we are adding (1.21).
68+
if v := gover.Local(); !have[v] {
69+
list = append(list, goPrefix+v)
70+
}
71+
6372
if r.path == "go" {
6473
sort.Slice(list, func(i, j int) bool {
6574
return gover.Compare(list[i], list[j]) < 0
@@ -74,20 +83,27 @@ func (r *toolchainRepo) Versions(ctx context.Context, prefix string) (*Versions,
7483
}
7584

7685
func (r *toolchainRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
77-
// If we're asking about "go" (not "toolchain"), pretend to have
78-
// all earlier Go versions available without network access:
79-
// we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
80-
if r.path == "go" && gover.Compare(rev, gover.Local()) <= 0 {
81-
return &RevInfo{Version: rev}, nil
82-
}
83-
8486
// Convert rev to DL version and stat that to make sure it exists.
87+
// In theory the go@ versions should be like 1.21.0
88+
// and the toolchain@ versions should be like go1.21.0
89+
// but people will type the wrong one, and so we accept
90+
// both and silently correct it to the standard form.
8591
prefix := ""
8692
v := rev
8793
v = strings.TrimPrefix(v, "go")
8894
if r.path == "toolchain" {
8995
prefix = "go"
9096
}
97+
98+
if !gover.IsValid(v) {
99+
return nil, fmt.Errorf("invalid %s version %s", r.path, rev)
100+
}
101+
// If we're asking about "go" (not "toolchain"), pretend to have
102+
// all earlier Go versions available without network access:
103+
// we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
104+
if r.path == "go" && gover.Compare(v, gover.Local()) <= 0 {
105+
return &RevInfo{Version: prefix + v}, nil
106+
}
91107
if gover.IsLang(v) {
92108
return nil, fmt.Errorf("go language version %s is not a toolchain version", rev)
93109
}

src/cmd/go/internal/modget/query.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,13 @@ func (q *query) matchesPath(path string) bool {
239239
// canMatchInModule reports whether the given module path can potentially
240240
// contain q.pattern.
241241
func (q *query) canMatchInModule(mPath string) bool {
242+
if gover.IsToolchain(mPath) {
243+
return false
244+
}
242245
if q.canMatchWildcardInModule != nil {
243246
return q.canMatchWildcardInModule(mPath)
244247
}
245-
return str.HasPathPrefix(q.pattern, mPath) && !gover.IsToolchain(mPath)
248+
return str.HasPathPrefix(q.pattern, mPath)
246249
}
247250

248251
// pathOnce invokes f to generate the pathSet for the given path,

src/cmd/go/internal/modload/query.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,11 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (*
473473
// AllowedFunc of qm.
474474
func (qm *queryMatcher) allowsVersion(ctx context.Context, v string) bool {
475475
if qm.prefix != "" && !strings.HasPrefix(v, qm.prefix) {
476-
return false
476+
if gover.IsToolchain(qm.path) && strings.TrimSuffix(qm.prefix, ".") == v {
477+
// Allow 1.21 to match "1.21." prefix.
478+
} else {
479+
return false
480+
}
477481
}
478482
if qm.filter != nil && !qm.filter(v) {
479483
return false

src/cmd/go/testdata/script/mod_get_toolchain.txt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
# setup
2-
env TESTGO_VERSION=go1.99.0
2+
env TESTGO_VERSION=go1.99rc1
33
env TESTGO_VERSION_SWITCH=switch
44

55
# go get go should use the latest Go 1.23
66
cp go.mod.orig go.mod
77
go get go
88
stderr '^go: upgraded go 1.21 => 1.23.9$'
99
grep 'go 1.23.9' go.mod
10-
grep 'toolchain go1.99.0' go.mod
10+
grep 'toolchain go1.99rc1' go.mod
1111

1212
# go get [email protected] should use the latest Go 1.23
1313
cp go.mod.orig go.mod
1414
1515
stderr '^go: upgraded go 1.21 => 1.23.9$'
1616
grep 'go 1.23.9' go.mod
17-
grep 'toolchain go1.99.0' go.mod
17+
grep 'toolchain go1.99rc1' go.mod
1818

1919
# go get [email protected] should use the latest Go 1.22
2020
cp go.mod.orig go.mod
2121
2222
stderr '^go: upgraded go 1.21 => 1.22.9$'
2323
grep 'go 1.22.9' go.mod
24-
grep 'toolchain go1.99.0' go.mod
24+
grep 'toolchain go1.99rc1' go.mod
2525

2626
# go get go@patch should use the latest patch release
2727
2828
go get go@patch
2929
stderr '^go: upgraded go 1.22.1 => 1.22.9$'
3030
grep 'go 1.22.9' go.mod
31-
grep 'toolchain go1.99.0' go.mod
31+
grep 'toolchain go1.99rc1' go.mod
3232

3333
# go get [email protected] does NOT find the release candidate
3434
cp go.mod.orig go.mod
@@ -40,20 +40,20 @@ cp go.mod.orig go.mod
4040
4141
stderr '^go: upgraded go 1.21 => 1.24rc1$'
4242
grep 'go 1.24rc1' go.mod
43-
grep 'toolchain go1.99.0' go.mod
43+
grep 'toolchain go1.99rc1' go.mod
4444

4545
# go get go@latest finds the latest Go 1.23
4646
cp go.mod.orig go.mod
4747
go get go@latest
4848
stderr '^go: upgraded go 1.21 => 1.23.9$'
4949
grep 'go 1.23.9' go.mod
50-
grep 'toolchain go1.99.0' go.mod
50+
grep 'toolchain go1.99rc1' go.mod
5151

5252
# Again, with toolchains.
5353

5454
# go get toolchain should find go1.999testmod.
5555
go get toolchain
56-
stderr '^go: upgraded toolchain go1.99.0 => go1.999testmod$'
56+
stderr '^go: upgraded toolchain go1.99rc1 => go1.999testmod$'
5757
grep 'go 1.23.9' go.mod
5858
grep 'toolchain go1.999testmod' go.mod
5959

@@ -96,6 +96,33 @@ stderr '^go: added toolchain go1.999testmod$'
9696
grep 'go 1.21' go.mod
9797
grep 'toolchain go1.999testmod' go.mod
9898

99+
# Bug fixes.
100+
101+
# go get go@garbage should fail but not crash
102+
! go get go@garbage
103+
! stderr panic
104+
stderr '^go: invalid go version garbage$'
105+
106+
# go get [email protected] is OK - we silently correct to 1.21.0
107+
108+
109+
stderr '^go: upgraded go 1.19 => 1.21.0'
110+
111+
# go get [email protected] is OK too.
112+
113+
stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
114+
115+
# go get [email protected] should work if we are the Go 1.21 language version,
116+
# even though there's no toolchain for it.
117+
# (Older versions resolve to the latest release in that version, so for example
118+
# go get [email protected] might resolve to 1.20.9, but if we're the devel copy of
119+
# Go 1.21, there's no release yet to resolve to, so we resolve to ourselves.)
120+
env TESTGO_VERSION=go1.21
121+
go get [email protected] toolchain@none
122+
123+
grep 'go 1.21$' go.mod
124+
! grep toolchain go.mod
125+
99126
-- go.mod.orig --
100127
module m
101128

0 commit comments

Comments
 (0)