github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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 it
    64  retrieves the most recent version 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  	if *getF && !*getU {
    94  		base.Fatalf("go get: cannot use -f flag without -u")
    95  	}
    96  
    97  	// Disable any prompting for passwords by Git.
    98  	// Only has an effect for 2.3.0 or later, but avoiding
    99  	// the prompt in earlier versions is just too hard.
   100  	// If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
   101  	// prompting.
   102  	// See golang.org/issue/9341 and golang.org/issue/12706.
   103  	if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
   104  		os.Setenv("GIT_TERMINAL_PROMPT", "0")
   105  	}
   106  
   107  	// Disable any ssh connection pooling by Git.
   108  	// If a Git subprocess forks a child into the background to cache a new connection,
   109  	// that child keeps stdout/stderr open. After the Git subprocess exits,
   110  	// os /exec expects to be able to read from the stdout/stderr pipe
   111  	// until EOF to get all the data that the Git subprocess wrote before exiting.
   112  	// The EOF doesn't come until the child exits too, because the child
   113  	// is holding the write end of the pipe.
   114  	// This is unfortunate, but it has come up at least twice
   115  	// (see golang.org/issue/13453 and golang.org/issue/16104)
   116  	// and confuses users when it does.
   117  	// If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND,
   118  	// assume they know what they are doing and don't step on it.
   119  	// But default to turning off ControlMaster.
   120  	if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
   121  		os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
   122  	}
   123  
   124  	// Phase 1.  Download/update.
   125  	var stk load.ImportStack
   126  	mode := 0
   127  	if *getT {
   128  		mode |= load.GetTestDeps
   129  	}
   130  	args = downloadPaths(args)
   131  	for _, arg := range args {
   132  		download(arg, nil, &stk, mode)
   133  	}
   134  	base.ExitIfErrors()
   135  
   136  	// Phase 2. Rescan packages and re-evaluate args list.
   137  
   138  	// Code we downloaded and all code that depends on it
   139  	// needs to be evicted from the package cache so that
   140  	// the information will be recomputed. Instead of keeping
   141  	// track of the reverse dependency information, evict
   142  	// everything.
   143  	load.ClearPackageCache()
   144  
   145  	// In order to rebuild packages information completely,
   146  	// we need to clear commands cache. Command packages are
   147  	// referring to evicted packages from the package cache.
   148  	// This leads to duplicated loads of the standard packages.
   149  	load.ClearCmdCache()
   150  
   151  	args = load.ImportPaths(args)
   152  	load.PackagesForBuild(args)
   153  
   154  	// Phase 3.  Install.
   155  	if *getD {
   156  		// Download only.
   157  		// Check delayed until now so that importPaths
   158  		// and packagesForBuild have a chance to print errors.
   159  		return
   160  	}
   161  
   162  	work.InstallPackages(args, true)
   163  }
   164  
   165  // downloadPaths prepares the list of paths to pass to download.
   166  // It expands ... patterns that can be expanded. If there is no match
   167  // for a particular pattern, downloadPaths leaves it in the result list,
   168  // in the hope that we can figure out the repository from the
   169  // initial ...-free prefix.
   170  func downloadPaths(args []string) []string {
   171  	args = load.ImportPathsNoDotExpansion(args)
   172  	var out []string
   173  	for _, a := range args {
   174  		if strings.Contains(a, "...") {
   175  			var expand []string
   176  			// Use matchPackagesInFS to avoid printing
   177  			// warnings. They will be printed by the
   178  			// eventual call to importPaths instead.
   179  			if build.IsLocalImport(a) {
   180  				expand = load.MatchPackagesInFS(a)
   181  			} else {
   182  				expand = load.MatchPackages(a)
   183  			}
   184  			if len(expand) > 0 {
   185  				out = append(out, expand...)
   186  				continue
   187  			}
   188  		}
   189  		out = append(out, a)
   190  	}
   191  	return out
   192  }
   193  
   194  // downloadCache records the import paths we have already
   195  // considered during the download, to avoid duplicate work when
   196  // there is more than one dependency sequence leading to
   197  // a particular package.
   198  var downloadCache = map[string]bool{}
   199  
   200  // downloadRootCache records the version control repository
   201  // root directories we have already considered during the download.
   202  // For example, all the packages in the github.com/google/codesearch repo
   203  // share the same root (the directory for that path), and we only need
   204  // to run the hg commands to consider each repository once.
   205  var downloadRootCache = map[string]bool{}
   206  
   207  // download runs the download half of the get command
   208  // for the package named by the argument.
   209  func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
   210  	if mode&load.UseVendor != 0 {
   211  		// Caller is responsible for expanding vendor paths.
   212  		panic("internal error: download mode has useVendor set")
   213  	}
   214  	load1 := func(path string, mode int) *load.Package {
   215  		if parent == nil {
   216  			return load.LoadPackage(path, stk)
   217  		}
   218  		return load.LoadImport(path, parent.Dir, parent, stk, nil, mode)
   219  	}
   220  
   221  	p := load1(arg, mode)
   222  	if p.Error != nil && p.Error.Hard {
   223  		base.Errorf("%s", p.Error)
   224  		return
   225  	}
   226  
   227  	// loadPackage inferred the canonical ImportPath from arg.
   228  	// Use that in the following to prevent hysteresis effects
   229  	// in e.g. downloadCache and packageCache.
   230  	// This allows invocations such as:
   231  	//   mkdir -p $GOPATH/src/github.com/user
   232  	//   cd $GOPATH/src/github.com/user
   233  	//   go get ./foo
   234  	// see: golang.org/issue/9767
   235  	arg = p.ImportPath
   236  
   237  	// There's nothing to do if this is a package in the standard library.
   238  	if p.Standard {
   239  		return
   240  	}
   241  
   242  	// Only process each package once.
   243  	// (Unless we're fetching test dependencies for this package,
   244  	// in which case we want to process it again.)
   245  	if downloadCache[arg] && mode&load.GetTestDeps == 0 {
   246  		return
   247  	}
   248  	downloadCache[arg] = true
   249  
   250  	pkgs := []*load.Package{p}
   251  	wildcardOkay := len(*stk) == 0
   252  	isWildcard := false
   253  
   254  	// Download if the package is missing, or update if we're using -u.
   255  	if p.Dir == "" || *getU {
   256  		// The actual download.
   257  		stk.Push(arg)
   258  		err := downloadPackage(p)
   259  		if err != nil {
   260  			base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()})
   261  			stk.Pop()
   262  			return
   263  		}
   264  		stk.Pop()
   265  
   266  		args := []string{arg}
   267  		// If the argument has a wildcard in it, re-evaluate the wildcard.
   268  		// We delay this until after reloadPackage so that the old entry
   269  		// for p has been replaced in the package cache.
   270  		if wildcardOkay && strings.Contains(arg, "...") {
   271  			if build.IsLocalImport(arg) {
   272  				args = load.MatchPackagesInFS(arg)
   273  			} else {
   274  				args = load.MatchPackages(arg)
   275  			}
   276  			isWildcard = true
   277  		}
   278  
   279  		// Clear all relevant package cache entries before
   280  		// doing any new loads.
   281  		load.ClearPackageCachePartial(args)
   282  
   283  		pkgs = pkgs[:0]
   284  		for _, arg := range args {
   285  			// Note: load calls loadPackage or loadImport,
   286  			// which push arg onto stk already.
   287  			// Do not push here too, or else stk will say arg imports arg.
   288  			p := load1(arg, mode)
   289  			if p.Error != nil {
   290  				base.Errorf("%s", p.Error)
   291  				continue
   292  			}
   293  			pkgs = append(pkgs, p)
   294  		}
   295  	}
   296  
   297  	// Process package, which might now be multiple packages
   298  	// due to wildcard expansion.
   299  	for _, p := range pkgs {
   300  		if *getFix {
   301  			base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), base.RelPaths(p.Internal.AllGoFiles)))
   302  
   303  			// The imports might have changed, so reload again.
   304  			p = load.ReloadPackage(arg, stk)
   305  			if p.Error != nil {
   306  				base.Errorf("%s", p.Error)
   307  				return
   308  			}
   309  		}
   310  
   311  		if isWildcard {
   312  			// Report both the real package and the
   313  			// wildcard in any error message.
   314  			stk.Push(p.ImportPath)
   315  		}
   316  
   317  		// Process dependencies, now that we know what they are.
   318  		imports := p.Imports
   319  		if mode&load.GetTestDeps != 0 {
   320  			// Process test dependencies when -t is specified.
   321  			// (But don't get test dependencies for test dependencies:
   322  			// we always pass mode 0 to the recursive calls below.)
   323  			imports = str.StringList(imports, p.TestImports, p.XTestImports)
   324  		}
   325  		for i, path := range imports {
   326  			if path == "C" {
   327  				continue
   328  			}
   329  			// Fail fast on import naming full vendor path.
   330  			// Otherwise expand path as needed for test imports.
   331  			// Note that p.Imports can have additional entries beyond p.Internal.Build.Imports.
   332  			orig := path
   333  			if i < len(p.Internal.Build.Imports) {
   334  				orig = p.Internal.Build.Imports[i]
   335  			}
   336  			if j, ok := load.FindVendor(orig); ok {
   337  				stk.Push(path)
   338  				err := &load.PackageError{
   339  					ImportStack: stk.Copy(),
   340  					Err:         "must be imported as " + path[j+len("vendor/"):],
   341  				}
   342  				stk.Pop()
   343  				base.Errorf("%s", err)
   344  				continue
   345  			}
   346  			// If this is a test import, apply vendor lookup now.
   347  			// We cannot pass useVendor to download, because
   348  			// download does caching based on the value of path,
   349  			// so it must be the fully qualified path already.
   350  			if i >= len(p.Imports) {
   351  				path = load.VendoredImportPath(p, path)
   352  			}
   353  			download(path, p, stk, 0)
   354  		}
   355  
   356  		if isWildcard {
   357  			stk.Pop()
   358  		}
   359  	}
   360  }
   361  
   362  // downloadPackage runs the create or download command
   363  // to make the first copy of or update a copy of the given package.
   364  func downloadPackage(p *load.Package) error {
   365  	var (
   366  		vcs            *vcsCmd
   367  		repo, rootPath string
   368  		err            error
   369  	)
   370  
   371  	security := web.Secure
   372  	if *getInsecure {
   373  		security = web.Insecure
   374  	}
   375  
   376  	if p.Internal.Build.SrcRoot != "" {
   377  		// Directory exists. Look for checkout along path to src.
   378  		vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
   379  		if err != nil {
   380  			return err
   381  		}
   382  		repo = "<local>" // should be unused; make distinctive
   383  
   384  		// Double-check where it came from.
   385  		if *getU && vcs.remoteRepo != nil {
   386  			dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
   387  			remote, err := vcs.remoteRepo(vcs, dir)
   388  			if err != nil {
   389  				return err
   390  			}
   391  			repo = remote
   392  			if !*getF {
   393  				if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil {
   394  					repo := rr.repo
   395  					if rr.vcs.resolveRepo != nil {
   396  						resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
   397  						if err == nil {
   398  							repo = resolved
   399  						}
   400  					}
   401  					if remote != repo && rr.isCustom {
   402  						return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
   403  					}
   404  				}
   405  			}
   406  		}
   407  	} else {
   408  		// Analyze the import path to determine the version control system,
   409  		// repository, and the import path for the root of the repository.
   410  		rr, err := repoRootForImportPath(p.ImportPath, security)
   411  		if err != nil {
   412  			return err
   413  		}
   414  		vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
   415  	}
   416  	if !vcs.isSecure(repo) && !*getInsecure {
   417  		return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
   418  	}
   419  
   420  	if p.Internal.Build.SrcRoot == "" {
   421  		// Package not found. Put in first directory of $GOPATH.
   422  		list := filepath.SplitList(cfg.BuildContext.GOPATH)
   423  		if len(list) == 0 {
   424  			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
   425  		}
   426  		// Guard against people setting GOPATH=$GOROOT.
   427  		if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) {
   428  			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
   429  		}
   430  		if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
   431  			return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
   432  		}
   433  		p.Internal.Build.Root = list[0]
   434  		p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
   435  		p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
   436  	}
   437  	root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
   438  	// If we've considered this repository already, don't do it again.
   439  	if downloadRootCache[root] {
   440  		return nil
   441  	}
   442  	downloadRootCache[root] = true
   443  
   444  	if cfg.BuildV {
   445  		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
   446  	}
   447  
   448  	// Check that this is an appropriate place for the repo to be checked out.
   449  	// The target directory must either not exist or have a repo checked out already.
   450  	meta := filepath.Join(root, "."+vcs.cmd)
   451  	st, err := os.Stat(meta)
   452  	if err == nil && !st.IsDir() {
   453  		return fmt.Errorf("%s exists but is not a directory", meta)
   454  	}
   455  	if err != nil {
   456  		// Metadata 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  }