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