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 list implements the ``go list'' command.
6package list
7
8import (
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
27var CmdList = &base.Command{
28	// Note: -f -json -m are listed explicitly because they are the most common list flags.
29	// Do not send CLs removing them because they're covered by [list flags].
30	UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]",
31	Short:     "list packages or modules",
32	Long: `
33List lists the named packages, one per line.
34The most commonly-used flags are -f and -json, which control the form
35of the output printed for each package. Other list flags, documented below,
36control more specific details.
37
38The 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
45The -f flag specifies an alternate format for the list, using the
46syntax of package template. The default output is equivalent
47to -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: cannot be recompiled from sources
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
108Packages stored in vendor directories report an ImportPath that includes the
109path to the vendor directory (for example, "d/vendor/p" instead of "p"),
110so that the ImportPath uniquely identifies a given copy of a package.
111The Imports, Deps, TestImports, and XTestImports lists also contain these
112expanded import paths. See golang.org/s/go15vendor for more about vendoring.
113
114The 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
122The module information is a Module struct, defined in the discussion
123of list -m below.
124
125The template function "join" calls strings.Join.
126
127The 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
142For more information about the meaning of these fields see the documentation
143for the go/build package's Context type.
144
145The -json flag causes the package data to be printed in JSON format
146instead of using the template format.
147
148The -compiled flag causes list to set CompiledGoFiles to the Go source
149files presented to the compiler. Typically this means that it repeats
150the files listed in GoFiles and then also adds the Go code generated
151by processing CgoFiles and SwigFiles. The Imports list contains the
152union of all imports from both GoFiles and CompiledGoFiles.
153
154The -deps flag causes list to iterate over not just the named packages
155but also all their dependencies. It visits them in a depth-first post-order
156traversal, so that a package is listed only after all its dependencies.
157Packages not explicitly listed on the command line will have the DepOnly
158field set to true.
159
160The -e flag changes the handling of erroneous packages, those that
161cannot be found or are malformed. By default, the list command
162prints an error to standard error for each erroneous package and
163omits the packages from consideration during the usual printing.
164With the -e flag, the list command never prints errors to standard
165error and instead processes the erroneous packages with the usual
166printing. Erroneous packages will have a non-empty ImportPath and
167a non-nil Error field; other information may or may not be missing
168(zeroed).
169
170The -export flag causes list to set the Export field to the name of a
171file containing up-to-date export information for the given package.
172
173The -find flag causes list to identify the named packages but not
174resolve their dependencies: the Imports and Deps lists will be empty.
175
176The -test flag causes list to report not only the named packages
177but also their test binaries (for packages with tests), to convey to
178source code analysis tools exactly how test binaries are constructed.
179The reported import path for a test binary is the import path of
180the package followed by a ".test" suffix, as in "math/rand.test".
181When building a test, it is sometimes necessary to rebuild certain
182dependencies specially for that test (most commonly the tested
183package itself). The reported import path of a package recompiled
184for a particular test binary is followed by a space and the name of
185the test binary in brackets, as in "math/rand [math/rand.test]"
186or "regexp [sort.test]". The ForTest field is also set to the name
187of the package being tested ("math/rand" or "sort" in the previous
188examples).
189
190The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
191are all absolute paths.
192
193By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
194(that is, paths relative to Dir, not absolute paths).
195The generated files added when using the -compiled and -test flags
196are absolute paths referring to cached copies of generated Go source files.
197Although they are Go source files, the paths may not end in ".go".
198
199The -m flag causes list to list modules instead of packages.
200
201When listing modules, the -f flag still specifies a format template
202applied 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        Error    *ModuleError // error loading module
216    }
217
218    type ModuleError struct {
219        Err string // the error itself
220    }
221
222The default output is to print the module path and then
223information about the version and replacement if any.
224For example, 'go list -m all' might print:
225
226    my/main/module
227    golang.org/x/text v0.3.0 => /tmp/text
228    rsc.io/pdf v0.1.1
229
230The Module struct has a String method that formats this
231line of output, so that the default format is equivalent
232to -f '{{.String}}'.
233
234Note that when a module has been replaced, its Replace field
235describes the replacement module, and its Dir field is set to
236the replacement's source code, if present. (That is, if Replace
237is non-nil, then Dir is set to Replace.Dir, with no access to
238the replaced source code.)
239
240The -u flag adds information about available upgrades.
241When the latest version of a given module is newer than
242the current one, list -u sets the Module's Update field
243to information about the newer module.
244The Module's String method indicates an available upgrade by
245formatting the newer version in brackets after the current version.
246For example, 'go list -m -u all' might print:
247
248    my/main/module
249    golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
250    rsc.io/pdf v0.1.1 [v0.1.2]
251
252(For tools, 'go list -m -u -json all' may be more convenient to parse.)
253
254The -versions flag causes list to set the Module's Versions field
255to a list of all known versions of that module, ordered according
256to semantic versioning, earliest to latest. The flag also changes
257the default output format to display the module path followed by the
258space-separated version list.
259
260The arguments to list -m are interpreted as a list of modules, not packages.
261The main module is the module containing the current directory.
262The active modules are the main module and its dependencies.
263With no arguments, list -m shows the main module.
264With arguments, list -m shows the modules specified by the arguments.
265Any of the active modules can be specified by its module path.
266The special pattern "all" specifies all the active modules, first the main
267module and then dependencies sorted by module path.
268A pattern containing "..." specifies the active modules whose
269module paths match the pattern.
270A query of the form path@version specifies the result of that query,
271which is not limited to active modules.
272See 'go help modules' for more about module queries.
273
274The template function "module" takes a single string argument
275that must be a module path or query and returns the specified
276module as a Module struct. If an error occurs, the result will
277be a Module struct with a non-nil Error field.
278
279For more about build flags, see 'go help build'.
280
281For more about specifying packages, see 'go help packages'.
282
283For more about modules, see 'go help modules'.
284	`,
285}
286
287func init() {
288	CmdList.Run = runList // break init cycle
289	work.AddBuildFlags(CmdList)
290}
291
292var (
293	listCompiled = CmdList.Flag.Bool("compiled", false, "")
294	listDeps     = CmdList.Flag.Bool("deps", false, "")
295	listE        = CmdList.Flag.Bool("e", false, "")
296	listExport   = CmdList.Flag.Bool("export", false, "")
297	listFmt      = CmdList.Flag.String("f", "", "")
298	listFind     = CmdList.Flag.Bool("find", false, "")
299	listJson     = CmdList.Flag.Bool("json", false, "")
300	listM        = CmdList.Flag.Bool("m", false, "")
301	listU        = CmdList.Flag.Bool("u", false, "")
302	listTest     = CmdList.Flag.Bool("test", false, "")
303	listVersions = CmdList.Flag.Bool("versions", false, "")
304)
305
306var nl = []byte{'\n'}
307
308func runList(cmd *base.Command, args []string) {
309	modload.LoadTests = *listTest
310	work.BuildInit()
311	out := newTrackingWriter(os.Stdout)
312	defer out.w.Flush()
313
314	if *listFmt == "" {
315		if *listM {
316			*listFmt = "{{.String}}"
317			if *listVersions {
318				*listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}`
319			}
320		} else {
321			*listFmt = "{{.ImportPath}}"
322		}
323	}
324
325	var do func(interface{})
326	if *listJson {
327		do = func(x interface{}) {
328			b, err := json.MarshalIndent(x, "", "\t")
329			if err != nil {
330				out.Flush()
331				base.Fatalf("%s", err)
332			}
333			out.Write(b)
334			out.Write(nl)
335		}
336	} else {
337		var cachedCtxt *Context
338		context := func() *Context {
339			if cachedCtxt == nil {
340				cachedCtxt = newContext(&cfg.BuildContext)
341			}
342			return cachedCtxt
343		}
344		fm := template.FuncMap{
345			"join":    strings.Join,
346			"context": context,
347			"module":  modload.ModuleInfo,
348		}
349		tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
350		if err != nil {
351			base.Fatalf("%s", err)
352		}
353		do = func(x interface{}) {
354			if err := tmpl.Execute(out, x); err != nil {
355				out.Flush()
356				base.Fatalf("%s", err)
357			}
358			if out.NeedNL() {
359				out.Write(nl)
360			}
361		}
362	}
363
364	if *listM {
365		// Module mode.
366		if *listCompiled {
367			base.Fatalf("go list -compiled cannot be used with -m")
368		}
369		if *listDeps {
370			// TODO(rsc): Could make this mean something with -m.
371			base.Fatalf("go list -deps cannot be used with -m")
372		}
373		if *listExport {
374			base.Fatalf("go list -export cannot be used with -m")
375		}
376		if *listFind {
377			base.Fatalf("go list -find cannot be used with -m")
378		}
379		if *listTest {
380			base.Fatalf("go list -test cannot be used with -m")
381		}
382
383		if modload.Init(); !modload.Enabled() {
384			base.Fatalf("go list -m: not using modules")
385		}
386		modload.LoadBuildList()
387
388		mods := modload.ListModules(args, *listU, *listVersions)
389		if !*listE {
390			for _, m := range mods {
391				if m.Error != nil {
392					base.Errorf("go list -m %s: %v", m.Path, m.Error.Err)
393				}
394			}
395			base.ExitIfErrors()
396		}
397		for _, m := range mods {
398			do(m)
399		}
400		return
401	}
402
403	// Package mode (not -m).
404	if *listU {
405		base.Fatalf("go list -u can only be used with -m")
406	}
407	if *listVersions {
408		base.Fatalf("go list -versions can only be used with -m")
409	}
410
411	// These pairings make no sense.
412	if *listFind && *listDeps {
413		base.Fatalf("go list -deps cannot be used with -find")
414	}
415	if *listFind && *listTest {
416		base.Fatalf("go list -test cannot be used with -find")
417	}
418
419	load.IgnoreImports = *listFind
420	var pkgs []*load.Package
421	if *listE {
422		pkgs = load.PackagesAndErrors(args)
423	} else {
424		pkgs = load.Packages(args)
425	}
426
427	if cache.Default() == nil {
428		// These flags return file names pointing into the build cache,
429		// so the build cache must exist.
430		if *listCompiled {
431			base.Fatalf("go list -compiled requires build cache")
432		}
433		if *listExport {
434			base.Fatalf("go list -export requires build cache")
435		}
436		if *listTest {
437			base.Fatalf("go list -test requires build cache")
438		}
439	}
440
441	if *listTest {
442		c := cache.Default()
443		// Add test binaries to packages to be listed.
444		for _, p := range pkgs {
445			if p.Error != nil {
446				continue
447			}
448			if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
449				pmain, ptest, pxtest, err := load.GetTestPackagesFor(p, nil)
450				if err != nil {
451					if *listE {
452						pkgs = append(pkgs, &load.Package{
453							PackagePublic: load.PackagePublic{
454								ImportPath: p.ImportPath + ".test",
455								Error:      &load.PackageError{Err: err.Error()},
456							},
457						})
458						continue
459					}
460					base.Errorf("can't load test package: %s", err)
461					continue
462				}
463				pkgs = append(pkgs, pmain)
464				if ptest != nil {
465					pkgs = append(pkgs, ptest)
466				}
467				if pxtest != nil {
468					pkgs = append(pkgs, pxtest)
469				}
470
471				data := *pmain.Internal.TestmainGo
472				h := cache.NewHash("testmain")
473				h.Write([]byte("testmain\n"))
474				h.Write(data)
475				out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
476				if err != nil {
477					base.Fatalf("%s", err)
478				}
479				pmain.GoFiles[0] = c.OutputFile(out)
480			}
481		}
482	}
483
484	// Remember which packages are named on the command line.
485	cmdline := make(map[*load.Package]bool)
486	for _, p := range pkgs {
487		cmdline[p] = true
488	}
489
490	if *listDeps {
491		// Note: This changes the order of the listed packages
492		// from "as written on the command line" to
493		// "a depth-first post-order traversal".
494		// (The dependency exploration order for a given node
495		// is alphabetical, same as listed in .Deps.)
496		// Note that -deps is applied after -test,
497		// so that you only get descriptions of tests for the things named
498		// explicitly on the command line, not for all dependencies.
499		pkgs = load.PackageList(pkgs)
500	}
501
502	// Do we need to run a build to gather information?
503	needStale := *listJson || strings.Contains(*listFmt, ".Stale")
504	if needStale || *listExport || *listCompiled {
505		var b work.Builder
506		b.Init()
507		b.IsCmdList = true
508		b.NeedExport = *listExport
509		b.NeedCompiledGoFiles = *listCompiled
510		a := &work.Action{}
511		// TODO: Use pkgsFilter?
512		for _, p := range pkgs {
513			if len(p.GoFiles)+len(p.CgoFiles) > 0 {
514				a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
515			}
516		}
517		b.Do(a)
518	}
519
520	for _, p := range pkgs {
521		// Show vendor-expanded paths in listing
522		p.TestImports = p.Resolve(p.TestImports)
523		p.XTestImports = p.Resolve(p.XTestImports)
524		p.DepOnly = !cmdline[p]
525
526		if *listCompiled {
527			p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports)
528		}
529	}
530
531	if *listTest {
532		all := pkgs
533		if !*listDeps {
534			all = load.PackageList(pkgs)
535		}
536		// Update import paths to distinguish the real package p
537		// from p recompiled for q.test.
538		// This must happen only once the build code is done
539		// looking at import paths, because it will get very confused
540		// if it sees these.
541		old := make(map[string]string)
542		for _, p := range all {
543			if p.ForTest != "" {
544				new := p.ImportPath + " [" + p.ForTest + ".test]"
545				old[new] = p.ImportPath
546				p.ImportPath = new
547			}
548			p.DepOnly = !cmdline[p]
549		}
550		// Update import path lists to use new strings.
551		m := make(map[string]string)
552		for _, p := range all {
553			for _, p1 := range p.Internal.Imports {
554				if p1.ForTest != "" {
555					m[old[p1.ImportPath]] = p1.ImportPath
556				}
557			}
558			for i, old := range p.Imports {
559				if new := m[old]; new != "" {
560					p.Imports[i] = new
561				}
562			}
563			for old := range m {
564				delete(m, old)
565			}
566		}
567		// Recompute deps lists using new strings, from the leaves up.
568		for _, p := range all {
569			deps := make(map[string]bool)
570			for _, p1 := range p.Internal.Imports {
571				deps[p1.ImportPath] = true
572				for _, d := range p1.Deps {
573					deps[d] = true
574				}
575			}
576			p.Deps = make([]string, 0, len(deps))
577			for d := range deps {
578				p.Deps = append(p.Deps, d)
579			}
580			sort.Strings(p.Deps)
581		}
582	}
583
584	// Record non-identity import mappings in p.ImportMap.
585	for _, p := range pkgs {
586		for i, srcPath := range p.Internal.RawImports {
587			path := p.Imports[i]
588			if path != srcPath {
589				if p.ImportMap == nil {
590					p.ImportMap = make(map[string]string)
591				}
592				p.ImportMap[srcPath] = path
593			}
594		}
595	}
596
597	for _, p := range pkgs {
598		do(&p.PackagePublic)
599	}
600}
601
602// TrackingWriter tracks the last byte written on every write so
603// we can avoid printing a newline if one was already written or
604// if there is no output at all.
605type TrackingWriter struct {
606	w    *bufio.Writer
607	last byte
608}
609
610func newTrackingWriter(w io.Writer) *TrackingWriter {
611	return &TrackingWriter{
612		w:    bufio.NewWriter(w),
613		last: '\n',
614	}
615}
616
617func (t *TrackingWriter) Write(p []byte) (n int, err error) {
618	n, err = t.w.Write(p)
619	if n > 0 {
620		t.last = p[n-1]
621	}
622	return
623}
624
625func (t *TrackingWriter) Flush() {
626	t.w.Flush()
627}
628
629func (t *TrackingWriter) NeedNL() bool {
630	return t.last != '\n'
631}
632