github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/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 // 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 }