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