Source file
src/cmd/go/main.go
Documentation: cmd/go
1
2
3
4
5
6
7 package main
8
9 import (
10 "context"
11 "flag"
12 "fmt"
13 "internal/buildcfg"
14 "log"
15 "os"
16 "path/filepath"
17 "runtime"
18 "strings"
19
20 "cmd/go/internal/base"
21 "cmd/go/internal/bug"
22 "cmd/go/internal/cfg"
23 "cmd/go/internal/clean"
24 "cmd/go/internal/doc"
25 "cmd/go/internal/envcmd"
26 "cmd/go/internal/fix"
27 "cmd/go/internal/fmtcmd"
28 "cmd/go/internal/generate"
29 "cmd/go/internal/get"
30 "cmd/go/internal/help"
31 "cmd/go/internal/list"
32 "cmd/go/internal/modcmd"
33 "cmd/go/internal/modfetch"
34 "cmd/go/internal/modget"
35 "cmd/go/internal/modload"
36 "cmd/go/internal/run"
37 "cmd/go/internal/test"
38 "cmd/go/internal/tool"
39 "cmd/go/internal/trace"
40 "cmd/go/internal/version"
41 "cmd/go/internal/vet"
42 "cmd/go/internal/work"
43 )
44
45 func init() {
46 base.Go.Commands = []*base.Command{
47 bug.CmdBug,
48 work.CmdBuild,
49 clean.CmdClean,
50 doc.CmdDoc,
51 envcmd.CmdEnv,
52 fix.CmdFix,
53 fmtcmd.CmdFmt,
54 generate.CmdGenerate,
55 modget.CmdGet,
56 work.CmdInstall,
57 list.CmdList,
58 modcmd.CmdMod,
59 run.CmdRun,
60 test.CmdTest,
61 tool.CmdTool,
62 version.CmdVersion,
63 vet.CmdVet,
64
65 help.HelpBuildConstraint,
66 help.HelpBuildmode,
67 help.HelpC,
68 help.HelpCache,
69 help.HelpEnvironment,
70 help.HelpFileType,
71 modload.HelpGoMod,
72 help.HelpGopath,
73 get.HelpGopathGet,
74 modfetch.HelpGoproxy,
75 help.HelpImportPath,
76 modload.HelpModules,
77 modget.HelpModuleGet,
78 modfetch.HelpModuleAuth,
79 help.HelpPackages,
80 modfetch.HelpPrivate,
81 test.HelpTestflag,
82 test.HelpTestfunc,
83 modget.HelpVCS,
84 }
85 }
86
87 func main() {
88 _ = go11tag
89 flag.Usage = base.Usage
90 flag.Parse()
91 log.SetFlags(0)
92
93 args := flag.Args()
94 if len(args) < 1 {
95 base.Usage()
96 }
97
98 if args[0] == "get" || args[0] == "help" {
99 if !modload.WillBeEnabled() {
100
101 *modget.CmdGet = *get.CmdGet
102 }
103 }
104
105 cfg.CmdName = args[0]
106 if args[0] == "help" {
107 help.Help(os.Stdout, args[1:])
108 return
109 }
110
111
112
113
114 if gopath := cfg.BuildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
115 fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
116 } else {
117 for _, p := range filepath.SplitList(gopath) {
118
119
120 if p == "" {
121 continue
122 }
123
124
125
126 if strings.HasPrefix(p, "~") {
127 fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
128 os.Exit(2)
129 }
130 if !filepath.IsAbs(p) {
131 if cfg.Getenv("GOPATH") == "" {
132
133
134 cfg.BuildContext.GOPATH = ""
135 } else {
136 fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nFor more details see: 'go help gopath'\n", p)
137 os.Exit(2)
138 }
139 }
140 }
141 }
142
143 if fi, err := os.Stat(cfg.GOROOT); err != nil || !fi.IsDir() {
144 fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", cfg.GOROOT)
145 os.Exit(2)
146 }
147
148 BigCmdLoop:
149 for bigCmd := base.Go; ; {
150 for _, cmd := range bigCmd.Commands {
151 if cmd.Name() != args[0] {
152 continue
153 }
154 if len(cmd.Commands) > 0 {
155 bigCmd = cmd
156 args = args[1:]
157 if len(args) == 0 {
158 help.PrintUsage(os.Stderr, bigCmd)
159 base.SetExitStatus(2)
160 base.Exit()
161 }
162 if args[0] == "help" {
163
164 help.Help(os.Stdout, append(strings.Split(cfg.CmdName, " "), args[1:]...))
165 return
166 }
167 cfg.CmdName += " " + args[0]
168 continue BigCmdLoop
169 }
170 if !cmd.Runnable() {
171 continue
172 }
173 invoke(cmd, args)
174 base.Exit()
175 return
176 }
177 helpArg := ""
178 if i := strings.LastIndex(cfg.CmdName, " "); i >= 0 {
179 helpArg = " " + cfg.CmdName[:i]
180 }
181 fmt.Fprintf(os.Stderr, "go %s: unknown command\nRun 'go help%s' for usage.\n", cfg.CmdName, helpArg)
182 base.SetExitStatus(2)
183 base.Exit()
184 }
185 }
186
187 func invoke(cmd *base.Command, args []string) {
188
189 if cmd != envcmd.CmdEnv {
190 buildcfg.Check()
191 }
192
193
194
195
196
197
198 cfg.OrigEnv = os.Environ()
199 cfg.CmdEnv = envcmd.MkEnv()
200 for _, env := range cfg.CmdEnv {
201 if os.Getenv(env.Name) != env.Value {
202 os.Setenv(env.Name, env.Value)
203 }
204 }
205
206 cmd.Flag.Usage = func() { cmd.Usage() }
207 if cmd.CustomFlags {
208 args = args[1:]
209 } else {
210 base.SetFromGOFLAGS(&cmd.Flag)
211 cmd.Flag.Parse(args[1:])
212 args = cmd.Flag.Args()
213 }
214 ctx := maybeStartTrace(context.Background())
215 ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
216 cmd.Run(ctx, cmd, args)
217 span.Done()
218 }
219
220 func init() {
221 base.Usage = mainUsage
222 }
223
224 func mainUsage() {
225 help.PrintUsage(os.Stderr, base.Go)
226 os.Exit(2)
227 }
228
229 func maybeStartTrace(pctx context.Context) context.Context {
230 if cfg.DebugTrace == "" {
231 return pctx
232 }
233
234 ctx, close, err := trace.Start(pctx, cfg.DebugTrace)
235 if err != nil {
236 base.Fatalf("failed to start trace: %v", err)
237 }
238 base.AtExit(func() {
239 if err := close(); err != nil {
240 base.Fatalf("failed to stop trace: %v", err)
241 }
242 })
243
244 return ctx
245 }
246
View as plain text