Source file src/pkg/cmd/go/internal/list/list.go
1
2
3
4
5
6 package list
7
8 import (
9 "bufio"
10 "bytes"
11 "encoding/json"
12 "io"
13 "os"
14 "sort"
15 "strings"
16 "text/template"
17
18 "cmd/go/internal/base"
19 "cmd/go/internal/cache"
20 "cmd/go/internal/cfg"
21 "cmd/go/internal/load"
22 "cmd/go/internal/modload"
23 "cmd/go/internal/str"
24 "cmd/go/internal/work"
25 )
26
27 var CmdList = &base.Command{
28
29
30 UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]",
31 Short: "list packages or modules",
32 Long: `
33 List lists the named packages, one per line.
34 The most commonly-used flags are -f and -json, which control the form
35 of the output printed for each package. Other list flags, documented below,
36 control more specific details.
37
38 The default output shows the package import path:
39
40 bytes
41 encoding/json
42 github.com/gorilla/mux
43 golang.org/x/net/html
44
45 The -f flag specifies an alternate format for the list, using the
46 syntax of package template. The default output is equivalent
47 to -f '{{.ImportPath}}'. The struct being passed to the template is:
48
49 type Package struct {
50 Dir string // directory containing package sources
51 ImportPath string // import path of package in dir
52 ImportComment string // path in import comment on package statement
53 Name string // package name
54 Doc string // package documentation string
55 Target string // install path
56 Shlib string // the shared library that contains this package (only set when -linkshared)
57 Goroot bool // is this package in the Go root?
58 Standard bool // is this package part of the standard Go library?
59 Stale bool // would 'go install' do anything for this package?
60 StaleReason string // explanation for Stale==true
61 Root string // Go root or Go path dir containing this package
62 ConflictDir string // this directory shadows Dir in $GOPATH
63 BinaryOnly bool // binary-only package (no longer supported)
64 ForTest string // package is only for use in named test
65 Export string // file containing export data (when using -export)
66 Module *Module // info about package's containing module, if any (can be nil)
67 Match []string // command-line patterns matching this package
68 DepOnly bool // package is only a dependency, not explicitly listed
69
70 // Source files
71 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
72 CgoFiles []string // .go source files that import "C"
73 CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
74 IgnoredGoFiles []string // .go source files ignored due to build constraints
75 CFiles []string // .c source files
76 CXXFiles []string // .cc, .cxx and .cpp source files
77 MFiles []string // .m source files
78 HFiles []string // .h, .hh, .hpp and .hxx source files
79 FFiles []string // .f, .F, .for and .f90 Fortran source files
80 SFiles []string // .s source files
81 SwigFiles []string // .swig files
82 SwigCXXFiles []string // .swigcxx files
83 SysoFiles []string // .syso object files to add to archive
84 TestGoFiles []string // _test.go files in package
85 XTestGoFiles []string // _test.go files outside package
86
87 // Cgo directives
88 CgoCFLAGS []string // cgo: flags for C compiler
89 CgoCPPFLAGS []string // cgo: flags for C preprocessor
90 CgoCXXFLAGS []string // cgo: flags for C++ compiler
91 CgoFFLAGS []string // cgo: flags for Fortran compiler
92 CgoLDFLAGS []string // cgo: flags for linker
93 CgoPkgConfig []string // cgo: pkg-config names
94
95 // Dependency information
96 Imports []string // import paths used by this package
97 ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
98 Deps []string // all (recursively) imported dependencies
99 TestImports []string // imports from TestGoFiles
100 XTestImports []string // imports from XTestGoFiles
101
102 // Error information
103 Incomplete bool // this package or a dependency has an error
104 Error *PackageError // error loading package
105 DepsErrors []*PackageError // errors loading dependencies
106 }
107
108 Packages stored in vendor directories report an ImportPath that includes the
109 path to the vendor directory (for example, "d/vendor/p" instead of "p"),
110 so that the ImportPath uniquely identifies a given copy of a package.
111 The Imports, Deps, TestImports, and XTestImports lists also contain these
112 expanded import paths. See golang.org/s/go15vendor for more about vendoring.
113
114 The error information, if any, is
115
116 type PackageError struct {
117 ImportStack []string // shortest path from package named on command line to this one
118 Pos string // position of error (if present, file:line:col)
119 Err string // the error itself
120 }
121
122 The module information is a Module struct, defined in the discussion
123 of list -m below.
124
125 The template function "join" calls strings.Join.
126
127 The template function "context" returns the build context, defined as:
128
129 type Context struct {
130 GOARCH string // target architecture
131 GOOS string // target operating system
132 GOROOT string // Go root
133 GOPATH string // Go path
134 CgoEnabled bool // whether cgo can be used
135 UseAllFiles bool // use files regardless of +build lines, file names
136 Compiler string // compiler to assume when computing target paths
137 BuildTags []string // build constraints to match in +build lines
138 ReleaseTags []string // releases the current release is compatible with
139 InstallSuffix string // suffix to use in the name of the install dir
140 }
141
142 For more information about the meaning of these fields see the documentation
143 for the go/build package's Context type.
144
145 The -json flag causes the package data to be printed in JSON format
146 instead of using the template format.
147
148 The -compiled flag causes list to set CompiledGoFiles to the Go source
149 files presented to the compiler. Typically this means that it repeats
150 the files listed in GoFiles and then also adds the Go code generated
151 by processing CgoFiles and SwigFiles. The Imports list contains the
152 union of all imports from both GoFiles and CompiledGoFiles.
153
154 The -deps flag causes list to iterate over not just the named packages
155 but also all their dependencies. It visits them in a depth-first post-order
156 traversal, so that a package is listed only after all its dependencies.
157 Packages not explicitly listed on the command line will have the DepOnly
158 field set to true.
159
160 The -e flag changes the handling of erroneous packages, those that
161 cannot be found or are malformed. By default, the list command
162 prints an error to standard error for each erroneous package and
163 omits the packages from consideration during the usual printing.
164 With the -e flag, the list command never prints errors to standard
165 error and instead processes the erroneous packages with the usual
166 printing. Erroneous packages will have a non-empty ImportPath and
167 a non-nil Error field; other information may or may not be missing
168 (zeroed).
169
170 The -export flag causes list to set the Export field to the name of a
171 file containing up-to-date export information for the given package.
172
173 The -find flag causes list to identify the named packages but not
174 resolve their dependencies: the Imports and Deps lists will be empty.
175
176 The -test flag causes list to report not only the named packages
177 but also their test binaries (for packages with tests), to convey to
178 source code analysis tools exactly how test binaries are constructed.
179 The reported import path for a test binary is the import path of
180 the package followed by a ".test" suffix, as in "math/rand.test".
181 When building a test, it is sometimes necessary to rebuild certain
182 dependencies specially for that test (most commonly the tested
183 package itself). The reported import path of a package recompiled
184 for a particular test binary is followed by a space and the name of
185 the test binary in brackets, as in "math/rand [math/rand.test]"
186 or "regexp [sort.test]". The ForTest field is also set to the name
187 of the package being tested ("math/rand" or "sort" in the previous
188 examples).
189
190 The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
191 are all absolute paths.
192
193 By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
194 (that is, paths relative to Dir, not absolute paths).
195 The generated files added when using the -compiled and -test flags
196 are absolute paths referring to cached copies of generated Go source files.
197 Although they are Go source files, the paths may not end in ".go".
198
199 The -m flag causes list to list modules instead of packages.
200
201 When listing modules, the -f flag still specifies a format template
202 applied to a Go struct, but now a Module struct:
203
204 type Module struct {
205 Path string // module path
206 Version string // module version
207 Versions []string // available module versions (with -versions)
208 Replace *Module // replaced by this module
209 Time *time.Time // time version was created
210 Update *Module // available update, if any (with -u)
211 Main bool // is this the main module?
212 Indirect bool // is this module only an indirect dependency of main module?
213 Dir string // directory holding files for this module, if any
214 GoMod string // path to go.mod file for this module, if any
215 GoVersion string // go version used in module
216 Error *ModuleError // error loading module
217 }
218
219 type ModuleError struct {
220 Err string // the error itself
221 }
222
223 The default output is to print the module path and then
224 information about the version and replacement if any.
225 For example, 'go list -m all' might print:
226
227 my/main/module
228 golang.org/x/text v0.3.0 => /tmp/text
229 rsc.io/pdf v0.1.1
230
231 The Module struct has a String method that formats this
232 line of output, so that the default format is equivalent
233 to -f '{{.String}}'.
234
235 Note that when a module has been replaced, its Replace field
236 describes the replacement module, and its Dir field is set to
237 the replacement's source code, if present. (That is, if Replace
238 is non-nil, then Dir is set to Replace.Dir, with no access to
239 the replaced source code.)
240
241 The -u flag adds information about available upgrades.
242 When the latest version of a given module is newer than
243 the current one, list -u sets the Module's Update field
244 to information about the newer module.
245 The Module's String method indicates an available upgrade by
246 formatting the newer version in brackets after the current version.
247 For example, 'go list -m -u all' might print:
248
249 my/main/module
250 golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
251 rsc.io/pdf v0.1.1 [v0.1.2]
252
253 (For tools, 'go list -m -u -json all' may be more convenient to parse.)
254
255 The -versions flag causes list to set the Module's Versions field
256 to a list of all known versions of that module, ordered according
257 to semantic versioning, earliest to latest. The flag also changes
258 the default output format to display the module path followed by the
259 space-separated version list.
260
261 The arguments to list -m are interpreted as a list of modules, not packages.
262 The main module is the module containing the current directory.
263 The active modules are the main module and its dependencies.
264 With no arguments, list -m shows the main module.
265 With arguments, list -m shows the modules specified by the arguments.
266 Any of the active modules can be specified by its module path.
267 The special pattern "all" specifies all the active modules, first the main
268 module and then dependencies sorted by module path.
269 A pattern containing "..." specifies the active modules whose
270 module paths match the pattern.
271 A query of the form path@version specifies the result of that query,
272 which is not limited to active modules.
273 See 'go help modules' for more about module queries.
274
275 The template function "module" takes a single string argument
276 that must be a module path or query and returns the specified
277 module as a Module struct. If an error occurs, the result will
278 be a Module struct with a non-nil Error field.
279
280 For more about build flags, see 'go help build'.
281
282 For more about specifying packages, see 'go help packages'.
283
284 For more about modules, see 'go help modules'.
285 `,
286 }
287
288 func init() {
289 CmdList.Run = runList
290 work.AddBuildFlags(CmdList)
291 }
292
293 var (
294 listCompiled = CmdList.Flag.Bool("compiled", false, "")
295 listDeps = CmdList.Flag.Bool("deps", false, "")
296 listE = CmdList.Flag.Bool("e", false, "")
297 listExport = CmdList.Flag.Bool("export", false, "")
298 listFmt = CmdList.Flag.String("f", "", "")
299 listFind = CmdList.Flag.Bool("find", false, "")
300 listJson = CmdList.Flag.Bool("json", false, "")
301 listM = CmdList.Flag.Bool("m", false, "")
302 listU = CmdList.Flag.Bool("u", false, "")
303 listTest = CmdList.Flag.Bool("test", false, "")
304 listVersions = CmdList.Flag.Bool("versions", false, "")
305 )
306
307 var nl = []byte{'\n'}
308
309 func runList(cmd *base.Command, args []string) {
310 modload.LoadTests = *listTest
311 work.BuildInit()
312 out := newTrackingWriter(os.Stdout)
313 defer out.w.Flush()
314
315 if *listFmt == "" {
316 if *listM {
317 *listFmt = "{{.String}}"
318 if *listVersions {
319 *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}`
320 }
321 } else {
322 *listFmt = "{{.ImportPath}}"
323 }
324 }
325
326 var do func(interface{})
327 if *listJson {
328 do = func(x interface{}) {
329 b, err := json.MarshalIndent(x, "", "\t")
330 if err != nil {
331 out.Flush()
332 base.Fatalf("%s", err)
333 }
334 out.Write(b)
335 out.Write(nl)
336 }
337 } else {
338 var cachedCtxt *Context
339 context := func() *Context {
340 if cachedCtxt == nil {
341 cachedCtxt = newContext(&cfg.BuildContext)
342 }
343 return cachedCtxt
344 }
345 fm := template.FuncMap{
346 "join": strings.Join,
347 "context": context,
348 "module": modload.ModuleInfo,
349 }
350 tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
351 if err != nil {
352 base.Fatalf("%s", err)
353 }
354 do = func(x interface{}) {
355 if err := tmpl.Execute(out, x); err != nil {
356 out.Flush()
357 base.Fatalf("%s", err)
358 }
359 if out.NeedNL() {
360 out.Write(nl)
361 }
362 }
363 }
364
365 if *listM {
366
367 if *listCompiled {
368 base.Fatalf("go list -compiled cannot be used with -m")
369 }
370 if *listDeps {
371
372 base.Fatalf("go list -deps cannot be used with -m")
373 }
374 if *listExport {
375 base.Fatalf("go list -export cannot be used with -m")
376 }
377 if *listFind {
378 base.Fatalf("go list -find cannot be used with -m")
379 }
380 if *listTest {
381 base.Fatalf("go list -test cannot be used with -m")
382 }
383
384 if modload.Init(); !modload.Enabled() {
385 base.Fatalf("go list -m: not using modules")
386 }
387 modload.LoadBuildList()
388
389 mods := modload.ListModules(args, *listU, *listVersions)
390 if !*listE {
391 for _, m := range mods {
392 if m.Error != nil {
393 base.Errorf("go list -m: %v", m.Error.Err)
394 }
395 }
396 base.ExitIfErrors()
397 }
398 for _, m := range mods {
399 do(m)
400 }
401 return
402 }
403
404
405 if *listU {
406 base.Fatalf("go list -u can only be used with -m")
407 }
408 if *listVersions {
409 base.Fatalf("go list -versions can only be used with -m")
410 }
411
412
413 if *listFind && *listDeps {
414 base.Fatalf("go list -deps cannot be used with -find")
415 }
416 if *listFind && *listTest {
417 base.Fatalf("go list -test cannot be used with -find")
418 }
419
420 load.IgnoreImports = *listFind
421 var pkgs []*load.Package
422 if *listE {
423 pkgs = load.PackagesAndErrors(args)
424 } else {
425 pkgs = load.Packages(args)
426 }
427
428 if cache.Default() == nil {
429
430
431 if *listCompiled {
432 base.Fatalf("go list -compiled requires build cache")
433 }
434 if *listExport {
435 base.Fatalf("go list -export requires build cache")
436 }
437 if *listTest {
438 base.Fatalf("go list -test requires build cache")
439 }
440 }
441
442 if *listTest {
443 c := cache.Default()
444
445 for _, p := range pkgs {
446 if p.Error != nil {
447 continue
448 }
449 if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
450 var pmain, ptest, pxtest *load.Package
451 var err error
452 if *listE {
453 pmain, ptest, pxtest = load.TestPackagesAndErrors(p, nil)
454 } else {
455 pmain, ptest, pxtest, err = load.TestPackagesFor(p, nil)
456 if err != nil {
457 base.Errorf("can't load test package: %s", err)
458 }
459 }
460 if pmain != nil {
461 pkgs = append(pkgs, pmain)
462 data := *pmain.Internal.TestmainGo
463 h := cache.NewHash("testmain")
464 h.Write([]byte("testmain\n"))
465 h.Write(data)
466 out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
467 if err != nil {
468 base.Fatalf("%s", err)
469 }
470 pmain.GoFiles[0] = c.OutputFile(out)
471 }
472 if ptest != nil && ptest != p {
473 pkgs = append(pkgs, ptest)
474 }
475 if pxtest != nil {
476 pkgs = append(pkgs, pxtest)
477 }
478 }
479 }
480 }
481
482
483 cmdline := make(map[*load.Package]bool)
484 for _, p := range pkgs {
485 cmdline[p] = true
486 }
487
488 if *listDeps {
489
490
491
492
493
494
495
496
497 pkgs = load.PackageList(pkgs)
498 }
499
500
501 needStale := *listJson || strings.Contains(*listFmt, ".Stale")
502 if needStale || *listExport || *listCompiled {
503 var b work.Builder
504 b.Init()
505 b.IsCmdList = true
506 b.NeedExport = *listExport
507 b.NeedCompiledGoFiles = *listCompiled
508 a := &work.Action{}
509
510 for _, p := range pkgs {
511 if len(p.GoFiles)+len(p.CgoFiles) > 0 {
512 a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
513 }
514 }
515 b.Do(a)
516 }
517
518 for _, p := range pkgs {
519
520 p.TestImports = p.Resolve(p.TestImports)
521 p.XTestImports = p.Resolve(p.XTestImports)
522 p.DepOnly = !cmdline[p]
523
524 if *listCompiled {
525 p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports)
526 }
527 }
528
529 if *listTest {
530 all := pkgs
531 if !*listDeps {
532 all = load.PackageList(pkgs)
533 }
534
535
536
537
538
539 old := make(map[string]string)
540 for _, p := range all {
541 if p.ForTest != "" {
542 new := p.ImportPath + " [" + p.ForTest + ".test]"
543 old[new] = p.ImportPath
544 p.ImportPath = new
545 }
546 p.DepOnly = !cmdline[p]
547 }
548
549 m := make(map[string]string)
550 for _, p := range all {
551 for _, p1 := range p.Internal.Imports {
552 if p1.ForTest != "" {
553 m[old[p1.ImportPath]] = p1.ImportPath
554 }
555 }
556 for i, old := range p.Imports {
557 if new := m[old]; new != "" {
558 p.Imports[i] = new
559 }
560 }
561 for old := range m {
562 delete(m, old)
563 }
564 }
565
566 for _, p := range all {
567 deps := make(map[string]bool)
568 for _, p1 := range p.Internal.Imports {
569 deps[p1.ImportPath] = true
570 for _, d := range p1.Deps {
571 deps[d] = true
572 }
573 }
574 p.Deps = make([]string, 0, len(deps))
575 for d := range deps {
576 p.Deps = append(p.Deps, d)
577 }
578 sort.Strings(p.Deps)
579 }
580 }
581
582
583 for _, p := range pkgs {
584 for i, srcPath := range p.Internal.RawImports {
585 path := p.Imports[i]
586 if path != srcPath {
587 if p.ImportMap == nil {
588 p.ImportMap = make(map[string]string)
589 }
590 p.ImportMap[srcPath] = path
591 }
592 }
593 }
594
595 for _, p := range pkgs {
596 do(&p.PackagePublic)
597 }
598 }
599
600
601
602
603 type TrackingWriter struct {
604 w *bufio.Writer
605 last byte
606 }
607
608 func newTrackingWriter(w io.Writer) *TrackingWriter {
609 return &TrackingWriter{
610 w: bufio.NewWriter(w),
611 last: '\n',
612 }
613 }
614
615 func (t *TrackingWriter) Write(p []byte) (n int, err error) {
616 n, err = t.w.Write(p)
617 if n > 0 {
618 t.last = p[n-1]
619 }
620 return
621 }
622
623 func (t *TrackingWriter) Flush() {
624 t.w.Flush()
625 }
626
627 func (t *TrackingWriter) NeedNL() bool {
628 return t.last != '\n'
629 }
630
View as plain text