Skip to content

Commit cbf4b5e

Browse files
committed
cmd/go: add -u=patch option for go list
Fixes golang#41006 Change-Id: I52fb3a9525ccdacd9d4ed237ce62193c5f9c1551
1 parent 4412230 commit cbf4b5e

File tree

4 files changed

+102
-7
lines changed

4 files changed

+102
-7
lines changed

src/cmd/go/internal/list/list.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,30 @@ func init() {
337337
CmdList.Run = runList // break init cycle
338338
work.AddBuildFlags(CmdList, work.DefaultBuildFlags)
339339
CmdList.Flag.Var(&listJsonFields, "json", "")
340+
CmdList.Flag.Var(&listU, "u", "")
341+
}
342+
343+
// listUFlag is provided to maintain backwards compatibility with the old
344+
// bool-only behavior. Now that the -u flag supports a string (-u=patch), we
345+
// need to differentiate between non-existence, existence without value (-u),
346+
// and existence with value (-u=patch).
347+
type listUFlag struct {
348+
set bool
349+
value string
350+
}
351+
352+
func (f *listUFlag) Set(x string) error {
353+
f.value = x
354+
f.set = true
355+
return nil
356+
}
357+
358+
func (f *listUFlag) String() string {
359+
return f.value
360+
}
361+
362+
func (f *listUFlag) IsBoolFlag() bool {
363+
return true
340364
}
341365

342366
var (
@@ -352,7 +376,7 @@ var (
352376
listRetracted = CmdList.Flag.Bool("retracted", false, "")
353377
listReuse = CmdList.Flag.String("reuse", "", "")
354378
listTest = CmdList.Flag.Bool("test", false, "")
355-
listU = CmdList.Flag.Bool("u", false, "")
379+
listU listUFlag
356380
listVersions = CmdList.Flag.Bool("versions", false, "")
357381
)
358382

@@ -522,7 +546,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
522546
if *listVersions {
523547
base.Fatalf(actionDisabledFormat, "determine available versions")
524548
}
525-
if *listU {
549+
if listU.set {
526550
base.Fatalf(actionDisabledFormat, "determine available upgrades")
527551
}
528552

@@ -540,7 +564,9 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
540564
}
541565

542566
var mode modload.ListMode
543-
if *listU {
567+
if listU.value == "patch" {
568+
mode |= modload.ListPatch | modload.ListRetracted | modload.ListDeprecated
569+
} else if listU.set {
544570
mode |= modload.ListU | modload.ListRetracted | modload.ListDeprecated
545571
}
546572
if *listRetracted {
@@ -574,7 +600,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
574600
}
575601

576602
// Package mode (not -m).
577-
if *listU {
603+
if listU.set {
578604
base.Fatalf("go list -u can only be used with -m")
579605
}
580606
if *listVersions {

src/cmd/go/internal/modload/build.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,17 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
124124
}
125125

126126
// addUpdate fills in m.Update if an updated version is available.
127-
func addUpdate(ctx context.Context, m *modinfo.ModulePublic) {
127+
func addUpdate(ctx context.Context, m *modinfo.ModulePublic, minor bool) {
128128
if m.Version == "" {
129129
return
130130
}
131131

132-
info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed)
132+
query := "upgrade"
133+
if !minor {
134+
query = "patch"
135+
}
136+
137+
info, err := Query(ctx, m.Path, query, m.Version, CheckAllowed)
133138
var noVersionErr *NoMatchingVersionError
134139
if errors.Is(err, ErrDisallowed) ||
135140
errors.Is(err, fs.ErrNotExist) ||

src/cmd/go/internal/modload/list.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
ListDeprecated
3333
ListVersions
3434
ListRetractedVersions
35+
ListPatch
3536
)
3637

3738
// ListModules returns a description of the modules matching args, if known,
@@ -80,7 +81,9 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st
8081
sem <- token{}
8182
go func() {
8283
if mode&ListU != 0 {
83-
addUpdate(ctx, m)
84+
addUpdate(ctx, m, true)
85+
} else if mode&ListPatch != 0 {
86+
addUpdate(ctx, m, false)
8487
}
8588
if mode&ListVersions != 0 {
8689
addVersions(ctx, m, mode&ListRetractedVersions != 0)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# • listing -u=patch for a module that is already above the “latest” version
2+
# how... would that happen? o.O maybe a locally-tagged module? but not sure how i'd set that up in these tests?
3+
#
4+
# DONE: • listing -u=patch for a module that is already at exactly the latest patch release
5+
#
6+
# • listing -u=patch for a module one hop away from the main module (e.g. a
7+
# dependency used by the test of an external package imported by the main module)
8+
#
9+
# • listing -u=patch for a module that is not currently in the build list at all
10+
#
11+
# • listing -u=patch, without -m (so listing packages instead of modules), with a
12+
# -f argument that inspects {{.Module.Update.Version}}. (I believe that such an
13+
# invocation should currently fail with go list -u can only be used with -m, which
14+
# is fine, but we should have a test of it anyway — if only to remind us to update
15+
# the test if we ever change that behavior.)
16+
17+
18+
env GO111MODULE=on
19+
20+
# When -u is specified, show upgrades up to latest minor.patch.
21+
go list -u -m all
22+
stdout '^rsc.io/quote v1.2.0 \[v1.5.2\]$'
23+
24+
# When -u=patch is specified, show upgrades up to latest patch.
25+
go list -u=patch -m all
26+
stdout '^rsc.io/quote v1.2.0 \[v1.2.1\]$'
27+
28+
# When -u=patch is specified but the module is already at the latest patch,
29+
# don't show an upgrade option.
30+
go mod edit -require=rsc.io/quote v1.2.1
31+
go mod download rsc.io/quote
32+
go list -u patch -m all
33+
stdout '^rsc.io/quote v1.2.0$'
34+
35+
# When -u is specified, show minor.patch upgrades for adjacent modules too.
36+
# (we are going to cloud.google.com/go/compute by way of golang.org/x/oauth2)
37+
go list -u -m all
38+
stdout '^cloud.google.com/go/compute v1.7.0 \[v1.10.0\]$'
39+
40+
# When -u=patch is specified, show patch upgrades for adjacent modules too.
41+
# (we are going to cloud.google.com/go/compute by way of golang.org/x/oauth2)
42+
go list -u=patch -m all
43+
stdout '^cloud.google.com/go/compute v1.7.0$'
44+
45+
-- go.mod --
46+
module x
47+
require (
48+
rsc.io/quote v1.2.0
49+
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
50+
)
51+
52+
-- go.sum --
53+
rsc.io/quote v1.2.0 h1:fFMCNi0A97hfNrtUZVQKETbuc3h7bmfFQHnjutpPYCg=
54+
rsc.io/quote v1.2.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
55+
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA=
56+
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
57+
-- use.go --
58+
package use
59+
60+
import _ "rsc.io/quote"
61+
import _ "golang.org/x/oauth2"

0 commit comments

Comments
 (0)