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 }