Skip to content

Commit 6e3df74

Browse files
author
Jay Conrod
committed
cmd/go: refactor -mod flag parsing
Keep track of whether the -mod flag was set explicitly. When -mod=readonly is the default, we'll want to adjust our error messages if it's set explicitly. Also, register the -mod, -modcacherw, and -modfile flags in functions in internal/base instead of internal/work. 'go mod' commands that don't load packages shouldn't depend on internal/work. For #40728 Change-Id: I272aea9e19908ba37e151baac4ea8630e90f241f Reviewed-on: https://go-review.googlesource.com/c/go/+/253744 Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent b22af9b commit 6e3df74

File tree

14 files changed

+61
-43
lines changed

14 files changed

+61
-43
lines changed

src/cmd/go/internal/base/flag.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,42 @@ func (v *StringsFlag) String() string {
2828
return "<StringsFlag>"
2929
}
3030

31+
// explicitStringFlag is like a regular string flag, but it also tracks whether
32+
// the string was set explicitly to a non-empty value.
33+
type explicitStringFlag struct {
34+
value *string
35+
explicit *bool
36+
}
37+
38+
func (f explicitStringFlag) String() string {
39+
if f.value == nil {
40+
return ""
41+
}
42+
return *f.value
43+
}
44+
45+
func (f explicitStringFlag) Set(v string) error {
46+
*f.value = v
47+
if v != "" {
48+
*f.explicit = true
49+
}
50+
return nil
51+
}
52+
3153
// AddBuildFlagsNX adds the -n and -x build flags to the flag set.
3254
func AddBuildFlagsNX(flags *flag.FlagSet) {
3355
flags.BoolVar(&cfg.BuildN, "n", false, "")
3456
flags.BoolVar(&cfg.BuildX, "x", false, "")
3557
}
3658

37-
// AddLoadFlags adds the -mod build flag to the flag set.
38-
func AddLoadFlags(flags *flag.FlagSet) {
39-
flags.StringVar(&cfg.BuildMod, "mod", "", "")
59+
// AddModFlag adds the -mod build flag to the flag set.
60+
func AddModFlag(flags *flag.FlagSet) {
61+
flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "")
62+
}
63+
64+
// AddModCommonFlags adds the module-related flags common to build commands
65+
// and 'go mod' subcommands.
66+
func AddModCommonFlags(flags *flag.FlagSet) {
67+
flags.BoolVar(&cfg.ModCacheRW, "modcacherw", false, "")
68+
flags.StringVar(&cfg.ModFile, "modfile", "", "")
4069
}

