github.com/euank/go@v0.0.0-20160829210321-495514729181/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. 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  	// Phase 1.  Download/update.
   102  	var stk importStack
   103  	mode := 0
   104  	if *getT {
   105  		mode |= getTestDeps
   106  	}
   107  	for _, arg := range downloadPaths(args) {
   108  		download(arg, nil, &stk, mode)
   109  	}
   110  	exitIfErrors()
   111  
   112  	// Phase 2. Rescan packages and re-evaluate args list.
   113  
   114  	// Code we downloaded and all code that depends on it
   115  	// needs to be evicted from the package cache so that
   116  	// the information will be recomputed. Instead of keeping
   117  	// track of the reverse dependency information, evict
   118  	// everything.
   119  	for name := range packageCache {
   120  		delete(packageCache, name)
   121  	}
   122  
   123  	// In order to rebuild packages information completely,
   124  	// we need to clear commands cache. Command packages are
   125  	// referring to evicted packages from the package cache.
   126  	// This leads to duplicated loads of the standard packages.
   127  	for name := range cmdCache {
   128  		delete(cmdCache, name)
   129  	}
   130  
   131  	args = importPaths(args)
   132  	packagesForBuild(args)
   133  
   134  	// Phase 3.  Install.
   135  	if *getD {
   136  		// Download only.
   137  		// Check delayed until now so that importPaths
   138  		// and packagesForBuild have a chance to print errors.
   139  		return
   140  	}
   141  
   142  	installPackages(args, true)
   143  }
   144  
   145  // downloadPaths prepares the list of paths to pass to download.
   146  // It expands ... patterns that can be expanded. If there is no match
   147  // for a particular pattern, downloadPaths leaves it in the result list,
   148  // in the hope that we can figure out the repository from the
   149  // initial ...-free prefix.
   150  func downloadPaths(args []string) []string {
   151  	args = importPathsNoDotExpansion(args)
   152  	var out []string
   153  	for _, a := range args {
   154  		if strings.Contains(a, "...") {
   155  			var expand []string
   156  			// Use matchPackagesInFS to avoid printing
   157  			// warnings. They will be printed by the
   158  			// eventual call to importPaths instead.
   159  			if build.IsLocalImport(a) {
   160  				expand = matchPackagesInFS(a)
   161  			} else {
   162  				expand = matchPackages(a)
   163  			}
   164  			if len(expand) > 0 {
   165  				out = append(out, expand...)
   166  				continue
   167  			}
   168  		}
   169  		out = append(out, a)
   170  	}
   171  	return out
   172  }
   173  
   174  // downloadCache records the import paths we have already
   175  // considered during the download, to avoid duplicate work when
   176  // there is more than one dependency sequence leading to
   177  // a particular package.
   178  var downloadCache = map[string]bool{}
   179  
   180  // downloadRootCache records the version control repository
   181  // root directories we have already considered during the download.
   182  // For example, all the packages in the code.google.com/p/codesearch repo
   183  // share the same root (the directory for that path), and we only need
   184  // to run the hg commands to consider each repository once.
   185  var downloadRootCache = map[string]bool{}
   186  
   187  // download runs the download half of the get command
   188  // for the package named by the argument.
   189  func download(arg string, parent *Package, stk *importStack, mode int) {
   190  	load := func(path string, mode int) *Package {
   191  		if parent == nil {
   192  			return loadPackage(path, stk)
   193  		}
   194  		return loadImport(path, parent.Dir, parent, stk, nil, mode)
   195  	}
   196  
   197  	p := load(arg, mode)
   198  	if p.Error != nil && p.Error.hard {
   199  		errorf("%s", p.Error)
   200  		return
   201  	}
   202  
   203  	// loadPackage inferred the canonical ImportPath from arg.
   204  	// Use that in the following to prevent hysteresis effects
   205  	// in e.g. downloadCache and packageCache.
   206  	// This allows invocations such as:
   207  	//   mkdir -p $GOPATH/src/github.com/user
   208  	//   cd $GOPATH/src/github.com/user
   209  	//   go get ./foo
   210  	// see: golang.org/issue/9767
   211  	arg = p.ImportPath
   212  
   213  	// There's nothing to do if this is a package in the standard library.
   214  	if p.Standard {
   215  		return
   216  	}
   217  
   218  	// Only process each package once.
   219  	// (Unless we're fetching test dependencies for this package,
   220  	// in which case we want to process it again.)
   221  	if downloadCache[arg] && mode&getTestDeps == 0 {
   222  		return
   223  	}
   224  	downloadCache[arg] = true
   225  
   226  	pkgs := []*Package{p}
   227  	wildcardOkay := len(*stk) == 0
   228  	isWildcard := false
   229  
   230  	// Download if the package is missing, or update if we're using -u.
   231  	if p.Dir == "" || *getU {
   232  		// The actual download.
   233  		stk.push(arg)
   234  		err := downloadPackage(p)
   235  		if err != nil {
   236  			errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
   237  			stk.pop()
   238  			return
   239  		}
   240  		stk.pop()
   241  
   242  		args := []string{arg}
   243  		// If the argument has a wildcard in it, re-evaluate the wildcard.
   244  		// We delay this until after reloadPackage so that the old entry
   245  		// for p has been replaced in the package cache.
   246  		if wildcardOkay && strings.Contains(arg, "...") {
   247  			if build.IsLocalImport(arg) {
   248  				args = matchPackagesInFS(arg)
   249  			} else {
   250  				args = matchPackages(arg)
   251  			}
   252  			isWildcard = true
   253  		}
   254  
   255  		// Clear all relevant package cache entries before
   256  		// doing any new loads.
   257  		for _, arg := range args {
   258  			p := packageCache[arg]
   259  			if p != nil {
   260  				delete(packageCache, p.Dir)
   261  				delete(packageCache, p.ImportPath)
   262  			}
   263  		}
   264  
   265  		pkgs = pkgs[:0]
   266  		for _, arg := range args {
   267  			// Note: load calls loadPackage or loadImport,
   268  			// which push arg onto stk already.
   269  			// Do not push here too, or else stk will say arg imports arg.
   270  			p := load(arg, mode)
   271  			if p.Error != nil {
   272  				errorf("%s", p.Error)
   273  				continue
   274  			}
   275  			pkgs = append(pkgs, p)
   276  		}
   277  	}
   278  
   279  	// Process package, which might now be multiple packages
   280  	// due to wildcard expansion.
   281  	for _, p := range pkgs {
   282  		if *getFix {
   283  			run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
   284  
   285  			// The imports might have changed, so reload again.
   286  			p = reloadPackage(arg, stk)
   287  			if p.Error != nil {
   288  				errorf("%s", p.Error)
   289  				return
   290  			}
   291  		}
   292  
   293  		if isWildcard {
   294  			// Report both the real package and the
   295  			// wildcard in any error message.
   296  			stk.push(p.ImportPath)
   297  		}
   298  
   299  		// Process dependencies, now that we know what they are.
   300  		for _, path := range p.Imports {
   301  			if path == "C" {
   302  				continue
   303  			}
   304  			// Don't get test dependencies recursively.
   305  			// Imports is already vendor-expanded.
   306  			download(path, p, stk, 0)
   307  		}
   308  		if mode&getTestDeps != 0 {
   309  			// Process test dependencies when -t is specified.
   310  			// (Don't get test dependencies for test dependencies.)
   311  			// We pass useVendor here because p.load does not
   312  			// vendor-expand TestImports and XTestImports.
   313  			// The call to loadImport inside download needs to do that.
   314  			for _, path := range p.TestImports {
   315  				if path == "C" {
   316  					continue
   317  				}
   318  				download(path, p, stk, useVendor)
   319  			}
   320  			for _, path := range p.XTestImports {
   321  				if path == "C" {
   322  					continue
   323  				}
   324  				download(path, p, stk, useVendor)
   325  			}
   326  		}
   327  
   328  		if isWildcard {
   329  			stk.pop()
   330  		}
   331  	}
   332  }
   333  
   334  // downloadPackage runs the create or download command
   335  // to make the first copy of or update a copy of the given package.
   336  func downloadPackage(p *Package) error {
   337  	var (
   338  		vcs            *vcsCmd
   339  		repo, rootPath string
   340  		err            error
   341  	)
   342  
   343  	security := secure
   344  	if *getInsecure {
   345  		security = insecure
   346  	}
   347  
   348  	if p.build.SrcRoot != "" {
   349  		// Directory exists. Look for checkout along path to src.
   350  		vcs, rootPath, err = vcsFromDir(p.Dir, p.build.SrcRoot)
   351  		if err != nil {
   352  			return err
   353  		}
   354  		repo = "<local>" // should be unused; make distinctive
   355  
   356  		// Double-check where it came from.
   357  		if *getU && vcs.remoteRepo != nil {
   358  			dir := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
   359  			remote, err := vcs.remoteRepo(vcs, dir)
   360  			if err != nil {
   361  				return err
   362  			}
   363  			repo = remote
   364  			if !*getF {
   365  				if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil {
   366  					repo := rr.repo
   367  					if rr.vcs.resolveRepo != nil {
   368  						resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
   369  						if err == nil {
   370  							repo = resolved
   371  						}
   372  					}
   373  					if remote != repo && p.ImportComment != "" {
   374  						return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
   375  					}
   376  				}
   377  			}
   378  		}
   379  	} else {
   380  		// Analyze the import path to determine the version control system,
   381  		// repository, and the import path for the root of the repository.
   382  		rr, err := repoRootForImportPath(p.ImportPath, security)
   383  		if err != nil {
   384  			return err
   385  		}
   386  		vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
   387  	}
   388  	if !vcs.isSecure(repo) && !*getInsecure {
   389  		return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
   390  	}
   391  
   392  	if p.build.SrcRoot == "" {
   393  		// Package not found. Put in first directory of $GOPATH.
   394  		list := filepath.SplitList(buildContext.GOPATH)
   395  		if len(list) == 0 {
   396  			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
   397  		}
   398  		// Guard against people setting GOPATH=$GOROOT.
   399  		if list[0] == goroot {
   400  			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath")
   401  		}
   402  		p.build.SrcRoot = filepath.Join(list[0], "src")
   403  		p.build.PkgRoot = filepath.Join(list[0], "pkg")
   404  	}
   405  	root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
   406  	// If we've considered this repository already, don't do it again.
   407  	if downloadRootCache[root] {
   408  		return nil
   409  	}
   410  	downloadRootCache[root] = true
   411  
   412  	if buildV {
   413  		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
   414  	}
   415  
   416  	// Check that this is an appropriate place for the repo to be checked out.
   417  	// The target directory must either not exist or have a repo checked out already.
   418  	meta := filepath.Join(root, "."+vcs.cmd)
   419  	st, err := os.Stat(meta)
   420  	if err == nil && !st.IsDir() {
   421  		return fmt.Errorf("%s exists but is not a directory", meta)
   422  	}
   423  	if err != nil {
   424  		// Metadata directory does not exist. Prepare to checkout new copy.
   425  		// Some version control tools require the target directory not to exist.
   426  		// We require that too, just to avoid stepping on existing work.
   427  		if _, err := os.Stat(root); err == nil {
   428  			return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
   429  		}
   430  		// Some version control tools require the parent of the target to exist.
   431  		parent, _ := filepath.Split(root)
   432  		if err = os.MkdirAll(parent, 0777); err != nil {
   433  			return err
   434  		}
   435  		if err = vcs.create(root, repo); err != nil {
   436  			return err
   437  		}
   438  	} else {
   439  		// Metadata directory does exist; download incremental updates.
   440  		if err = vcs.download(root); err != nil {
   441  			return err
   442  		}
   443  	}
   444  
   445  	if buildN {
   446  		// Do not show tag sync in -n; it's noise more than anything,
   447  		// and since we're not running commands, no tag will be found.
   448  		// But avoid printing nothing.
   449  		fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
   450  		return nil
   451  	}
   452  
   453  	// Select and sync to appropriate version of the repository.
   454  	tags, err := vcs.tags(root)
   455  	if err != nil {
   456  		return err
   457  	}
   458  	vers := runtime.Version()
   459  	if i := strings.Index(vers, " "); i >= 0 {
   460  		vers = vers[:i]
   461  	}
   462  	if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
   463  		return err
   464  	}
   465  
   466  	return nil
   467  }
   468  
   469  // goTag matches go release tags such as go1 and go1.2.3.
   470  // The numbers involved must be small (at most 4 digits),
   471  // have no unnecessary leading zeros, and the version cannot
   472  // end in .0 - it is go1, not go1.0 or go1.0.0.
   473  var goTag = regexp.MustCompile(
   474  	`^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
   475  )
   476  
   477  // selectTag returns the closest matching tag for a given version.
   478  // Closest means the latest one that is not after the current release.
   479  // Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
   480  // Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
   481  // Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
   482  //
   483  // NOTE(rsc): Eventually we will need to decide on some logic here.
   484  // For now, there is only "go1".  This matches the docs in go help get.
   485  func selectTag(goVersion string, tags []string) (match string) {
   486  	for _, t := range tags {
   487  		if t == "go1" {
   488  			return "go1"
   489  		}
   490  	}
   491  	return ""
   492  
   493  	/*
   494  		if goTag.MatchString(goVersion) {
   495  			v := goVersion
   496  			for _, t := range tags {
   497  				if !goTag.MatchString(t) {
   498  					continue
   499  				}
   500  				if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
   501  					match = t
   502  				}
   503  			}
   504  		}
   505  
   506  		return match
   507  	*/
   508  }
   509  
   510  // cmpGoVersion returns -1, 0, +1 reporting whether
   511  // x < y, x == y, or x > y.
   512  func cmpGoVersion(x, y string) int {
   513  	// Malformed strings compare less than well-formed strings.
   514  	if !goTag.MatchString(x) {
   515  		return -1
   516  	}
   517  	if !goTag.MatchString(y) {
   518  		return +1
   519  	}
   520  
   521  	// Compare numbers in sequence.
   522  	xx := strings.Split(x[len("go"):], ".")
   523  	yy := strings.Split(y[len("go"):], ".")
   524  
   525  	for i := 0; i < len(xx) && i < len(yy); i++ {
   526  		// The Atoi are guaranteed to succeed
   527  		// because the versions match goTag.
   528  		xi, _ := strconv.Atoi(xx[i])
   529  		yi, _ := strconv.Atoi(yy[i])
   530  		if xi < yi {
   531  			return -1
   532  		} else if xi > yi {
   533  			return +1
   534  		}
   535  	}
   536  
   537  	if len(xx) < len(yy) {
   538  		return -1
   539  	}
   540  	if len(xx) > len(yy) {
   541  		return +1
   542  	}
   543  	return 0
   544  }