Source file src/pkg/cmd/go/internal/get/get.go
1
2
3
4
5
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/search"
20 "cmd/go/internal/str"
21 "cmd/go/internal/web"
22 "cmd/go/internal/work"
23 )
24
25 var CmdGet = &base.Command{
26 UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]",
27 Short: "download and install packages and dependencies",
28 Long: `
29 Get downloads the packages named by the import paths, along with their
30 dependencies. It then installs the named packages, like 'go install'.
31
32 The -d flag instructs get to stop after downloading the packages; that is,
33 it instructs get not to install the packages.
34
35 The -f flag, valid only when -u is set, forces get -u not to verify that
36 each package has been checked out from the source control repository
37 implied by its import path. This can be useful if the source is a local fork
38 of the original.
39
40 The -fix flag instructs get to run the fix tool on the downloaded packages
41 before resolving dependencies or building the code.
42
43 The -insecure flag permits fetching from repositories and resolving
44 custom domains using insecure schemes such as HTTP. Use with caution.
45
46 The -t flag instructs get to also download the packages required to build
47 the tests for the specified packages.
48
49 The -u flag instructs get to use the network to update the named packages
50 and their dependencies. By default, get uses the network to check out
51 missing packages but does not use it to look for updates to existing packages.
52
53 The -v flag enables verbose progress and debug output.
54
55 Get also accepts build flags to control the installation. See 'go help build'.
56
57 When checking out a new package, get creates the target directory
58 GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
59 get uses the first one. For more details see: 'go help gopath'.
60
61 When checking out or updating a package, get looks for a branch or tag
62 that matches the locally installed version of Go. The most important
63 rule is that if the local installation is running version "go1", get
64 searches for a branch or tag named "go1". If no such version exists
65 it retrieves the default branch of the package.
66
67 When go get checks out or updates a Git repository,
68 it also updates any git submodules referenced by the repository.
69
70 Get never checks out or updates code stored in vendor directories.
71
72 For more about specifying packages, see 'go help packages'.
73
74 For more about how 'go get' finds source code to
75 download, see 'go help importpath'.
76
77 This text describes the behavior of get when using GOPATH
78 to manage source code and dependencies.
79 If instead the go command is running in module-aware mode,
80 the details of get's flags and effects change, as does 'go help get'.
81 See 'go help modules' and 'go help module-get'.
82
83 See also: go build, go install, go clean.
84 `,
85 }
86
87 var HelpGopathGet = &base.Command{
88 UsageLine: "gopath-get",
89 Short: "legacy GOPATH go get",
90 Long: `
91 The 'go get' command changes behavior depending on whether the
92 go command is running in module-aware mode or legacy GOPATH mode.
93 This help text, accessible as 'go help gopath-get' even in module-aware mode,
94 describes 'go get' as it operates in legacy GOPATH mode.
95
96 Usage: ` + CmdGet.UsageLine + `
97 ` + CmdGet.Long,
98 }
99
100 var (
101 getD = CmdGet.Flag.Bool("d", false, "")
102 getF = CmdGet.Flag.Bool("f", false, "")
103 getT = CmdGet.Flag.Bool("t", false, "")
104 getU = CmdGet.Flag.Bool("u", false, "")
105 getFix = CmdGet.Flag.Bool("fix", false, "")
106
107 Insecure bool
108 )
109
110 func init() {
111 work.AddBuildFlags(CmdGet)
112 CmdGet.Run = runGet
113 CmdGet.Flag.BoolVar(&Insecure, "insecure", Insecure, "")
114 }
115
116 func runGet(cmd *base.Command, args []string) {
117 if cfg.ModulesEnabled {
118
119 base.Fatalf("go get: modules not implemented")
120 }
121
122 work.BuildInit()
123
124 if *getF && !*getU {
125 base.Fatalf("go get: cannot use -f flag without -u")
126 }
127
128
129
130
131
132
133
134 if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
135 os.Setenv("GIT_TERMINAL_PROMPT", "0")
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
152 os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
153 }
154
155
156 var stk load.ImportStack
157 mode := 0
158 if *getT {
159 mode |= load.GetTestDeps
160 }
161 for _, pkg := range downloadPaths(args) {
162 download(pkg, nil, &stk, mode)
163 }
164 base.ExitIfErrors()
165
166
167
168
169
170
171
172
173 load.ClearPackageCache()
174
175 pkgs := load.PackagesForBuild(args)
176
177
178 if *getD {
179
180
181
182 return
183 }
184
185 work.InstallPackages(args, pkgs)
186 }
187
188
189
190
191
192
193 func downloadPaths(patterns []string) []string {
194 for _, arg := range patterns {
195 if strings.Contains(arg, "@") {
196 base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
197 }
198 }
199 var pkgs []string
200 for _, m := range search.ImportPathsQuiet(patterns) {
201 if len(m.Pkgs) == 0 && strings.Contains(m.Pattern, "...") {
202 pkgs = append(pkgs, m.Pattern)
203 } else {
204 pkgs = append(pkgs, m.Pkgs...)
205 }
206 }
207 return pkgs
208 }
209
210
211
212
213
214 var downloadCache = map[string]bool{}
215
216
217
218
219
220
221 var downloadRootCache = map[string]bool{}
222
223
224
225 func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
226 if mode&load.ResolveImport != 0 {
227
228 panic("internal error: download mode has useVendor set")
229 }
230 load1 := func(path string, mode int) *load.Package {
231 if parent == nil {
232 mode := 0
233 return load.LoadImport(path, base.Cwd, nil, stk, nil, mode)
234 }
235 return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
236 }
237
238 p := load1(arg, mode)
239 if p.Error != nil && p.Error.Hard {
240 base.Errorf("%s", p.Error)
241 return
242 }
243
244
245
246
247
248
249
250
251
252 arg = p.ImportPath
253
254
255 if p.Standard {
256 return
257 }
258
259
260
261
262 if downloadCache[arg] && mode&load.GetTestDeps == 0 {
263 return
264 }
265 downloadCache[arg] = true
266
267 pkgs := []*load.Package{p}
268 wildcardOkay := len(*stk) == 0
269 isWildcard := false
270
271
272 if p.Dir == "" || *getU {
273
274 stk.Push(arg)
275 err := downloadPackage(p)
276 if err != nil {
277 base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()})
278 stk.Pop()
279 return
280 }
281 stk.Pop()
282
283 args := []string{arg}
284
285
286
287 if wildcardOkay && strings.Contains(arg, "...") {
288 if build.IsLocalImport(arg) {
289 args = search.MatchPackagesInFS(arg).Pkgs
290 } else {
291 args = search.MatchPackages(arg).Pkgs
292 }
293 isWildcard = true
294 }
295
296
297
298 load.ClearPackageCachePartial(args)
299
300 pkgs = pkgs[:0]
301 for _, arg := range args {
302
303
304
305 p := load1(arg, mode)
306 if p.Error != nil {
307 base.Errorf("%s", p.Error)
308 continue
309 }
310 pkgs = append(pkgs, p)
311 }
312 }
313
314
315
316 for _, p := range pkgs {
317 if *getFix {
318 files := base.RelPaths(p.InternalAllGoFiles())
319 base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
320
321
322 p = load.ReloadPackageNoFlags(arg, stk)
323 if p.Error != nil {
324 base.Errorf("%s", p.Error)
325 return
326 }
327 }
328
329 if isWildcard {
330
331
332 stk.Push(p.ImportPath)
333 }
334
335
336 imports := p.Imports
337 if mode&load.GetTestDeps != 0 {
338
339
340
341 imports = str.StringList(imports, p.TestImports, p.XTestImports)
342 }
343 for i, path := range imports {
344 if path == "C" {
345 continue
346 }
347
348
349
350 orig := path
351 if i < len(p.Internal.Build.Imports) {
352 orig = p.Internal.Build.Imports[i]
353 }
354 if j, ok := load.FindVendor(orig); ok {
355 stk.Push(path)
356 err := &load.PackageError{
357 ImportStack: stk.Copy(),
358 Err: "must be imported as " + path[j+len("vendor/"):],
359 }
360 stk.Pop()
361 base.Errorf("%s", err)
362 continue
363 }
364
365
366
367
368 if i >= len(p.Imports) {
369 path = load.ResolveImportPath(p, path)
370 }
371 download(path, p, stk, 0)
372 }
373
374 if isWildcard {
375 stk.Pop()
376 }
377 }
378 }
379
380
381
382 func downloadPackage(p *load.Package) error {
383 var (
384 vcs *vcsCmd
385 repo, rootPath string
386 err error
387 blindRepo bool
388 )
389
390 security := web.SecureOnly
391 if Insecure {
392 security = web.Insecure
393 }
394
395
396
397
398
399
400 importPrefix := p.ImportPath
401 if i := strings.Index(importPrefix, "..."); i >= 0 {
402 slash := strings.LastIndexByte(importPrefix[:i], '/')
403 if slash < 0 {
404 return fmt.Errorf("cannot expand ... in %q", p.ImportPath)
405 }
406 importPrefix = importPrefix[:slash]
407 }
408 if err := CheckImportPath(importPrefix); err != nil {
409 return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
410 }
411
412 if p.Internal.Build.SrcRoot != "" {
413
414 vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
415 if err != nil {
416 return err
417 }
418 repo = "<local>"
419
420
421 if *getU && vcs.remoteRepo != nil {
422 dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
423 remote, err := vcs.remoteRepo(vcs, dir)
424 if err != nil {
425
426
427 blindRepo = true
428 }
429 repo = remote
430 if !*getF && err == nil {
431 if rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security); err == nil {
432 repo := rr.Repo
433 if rr.vcs.resolveRepo != nil {
434 resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
435 if err == nil {
436 repo = resolved
437 }
438 }
439 if remote != repo && rr.IsCustom {
440 return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.Root, repo, dir, remote)
441 }
442 }
443 }
444 }
445 } else {
446
447
448 rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security)
449 if err != nil {
450 return err
451 }
452 vcs, repo, rootPath = rr.vcs, rr.Repo, rr.Root
453 }
454 if !blindRepo && !vcs.isSecure(repo) && !Insecure {
455 return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
456 }
457
458 if p.Internal.Build.SrcRoot == "" {
459
460 list := filepath.SplitList(cfg.BuildContext.GOPATH)
461 if len(list) == 0 {
462 return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
463 }
464
465 if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) {
466 return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
467 }
468 if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
469 return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
470 }
471 p.Internal.Build.Root = list[0]
472 p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
473 p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
474 }
475 root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
476
477 if err := checkNestedVCS(vcs, root, p.Internal.Build.SrcRoot); err != nil {
478 return err
479 }
480
481
482 if downloadRootCache[root] {
483 return nil
484 }
485 downloadRootCache[root] = true
486
487 if cfg.BuildV {
488 fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
489 }
490
491
492
493 meta := filepath.Join(root, "."+vcs.cmd)
494 if _, err := os.Stat(meta); err != nil {
495
496
497
498 if _, err := os.Stat(root); err == nil {
499 return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
500 }
501
502 _, err := os.Stat(p.Internal.Build.Root)
503 gopathExisted := err == nil
504
505
506 parent, _ := filepath.Split(root)
507 if err = os.MkdirAll(parent, 0777); err != nil {
508 return err
509 }
510 if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH {
511 fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
512 }
513
514 if err = vcs.create(root, repo); err != nil {
515 return err
516 }
517 } else {
518
519 if err = vcs.download(root); err != nil {
520 return err
521 }
522 }
523
524 if cfg.BuildN {
525
526
527
528 fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
529 return nil
530 }
531
532
533 tags, err := vcs.tags(root)
534 if err != nil {
535 return err
536 }
537 vers := runtime.Version()
538 if i := strings.Index(vers, " "); i >= 0 {
539 vers = vers[:i]
540 }
541 if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
542 return err
543 }
544
545 return nil
546 }
547
548
549
550
551
552
553
554
555
556 func selectTag(goVersion string, tags []string) (match string) {
557 for _, t := range tags {
558 if t == "go1" {
559 return "go1"
560 }
561 }
562 return ""
563 }
564
View as plain text