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