Skip to content

Commit 6121987

Browse files
committed
cmd/go: split go mod into multiple subcommands
The current "go mod" command does too many things. The design is unclear. It looks like "everything you might want to do with modules" which causes people to think all module operations go through "go mod", which is the opposite of the seamless integration we're going for. In particular too many people think "go mod -require" and "go get" are the same. It does make sense to put the module-specific functionality under "go mod", but not as flags. Instead, split "go mod" into multiple subcommands: go mod edit # old go mod -require ... go mod fix # old go mod -fix go mod graph # old go mod -graph go mod init # old go mod -init go mod tidy # old go mod -sync go mod vendor # old go mod -vendor go mod verify # old go mod -verify Splitting out the individual commands makes both the docs and the implementations dramatically easier to read. It simplifies the command lines (go mod -init -module m is now 'go mod init m') and allows command-specific flags. We've avoided subcommands in the go command to date, and we should continue to avoid adding them unless it really makes the experience significantly better. In this case, it does. Creating subcommands required some changes in the core command-parsing and help logic to generalize from one level to multiple levels. As part of having "go mod init" be a separate command, this CL changes the failure behavior during module initialization to be delayed until modules are actually needed. Initialization can still happen early, but the base.Fatalf is delayed until something needs to use modules. This fixes a bunch of commands like 'go env' that were unhelpfully failing with GO111MODULE=on when not in a module directory. Fixes #26432. Fixes #26581. Fixes #26596. Fixes #26639. Change-Id: I868db0babe8c288e8af684b29d4a5ae4825d6407 Reviewed-on: https://go-review.googlesource.com/126655 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 16962fa commit 6121987

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1225
-850
lines changed

src/cmd/go/alldocs.go

Lines changed: 129 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,43 @@ type Command struct {
4545
// CustomFlags indicates that the command will do its own
4646
// flag parsing.
4747
CustomFlags bool
48+
49+
// Commands lists the available commands and help topics.
50+
// The order here is the order in which they are printed by 'go help'.
51+
// Note that subcommands are in general best avoided.
52+
Commands []*Command
4853
}
4954

50-
// Commands lists the available commands and help topics.
51-
// The order here is the order in which they are printed by 'go help'.
52-
var Commands []*Command
55+
var Go = &Command{
56+
UsageLine: "go",
57+
Long: `Go is a tool for managing Go source code.`,
58+
// Commands initialized in package main
59+
}
5360

54-
// Name returns the command's name: the first word in the usage line.
55-
func (c *Command) Name() string {
61+
// LongName returns the command's long name: all the words in the usage line between "go" and a flag or argument,
62+
func (c *Command) LongName() string {
5663
name := c.UsageLine
57-
i := strings.Index(name, " ")
58-
if i >= 0 {
64+
if i := strings.Index(name, " ["); i >= 0 {
5965
name = name[:i]
6066
}
67+
if name == "go" {
68+
return ""
69+
}
70+
return strings.TrimPrefix(name, "go ")
71+
}
72+
73+
// Name returns the command's short name: the last word in the usage line before a flag or argument.
74+
func (c *Command) Name() string {
75+
name := c.LongName()
76+
if i := strings.LastIndex(name, " "); i >= 0 {
77+
name = name[i+1:]
78+
}
6179
return name
6280
}
6381

6482
func (c *Command) Usage() {
6583
fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine)
66-
fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.Name())
84+
fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName())
6785
os.Exit(2)
6886
}
6987

src/cmd/go/internal/bug/bug.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525

2626
var CmdBug = &base.Command{
2727
Run: runBug,
28-
UsageLine: "bug",
28+
UsageLine: "go bug",
2929
Short: "start a bug report",
3030
Long: `
3131
Bug opens the default browser and starts a new bug report.
@@ -38,6 +38,9 @@ func init() {
3838
}
3939

4040
func runBug(cmd *base.Command, args []string) {
41+
if len(args) > 0 {
42+
base.Fatalf("go bug: bug takes no arguments")
43+
}
4144
var buf bytes.Buffer
4245
buf.WriteString(bugHeader)
4346
inspectGoVersion(&buf)

0 commit comments

Comments
 (0)