...

Source file src/cmd/go/main.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	//go:generate ./mkalldocs.sh
     6	
     7	package main
     8	
     9	import (
    10		"flag"
    11		"fmt"
    12		"log"
    13		"os"
    14		"path/filepath"
    15		"runtime"
    16		"strings"
    17	
    18		"cmd/go/internal/base"
    19		"cmd/go/internal/bug"
    20		"cmd/go/internal/cfg"
    21		"cmd/go/internal/clean"
    22		"cmd/go/internal/doc"
    23		"cmd/go/internal/envcmd"
    24		"cmd/go/internal/fix"
    25		"cmd/go/internal/fmtcmd"
    26		"cmd/go/internal/generate"
    27		"cmd/go/internal/get"
    28		"cmd/go/internal/help"
    29		"cmd/go/internal/list"
    30		"cmd/go/internal/modcmd"
    31		"cmd/go/internal/modfetch"
    32		"cmd/go/internal/modget"
    33		"cmd/go/internal/modload"
    34		"cmd/go/internal/run"
    35		"cmd/go/internal/test"
    36		"cmd/go/internal/tool"
    37		"cmd/go/internal/version"
    38		"cmd/go/internal/vet"
    39		"cmd/go/internal/work"
    40	)
    41	
    42	func init() {
    43		base.Go.Commands = []*base.Command{
    44			bug.CmdBug,
    45			work.CmdBuild,
    46			clean.CmdClean,
    47			doc.CmdDoc,
    48			envcmd.CmdEnv,
    49			fix.CmdFix,
    50			fmtcmd.CmdFmt,
    51			generate.CmdGenerate,
    52			modget.CmdGet,
    53			work.CmdInstall,
    54			list.CmdList,
    55			modcmd.CmdMod,
    56			run.CmdRun,
    57			test.CmdTest,
    58			tool.CmdTool,
    59			version.CmdVersion,
    60			vet.CmdVet,
    61	
    62			help.HelpBuildmode,
    63			help.HelpC,
    64			help.HelpCache,
    65			help.HelpEnvironment,
    66			help.HelpFileType,
    67			modload.HelpGoMod,
    68			help.HelpGopath,
    69			get.HelpGopathGet,
    70			modfetch.HelpGoproxy,
    71			help.HelpImportPath,
    72			modload.HelpModules,
    73			modget.HelpModuleGet,
    74			modfetch.HelpModuleAuth,
    75			modfetch.HelpModulePrivate,
    76			help.HelpPackages,
    77			test.HelpTestflag,
    78			test.HelpTestfunc,
    79		}
    80	}
    81	
    82	func main() {
    83		_ = go11tag
    84		flag.Usage = base.Usage
    85		flag.Parse()
    86		log.SetFlags(0)
    87	
    88		args := flag.Args()
    89		if len(args) < 1 {
    90			base.Usage()
    91		}
    92	
    93		if args[0] == "get" || args[0] == "help" {
    94			if modload.Init(); !modload.Enabled() {
    95				// Replace module-aware get with GOPATH get if appropriate.
    96				*modget.CmdGet = *get.CmdGet
    97			}
    98		}
    99	
   100		cfg.CmdName = args[0] // for error messages
   101		if args[0] == "help" {
   102			help.Help(os.Stdout, args[1:])
   103			return
   104		}
   105	
   106		// Diagnose common mistake: GOPATH==GOROOT.
   107		// This setting is equivalent to not setting GOPATH at all,
   108		// which is not what most people want when they do it.
   109		if gopath := cfg.BuildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
   110			fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
   111		} else {
   112			for _, p := range filepath.SplitList(gopath) {
   113				// Some GOPATHs have empty directory elements - ignore them.
   114				// See issue 21928 for details.
   115				if p == "" {
   116					continue
   117				}
   118				// Note: using HasPrefix instead of Contains because a ~ can appear
   119				// in the middle of directory elements, such as /tmp/git-1.8.2~rc3
   120				// or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell.
   121				if strings.HasPrefix(p, "~") {
   122					fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
   123					os.Exit(2)
   124				}
   125				if !filepath.IsAbs(p) {
   126					if cfg.Getenv("GOPATH") == "" {
   127						// We inferred $GOPATH from $HOME and did a bad job at it.
   128						// Instead of dying, uninfer it.
   129						cfg.BuildContext.GOPATH = ""
   130					} else {
   131						fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nFor more details see: 'go help gopath'\n", p)
   132						os.Exit(2)
   133					}
   134				}
   135			}
   136		}
   137	
   138		if fi, err := os.Stat(cfg.GOROOT); err != nil || !fi.IsDir() {
   139			fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", cfg.GOROOT)
   140			os.Exit(2)
   141		}
   142	
   143		// Set environment (GOOS, GOARCH, etc) explicitly.
   144		// In theory all the commands we invoke should have
   145		// the same default computation of these as we do,
   146		// but in practice there might be skew
   147		// This makes sure we all agree.
   148		cfg.OrigEnv = os.Environ()
   149		cfg.CmdEnv = envcmd.MkEnv()
   150		for _, env := range cfg.CmdEnv {
   151			if os.Getenv(env.Name) != env.Value {
   152				os.Setenv(env.Name, env.Value)
   153			}
   154		}
   155	
   156	BigCmdLoop:
   157		for bigCmd := base.Go; ; {
   158			for _, cmd := range bigCmd.Commands {
   159				if cmd.Name() != args[0] {
   160					continue
   161				}
   162				if len(cmd.Commands) > 0 {
   163					bigCmd = cmd
   164					args = args[1:]
   165					if len(args) == 0 {
   166						help.PrintUsage(os.Stderr, bigCmd)
   167						base.SetExitStatus(2)
   168						base.Exit()
   169					}
   170					if args[0] == "help" {
   171						// Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'.
   172						help.Help(os.Stdout, append(strings.Split(cfg.CmdName, " "), args[1:]...))
   173						return
   174					}
   175					cfg.CmdName += " " + args[0]
   176					continue BigCmdLoop
   177				}
   178				if !cmd.Runnable() {
   179					continue
   180				}
   181				cmd.Flag.Usage = func() { cmd.Usage() }
   182				if cmd.CustomFlags {
   183					args = args[1:]
   184				} else {
   185					base.SetFromGOFLAGS(cmd.Flag)
   186					cmd.Flag.Parse(args[1:])
   187					args = cmd.Flag.Args()
   188				}
   189				cmd.Run(cmd, args)
   190				base.Exit()
   191				return
   192			}
   193			helpArg := ""
   194			if i := strings.LastIndex(cfg.CmdName, " "); i >= 0 {
   195				helpArg = " " + cfg.CmdName[:i]
   196			}
   197			fmt.Fprintf(os.Stderr, "go %s: unknown command\nRun 'go help%s' for usage.\n", cfg.CmdName, helpArg)
   198			base.SetExitStatus(2)
   199			base.Exit()
   200		}
   201	}
   202	
   203	func init() {
   204		base.Usage = mainUsage
   205	}
   206	
   207	func mainUsage() {
   208		help.PrintUsage(os.Stderr, base.Go)
   209		os.Exit(2)
   210	}
   211	

View as plain text