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