github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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 }