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