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