github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/go/internal/get/get.go (about)

     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  // Package get implements the ``go get'' command.
     6  package get
     7  
     8  import (
     9  	"fmt"
    10  	"go/build"
    11  	"os"
    12  	"path/filepath"
    13  	"regexp"
    14  	"runtime"
    15  	"strconv"
    16  	"strings"
    17  
    18  	"cmd/go/internal/base"
    19  	"cmd/go/internal/cfg"
    20  	"cmd/go/internal/load"
    21  	"cmd/go/internal/str"
    22  	"cmd/go/internal/web"
    23  	"cmd/go/internal/work"
    24  )
    25  
    26  var CmdGet = &base.Command{
    27  	UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
    28  	Short:     "download and install packages and dependencies",
    29  	Long: `
    30  Get downloads the packages named by the import paths, along with their
    31  dependencies. It then installs the named packages, like 'go install'.
    32  
    33  The -d flag instructs get to stop after downloading the packages; that is,
    34  it instructs get not to install the packages.
    35  
    36  The -f flag, valid only when -u is set, forces get -u not to verify that
    37  each package has been checked out from the source control repository
    38  implied by its import path. This can be useful if the source is a local fork
    39  of the original.
    40  
    41  The -fix flag instructs get to run the fix tool on the downloaded packages
    42  before resolving dependencies or building the code.
    43  
    44  The -insecure flag permits fetching from repositories and resolving
    45  custom domains using insecure schemes such as HTTP. Use with caution.
    46  
    47  The -t flag instructs get to also download the packages required to build
    48  the tests for the specified packages.
    49  
    50  The -u flag instructs get to use the network to update the named packages
    51  and their dependencies.  By default, get uses the network to check out
    52  missing packages but does not use it to look for updates to existing packages.
    53  
    54  The -v flag enables verbose progress and debug output.
    55  
    56  Get also accepts build flags to control the installation. See 'go help build'.
    57  
    58  When checking out a new package, get creates the target directory
    59  GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
    60  get uses the first one. For more details see: 'go help gopath'.
    61  
    62  When checking out or updating a package, get looks for a branch or tag
    63  that matches the locally installed version of Go. The most important
    64  rule is that if the local installation is running version "go1", get
    65  searches for a branch or tag named "go1". If no such version exists it
    66  retrieves the most recent version of the package.
    67  
    68  When go get checks out or updates a Git repository,
    69  it also updates any git submodules referenced by the repository.
    70  
    71  Get never checks out or updates code stored in vendor directories.
    72  
    73  For more about specifying packages, see 'go help packages'.
    74  
    75  For more about how 'go get' finds source code to
    76  download, see 'go help importpath'.
    77  
    78  See also: go build, go install, go clean.
    79  	`,
    80  }
    81  
    82  var getD = CmdGet.Flag.Bool("d", false, "")
    83  var getF = CmdGet.Flag.Bool("f", false, "")
    84  var getT = CmdGet.Flag.Bool("t", false, "")
    85  var getU = CmdGet.Flag.Bool("u", false, "")
    86  var getFix = CmdGet.Flag.Bool("fix", false, "")
    87  var getInsecure = CmdGet.Flag.Bool("insecure", false, "")
    88  
    89  func init() {
    90  	work.AddBuildFlags(CmdGet)
    91  	CmdGet.Run = runGet // break init loop
    92  }
    93  
    94  func runGet(cmd *base.Command, args []string) {
    95  	if *getF && !*getU {
    96  		base.Fatalf("go get: cannot use -f flag without -u")
    97  	}
    98  
    99  	// Disable any prompting for passwords by Git.
   100  	// Only has an effect for 2.3.0 or later, but avoiding
   101  	// the prompt in earlier versions is just too hard.
   102  	// If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
   103  	// prompting.
   104  	// See golang.org/issue/9341 and golang.org/issue/12706.
   105  	if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
   106  		os.Setenv("GIT_TERMINAL_PROMPT", "0")
   107  	}
   108  
   109  	// Disable any ssh connection pooling by Git.
   110  	// If a Git subprocess forks a child into the background to cache a new connection,
   111  	// that child keeps stdout/stderr open. After the Git subprocess exits,
   112  	// os /exec expects to be able to read from the stdout/stderr pipe
   113  	// until EOF to get all the data that the Git subprocess wrote before exiting.
   114  	// The EOF doesn't come until the child exits too, because the child
   115  	// is holding the write end of the pipe.
   116  	// This is unfortunate, but it has come up at least twice
   117  	// (see golang.org/issue/13453 and golang.org/issue/16104)
   118  	// and confuses users when it does.
   119  	// If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND,
   120  	// assume they know what they are doing and don't step on it.
   121  	// But default to turning off ControlMaster.
   122  	if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
   123  		os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
   124  	}
   125  
   126  	// Phase 1.  Download/update.
   127  	var stk load.ImportStack
   128  	mode := 0
   129  	if *getT {
   130  		mode |= load.GetTestDeps
   131  	}
   132  	args = downloadPaths(args)
   133  	for _, arg := range args {
   134  		download(arg, nil, &stk, mode)
   135  	}
   136  	base.ExitIfErrors()
   137  
   138  	// Phase 2. Rescan packages and re-evaluate args list.
   139  
   140  	// Code we downloaded and all code that depends on it
   141  	// needs to be evicted from the package cache so that
   142  	// the information will be recomputed. Instead of keeping
   143  	// track of the reverse dependency information, evict
   144  	// everything.
   145  	load.ClearPackageCache()
   146  
   147  	// In order to rebuild packages information completely,
   148  	// we need to clear commands cache. Command packages are
   149  	// referring to evicted packages from the package cache.
   150  	// This leads to duplicated loads of the standard packages.
   151  	load.ClearCmdCache()
   152  
   153  	args = load.ImportPaths(args)
   154  	load.PackagesForBuild(args)
   155  
   156  	// Phase 3.  Install.
   157  	if *getD {
   158  		// Download only.
   159  		// Check delayed until now so that importPaths
   160  		// and packagesForBuild have a chance to print errors.
   161  		return
   162  	}
   163  
   164  	work.InstallPackages(args, true)
   165  }
   166  
   167  // downloadPaths prepares the list of paths to pass to download.
   168  // It expands ... patterns that can be expanded. If there is no match
   169  // for a particular pattern, downloadPaths leaves it in the result list,
   170  // in the hope that we can figure out the repository from the
   171  // initial ...-free prefix.
   172  func downloadPaths(args []string) []string {
   173  	args = load.ImportPathsNoDotExpansion(args)
   174  	var out []string
   175  	for _, a := range args {
   176  		if strings.Contains(a, "...") {
   177  			var expand []string
   178  			// Use matchPackagesInFS to avoid printing
   179  			// warnings. They will be printed by the
   180  			// eventual call to importPaths instead.
   181  			if build.IsLocalImport(a) {
   182  				expand = load.MatchPackagesInFS(a)
   183  			} else {
   184  				expand = load.MatchPackages(a)
   185  			}
   186  			if len(expand) > 0 {
   187  				out = append(out, expand...)
   188  				continue
   189  			}
   190  		}
   191  		out = append(out, a)
   192  	}
   193  	return out
   194  }
   195  
   196  // downloadCache records the import paths we have already
   197  // considered during the download, to avoid duplicate work when
   198  // there is more than one dependency sequence leading to
   199  // a particular package.
   200  var downloadCache = map[string]bool{}
   201  
   202  // downloadRootCache records the version control repository
   203  // root directories we have already considered during the download.
   204  // For example, all the packages in the github.com/google/codesearch repo
   205  // share the same root (the directory for that path), and we only need
   206  // to run the hg commands to consider each repository once.
   207  var downloadRootCache = map[string]bool{}
   208  
   209  // download runs the download half of the get command
   210  // for the package named by the argument.
   211  func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
   212  	if mode&load.UseVendor != 0 {
   213  		// Caller is responsible for expanding vendor paths.
   214  		panic("internal error: download mode has useVendor set")
   215  	}
   216  	load1 := func(path string, mode int) *load.Package {
   217  		if parent == nil {
   218  			return load.LoadPackage(path, stk)
   219  		}
   220  		return load.LoadImport(path, parent.Dir, parent, stk, nil, mode)
   221  	}
   222  
   223  	p := load1(arg, mode)
   224  	if p.Error != nil && p.Error.Hard {
   225  		base.Errorf("%s", p.Error)
   226  		return
   227  	}
   228  
   229  	// loadPackage inferred the canonical ImportPath from arg.
   230  	// Use that in the following to prevent hysteresis effects
   231  	// in e.g. downloadCache and packageCache.
   232  	// This allows invocations such as:
   233  	//   mkdir -p $GOPATH/src/github.com/user
   234  	//   cd $GOPATH/src/github.com/user
   235  	//   go get ./foo
   236  	// see: golang.org/issue/9767
   237  	arg = p.ImportPath
   238  
   239  	// There's nothing to do if this is a package in the standard library.
   240  	if p.Standard {
   241  		return
   242  	}
   243  
   244  	// Only process each package once.
   245  	// (Unless we're fetching test dependencies for this package,
   246  	// in which case we want to process it again.)
   247  	if downloadCache[arg] && mode&load.GetTestDeps == 0 {
   248  		return
   249  	}
   250  	downloadCache[arg] = true
   251  
   252  	pkgs := []*load.Package{p}
   253  	wildcardOkay := len(*stk) == 0
   254  	isWildcard := false
   255  
   256  	// Download if the package is missing, or update if we're using -u.
   257  	if p.Dir == "" || *getU {
   258  		// The actual download.
   259  		stk.Push(arg)
   260  		err := downloadPackage(p)
   261  		if err != nil {
   262  			base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()})
   263  			stk.Pop()
   264  			return
   265  		}
   266  		stk.Pop()
   267  
   268  		args := []string{arg}
   269  		// If the argument has a wildcard in it, re-evaluate the wildcard.
   270  		// We delay this until after reloadPackage so that the old entry
   271  		// for p has been replaced in the package cache.
   272  		if wildcardOkay && strings.Contains(arg, "...") {
   273  			if build.IsLocalImport(arg) {
   274  				args = load.MatchPackagesInFS(arg)
   275  			} else {
   276  				args = load.MatchPackages(arg)
   277  			}
   278  			isWildcard = true
   279  		}
   280  
   281  		// Clear all relevant package cache entries before
   282  		// doing any new loads.
   283  		load.ClearPackageCachePartial(args)
   284  
   285  		pkgs = pkgs[:0]
   286  		for _, arg := range args {
   287  			// Note: load calls loadPackage or loadImport,
   288  			// which push arg onto stk already.
   289  			// Do not push here too, or else stk will say arg imports arg.
   290  			p := load1(arg, mode)
   291  			if p.Error != nil {
   292  				base.Errorf("%s", p.Error)
   293  				continue
   294  			}
   295  			pkgs = append(pkgs, p)
   296  		}
   297  	}
   298  
   299  	// Process package, which might now be multiple packages
   300  	// due to wildcard expansion.
   301  	for _, p := range pkgs {
   302  		if *getFix {
   303  			base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), base.RelPaths(p.Internal.AllGoFiles)))
   304  
   305  			// The imports might have changed, so reload again.
   306  			p = load.ReloadPackage(arg, stk)
   307  			if p.Error != nil {
   308  				base.Errorf("%s", p.Error)
   309  				return
   310  			}
   311  		}
   312  
   313  		if isWildcard {
   314  			// Report both the real package and the
   315  			// wildcard in any error message.
   316  			stk.Push(p.ImportPath)
   317  		}
   318  
   319  		// Process dependencies, now that we know what they are.
   320  		imports := p.Imports
   321  		if mode&load.GetTestDeps != 0 {
   322  			// Process test dependencies when -t is specified.
   323  			// (But don't get test dependencies for test dependencies:
   324  			// we always pass mode 0 to the recursive calls below.)
   325  			imports = str.StringList(imports, p.TestImports, p.XTestImports)
   326  		}
   327  		for i, path := range imports {
   328  			if path == "C" {
   329  				continue
   330  			}
   331  			// Fail fast on import naming full vendor path.
   332  			// Otherwise expand path as needed for test imports.
   333  			// Note that p.Imports can have additional entries beyond p.Internal.Build.Imports.
   334  			orig := path
   335  			if i < len(p.Internal.Build.Imports) {
   336  				orig = p.Internal.Build.Imports[i]
   337  			}
   338  			if j, ok := load.FindVendor(orig); ok {
   339  				stk.Push(path)
   340  				err := &load.PackageError{
   341  					ImportStack: stk.Copy(),
   342  					Err:         "must be imported as " + path[j+len("vendor/"):],
   343  				}
   344  				stk.Pop()
   345  				base.Errorf("%s", err)
   346  				continue
   347  			}
   348  			// If this is a test import, apply vendor lookup now.
   349  			// We cannot pass useVendor to download, because
   350  			// download does caching based on the value of path,
   351  			// so it must be the fully qualified path already.
   352  			if i >= len(p.Imports) {
   353  				path = load.VendoredImportPath(p, path)
   354  			}
   355  			download(path, p, stk, 0)
   356  		}
   357  
   358  		if isWildcard {
   359  			stk.Pop()
   360  		}
   361  	}
   362  }
   363  
   364  // downloadPackage runs the create or download command
   365  // to make the first copy of or update a copy of the given package.
   366  func downloadPackage(p *load.Package) error {
   367  	var (
   368  		vcs            *vcsCmd
   369  		repo, rootPath string
   370  		err            error
   371  	)
   372  
   373  	security := web.Secure
   374  	if *getInsecure {
   375  		security = web.Insecure
   376  	}
   377  
   378  	if p.Internal.Build.SrcRoot != "" {
   379  		// Directory exists. Look for checkout along path to src.
   380  		vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
   381  		if err != nil {
   382  			return err
   383  		}
   384  		repo = "<local>" // should be unused; make distinctive
   385  
   386  		// Double-check where it came from.
   387  		if *getU && vcs.remoteRepo != nil {
   388  			dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
   389  			remote, err := vcs.remoteRepo(vcs, dir)
   390  			if err != nil {
   391  				return err
   392  			}
   393  			repo = remote
   394  			if !*getF {
   395  				if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil {
   396  					repo := rr.repo
   397  					if rr.vcs.resolveRepo != nil {
   398  						resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
   399  						if err == nil {
   400  							repo = resolved
   401  						}
   402  					}
   403  					if remote != repo && rr.isCustom {
   404  						return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
   405  					}
   406  				}
   407  			}
   408  		}
   409  	} else {
   410  		// Analyze the import path to determine the version control system,
   411  		// repository, and the import path for the root of the repository.
   412  		rr, err := repoRootForImportPath(p.ImportPath, security)
   413  		if err != nil {
   414  			return err
   415  		}
   416  		vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
   417  	}
   418  	if !vcs.isSecure(repo) && !*getInsecure {
   419  		return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
   420  	}
   421  
   422  	if p.Internal.Build.SrcRoot == "" {
   423  		// Package not found. Put in first directory of $GOPATH.
   424  		list := filepath.SplitList(cfg.BuildContext.GOPATH)
   425  		if len(list) == 0 {
   426  			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
   427  		}
   428  		// Guard against people setting GOPATH=$GOROOT.
   429  		if list[0] == cfg.GOROOT {
   430  			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
   431  		}
   432  		if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
   433  			return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
   434  		}
   435  		p.Internal.Build.Root = list[0]
   436  		p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
   437  		p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
   438  	}
   439  	root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
   440  	// If we've considered this repository already, don't do it again.
   441  	if downloadRootCache[root] {
   442  		return nil
   443  	}
   444  	downloadRootCache[root] = true
   445  
   446  	if cfg.BuildV {
   447  		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
   448  	}
   449  
   450  	// Check that this is an appropriate place for the repo to be checked out.
   451  	// The target directory must either not exist or have a repo checked out already.
   452  	meta := filepath.Join(root, "."+vcs.cmd)
   453  	st, err := os.Stat(meta)
   454  	if err == nil && !st.IsDir() {
   455  		return fmt.Errorf("%s exists but is not a directory", meta)
   456  	}
   457  	if err != nil {
   458  		// Metadata directory does not exist. Prepare to checkout new copy.
   459  		// Some version control tools require the target directory not to exist.
   460  		// We require that too, just to avoid stepping on existing work.
   461  		if _, err := os.Stat(root); err == nil {
   462  			return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
   463  		}
   464  
   465  		_, err := os.Stat(p.Internal.Build.Root)
   466  		gopathExisted := err == nil
   467  
   468  		// Some version control tools require the parent of the target to exist.
   469  		parent, _ := filepath.Split(root)
   470  		if err = os.MkdirAll(parent, 0777); err != nil {
   471  			return err
   472  		}
   473  		if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH {
   474  			fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
   475  		}
   476  
   477  		if err = vcs.create(root, repo); err != nil {
   478  			return err
   479  		}
   480  	} else {
   481  		// Metadata directory does exist; download incremental updates.
   482  		if err = vcs.download(root); err != nil {
   483  			return err
   484  		}
   485  	}
   486  
   487  	if cfg.BuildN {
   488  		// Do not show tag sync in -n; it's noise more than anything,
   489  		// and since we're not running commands, no tag will be found.
   490  		// But avoid printing nothing.
   491  		fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
   492  		return nil
   493  	}
   494  
   495  	// Select and sync to appropriate version of the repository.
   496  	tags, err := vcs.tags(root)
   497  	if err != nil {
   498  		return err
   499  	}
   500  	vers := runtime.Version()
   501  	if i := strings.Index(vers, " "); i >= 0 {
   502  		vers = vers[:i]
   503  	}
   504  	if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
   505  		return err
   506  	}
   507  
   508  	return nil
   509  }
   510  
   511  // goTag matches go release tags such as go1 and go1.2.3.
   512  // The numbers involved must be small (at most 4 digits),
   513  // have no unnecessary leading zeros, and the version cannot
   514  // end in .0 - it is go1, not go1.0 or go1.0.0.
   515  var goTag = regexp.MustCompile(
   516  	`^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
   517  )
   518  
   519  // selectTag returns the closest matching tag for a given version.
   520  // Closest means the latest one that is not after the current release.
   521  // Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
   522  // Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
   523  // Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
   524  //
   525  // NOTE(rsc): Eventually we will need to decide on some logic here.
   526  // For now, there is only "go1".  This matches the docs in go help get.
   527  func selectTag(goVersion string, tags []string) (match string) {
   528  	for _, t := range tags {
   529  		if t == "go1" {
   530  			return "go1"
   531  		}
   532  	}
   533  	return ""
   534  
   535  	/*
   536  		if goTag.MatchString(goVersion) {
   537  			v := goVersion
   538  			for _, t := range tags {
   539  				if !goTag.MatchString(t) {
   540  					continue
   541  				}
   542  				if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
   543  					match = t
   544  				}
   545  			}
   546  		}
   547  
   548  		return match
   549  	*/
   550  }
   551  
   552  // cmpGoVersion returns -1, 0, +1 reporting whether
   553  // x < y, x == y, or x > y.
   554  func cmpGoVersion(x, y string) int {
   555  	// Malformed strings compare less than well-formed strings.
   556  	if !goTag.MatchString(x) {
   557  		return -1
   558  	}
   559  	if !goTag.MatchString(y) {
   560  		return +1
   561  	}
   562  
   563  	// Compare numbers in sequence.
   564  	xx := strings.Split(x[len("go"):], ".")
   565  	yy := strings.Split(y[len("go"):], ".")
   566  
   567  	for i := 0; i < len(xx) && i < len(yy); i++ {
   568  		// The Atoi are guaranteed to succeed
   569  		// because the versions match goTag.
   570  		xi, _ := strconv.Atoi(xx[i])
   571  		yi, _ := strconv.Atoi(yy[i])
   572  		if xi < yi {
   573  			return -1
   574  		} else if xi > yi {
   575  			return +1
   576  		}
   577  	}
   578  
   579  	if len(xx) < len(yy) {
   580  		return -1
   581  	}
   582  	if len(xx) > len(yy) {
   583  		return +1
   584  	}
   585  	return 0
   586  }