src/cmd/go/internal/cfg/cfg.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ var (
2727
BuildBuildmode string // -buildmode flag
2828
BuildContext = defaultContext()
2929
BuildMod string // -mod flag
30-
BuildModReason string // reason -mod flag is set, if set by default
30+
BuildModExplicit bool // whether -mod was set explicitly
31+
BuildModReason string // reason -mod was set, if set by default
3132
BuildI bool // -i flag
3233
BuildLinkshared bool // -linkshared flag
3334
BuildMSan bool // -msan flag

src/cmd/go/internal/fmtcmd/fmt.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import (
2323

2424
func init() {
2525
base.AddBuildFlagsNX(&CmdFmt.Flag)
26-
base.AddLoadFlags(&CmdFmt.Flag)
26+
base.AddModFlag(&CmdFmt.Flag)
27+
base.AddModCommonFlags(&CmdFmt.Flag)
2728
}
2829

2930
var CmdFmt = &base.Command{

src/cmd/go/internal/modcmd/download.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"cmd/go/internal/cfg"
1515
"cmd/go/internal/modfetch"
1616
"cmd/go/internal/modload"
17-
"cmd/go/internal/work"
1817

1918
"golang.org/x/mod/module"
2019
)
@@ -64,7 +63,7 @@ func init() {
6463

6564
// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
6665
cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
67-
work.AddModCommonFlags(cmdDownload)
66+
base.AddModCommonFlags(&cmdDownload.Flag)
6867
}
6968

7069
type moduleJSON struct {

src/cmd/go/internal/modcmd/edit.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"cmd/go/internal/lockedfile"
2020
"cmd/go/internal/modfetch"
2121
"cmd/go/internal/modload"
22-
"cmd/go/internal/work"
2322

2423
"golang.org/x/mod/modfile"
2524
"golang.org/x/mod/module"
@@ -154,7 +153,7 @@ func init() {
154153
cmdEdit.Flag.Var(flagFunc(flagRetract), "retract", "")
155154
cmdEdit.Flag.Var(flagFunc(flagDropRetract), "dropretract", "")
156155

157-
work.AddModCommonFlags(cmdEdit)
156+
base.AddModCommonFlags(&cmdEdit.Flag)
158157
base.AddBuildFlagsNX(&cmdEdit.Flag)
159158
}
160159

src/cmd/go/internal/modcmd/graph.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"cmd/go/internal/base"
1616
"cmd/go/internal/cfg"
1717
"cmd/go/internal/modload"
18-
"cmd/go/internal/work"
1918

2019
"golang.org/x/mod/module"
2120
)
@@ -33,7 +32,7 @@ path@version, except for the main module, which has no @version suffix.
3332
}
3433

3534
func init() {
36-
work.AddModCommonFlags(cmdGraph)
35+
base.AddModCommonFlags(&cmdGraph.Flag)
3736
}
3837

3938
func runGraph(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modcmd/init.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package modcmd
99
import (
1010
"cmd/go/internal/base"
1111
"cmd/go/internal/modload"
12-
"cmd/go/internal/work"
1312
"context"
1413
"os"
1514
"strings"
@@ -30,7 +29,7 @@ To override this guess, supply the module path as an argument.
3029
}
3130

3231
func init() {
33-
work.AddModCommonFlags(cmdInit)
32+
base.AddModCommonFlags(&cmdInit.Flag)
3433
}
3534

3635
func runInit(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modcmd/tidy.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"cmd/go/internal/base"
1111
"cmd/go/internal/cfg"
1212
"cmd/go/internal/modload"
13-
"cmd/go/internal/work"
1413
"context"
1514
)
1615

@@ -32,7 +31,7 @@ to standard error.
3231
func init() {
3332
cmdTidy.Run = runTidy // break init cycle
3433
cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
35-
work.AddModCommonFlags(cmdTidy)
34+
base.AddModCommonFlags(&cmdTidy.Flag)
3635
}
3736

3837
func runTidy(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modcmd/vendor.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"cmd/go/internal/cfg"
2020
"cmd/go/internal/imports"
2121
"cmd/go/internal/modload"
22-
"cmd/go/internal/work"
2322

2423
"golang.org/x/mod/module"
2524
"golang.org/x/mod/semver"
@@ -41,7 +40,7 @@ modules and packages to standard error.
4140

4241
func init() {
4342
cmdVendor.Flag.BoolVar(&cfg.BuildV, "v", false, "")
44-
work.AddModCommonFlags(cmdVendor)
43+
base.AddModCommonFlags(&cmdVendor.Flag)
4544
}
4645

4746
func runVendor(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modcmd/verify.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"cmd/go/internal/cfg"
1818
"cmd/go/internal/modfetch"
1919
"cmd/go/internal/modload"
20-
"cmd/go/internal/work"
2120

2221
"golang.org/x/mod/module"
2322
"golang.org/x/mod/sumdb/dirhash"
@@ -38,7 +37,7 @@ non-zero status.
3837
}
3938

4039
func init() {
41-
work.AddModCommonFlags(cmdVerify)
40+
base.AddModCommonFlags(&cmdVerify.Flag)
4241
}
4342

4443
func runVerify(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modcmd/why.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111

1212
"cmd/go/internal/base"
1313
"cmd/go/internal/modload"
14-
"cmd/go/internal/work"
1514

1615
"golang.org/x/mod/module"
1716
)
@@ -58,7 +57,7 @@ var (
5857

5958
func init() {
6059
cmdWhy.Run = runWhy // break init cycle
61-
work.AddModCommonFlags(cmdWhy)
60+
base.AddModCommonFlags(&cmdWhy.Flag)
6261
}
6362

6463
func runWhy(ctx context.Context, cmd *base.Command, args []string) {

src/cmd/go/internal/modload/init.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -518,17 +518,20 @@ func modFileToBuildList() {
518518
// setDefaultBuildMod sets a default value for cfg.BuildMod
519519
// if it is currently empty.
520520
func setDefaultBuildMod() {
521-
if cfg.BuildMod != "" {
521+
if cfg.BuildModExplicit {
522522
// Don't override an explicit '-mod=' argument.
523523
return
524524
}
525-
cfg.BuildMod = "mod"
525+
526526
if cfg.CmdName == "get" || strings.HasPrefix(cfg.CmdName, "mod ") {
527-
// Don't set -mod implicitly for commands whose purpose is to
528-
// manipulate the build list.
527+
// 'get' and 'go mod' commands may update go.mod automatically.
528+
// TODO(jayconrod): should this narrower? Should 'go mod download' or
529+
// 'go mod graph' update go.mod by default?
530+
cfg.BuildMod = "mod"
529531
return
530532
}
531533
if modRoot == "" {
534+
cfg.BuildMod = "mod"
532535
return
533536
}
534537

@@ -546,18 +549,18 @@ func setDefaultBuildMod() {
546549
}
547550
}
548551

549-
// Since a vendor directory exists, we have a non-trivial reason for
550-
// choosing -mod=mod, although it probably won't be used for anything.
551-
// Record the reason anyway for consistency.
552-
// It may be overridden if we switch to mod=readonly below.
553-
cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s.", modGo)
552+
// Since a vendor directory exists, we should record why we didn't use it.
553+
// This message won't normally be shown, but it may appear with import errors.
554+
cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s, so vendor directory was not used.", modGo)
554555
}
555556

556557
p := ModFilePath()
557558
if fi, err := os.Stat(p); err == nil && !hasWritePerm(p, fi) {
558559
cfg.BuildMod = "readonly"
559560
cfg.BuildModReason = "go.mod file is read-only."
561+
return
560562
}
563+
cfg.BuildMod = "mod"
561564
}
562565

563566
func legacyModInit() {
@@ -857,7 +860,7 @@ func WriteGoMod() {
857860
// prefer to report a dirty go.mod over a dirty go.sum
858861
if cfg.BuildModReason != "" {
859862
base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly\n\t(%s)", cfg.BuildModReason)
860-
} else {
863+
} else if cfg.BuildModExplicit {
861864
base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly")
862865
}
863866
}

src/cmd/go/internal/work/build.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,24 +240,23 @@ const (
240240
// AddBuildFlags adds the flags common to the build, clean, get,
241241
// install, list, run, and test commands.
242242
func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
243+
base.AddBuildFlagsNX(&cmd.Flag)
243244
cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
244-
cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
245245
cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
246246
if mask&OmitVFlag == 0 {
247247
cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
248248
}
249-
cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
250249

251250
cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
252251
cmd.Flag.Var(buildCompiler{}, "compiler", "")
253252
cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
254253
cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
255254
cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
256255
if mask&OmitModFlag == 0 {
257-
cmd.Flag.StringVar(&cfg.BuildMod, "mod", "", "")
256+
base.AddModFlag(&cmd.Flag)
258257
}
259258
if mask&OmitModCommonFlags == 0 {
260-
AddModCommonFlags(cmd)
259+
base.AddModCommonFlags(&cmd.Flag)
261260
}
262261
cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
263262
cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
@@ -275,13 +274,6 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
275274
cmd.Flag.StringVar(&cfg.DebugTrace, "debug-trace", "", "")
276275
}
277276

278-
// AddModCommonFlags adds the module-related flags common to build commands
279-
// and 'go mod' subcommands.
280-
func AddModCommonFlags(cmd *base.Command) {
281-
cmd.Flag.BoolVar(&cfg.ModCacheRW, "modcacherw", false, "")
282-
cmd.Flag.StringVar(&cfg.ModFile, "modfile", "", "")
283-
}
284-
285277
// tagsFlag is the implementation of the -tags flag.
286278
type tagsFlag []string
287279

src/cmd/go/internal/work/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ func buildModeInit() {
252252

253253
switch cfg.BuildMod {
254254
case "":
255-
// ok
255+
// Behavior will be determined automatically, as if no flag were passed.
256256
case "readonly", "vendor", "mod":
257257
if !cfg.ModulesEnabled && !inGOFLAGS("-mod") {
258258
base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod)

0 commit comments

Comments
 (0)