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