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 (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
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 used when loading 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
223The file GoMod refers to may be outside the module directory if the
224module is in the module cache or if the -modfile flag is used.
225
226The default output is to print the module path and then
227information about the version and replacement if any.
228For example, 'go list -m all' might print:
229
230    my/main/module
231    golang.org/x/text v0.3.0 => /tmp/text
232    rsc.io/pdf v0.1.1
233
234The Module struct has a String method that formats this
235line of output, so that the default format is equivalent
236to -f '{{.String}}'.
237
238Note that when a module has been replaced, its Replace field
239describes the replacement module, and its Dir field is set to
240the replacement's source code, if present. (That is, if Replace
241is non-nil, then Dir is set to Replace.Dir, with no access to
242the replaced source code.)
243
244The -u flag adds information about available upgrades.
245When the latest version of a given module is newer than
246the current one, list -u sets the Module's Update field
247to information about the newer module.
248The Module's String method indicates an available upgrade by
249formatting the newer version in brackets after the current version.
250For example, 'go list -m -u all' might print:
251
252    my/main/module
253    golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
254    rsc.io/pdf v0.1.1 [v0.1.2]
255
256(For tools, 'go list -m -u -json all' may be more convenient to parse.)
257
258The -versions flag causes list to set the Module's Versions field
259to a list of all known versions of that module, ordered according
260to semantic versioning, earliest to latest. The flag also changes
261the default output format to display the module path followed by the
262space-separated version list.
263
264The arguments to list -m are interpreted as a list of modules, not packages.
265The main module is the module containing the current directory.
266The active modules are the main module and its dependencies.
267With no arguments, list -m shows the main module.
268With arguments, list -m shows the modules specified by the arguments.
269Any of the active modules can be specified by its module path.
270The special pattern "all" specifies all the active modules, first the main
271module and then dependencies sorted by module path.
272A pattern containing "..." specifies the active modules whose
273module paths match the pattern.
274A query of the form path@version specifies the result of that query,
275which is not limited to active modules.
276See 'go help modules' for more about module queries.
277
278The template function "module" takes a single string argument
279that must be a module path or query and returns the specified
280module as a Module struct. If an error occurs, the result will
281be a Module struct with a non-nil Error field.
282
283For more about build flags, see 'go help build'.
284
285For more about specifying packages, see 'go help packages'.
286
287For more about modules, see 'go help modules'.
288	`,
289}
290
291func init() {
292	CmdList.Run = runList // break init cycle
293	work.AddBuildFlags(CmdList, work.DefaultBuildFlags)
294}
295
296var (
297	listCompiled = CmdList.Flag.Bool("compiled", false, "")
298	listDeps     = CmdList.Flag.Bool("deps", false, "")
299	listE        = CmdList.Flag.Bool("e", false, "")
300	listExport   = CmdList.Flag.Bool("export", false, "")
301	listFmt      = CmdList.Flag.String("f", "", "")
302	listFind     = CmdList.Flag.Bool("find", false, "")
303	listJson     = CmdList.Flag.Bool("json", false, "")
304	listM        = CmdList.Flag.Bool("m", false, "")
305	listU        = CmdList.Flag.Bool("u", false, "")
306	listTest     = CmdList.Flag.Bool("test", false, "")
307	listVersions = CmdList.Flag.Bool("versions", false, "")
308)
309
310var nl = []byte{'\n'}
311
312func runList(cmd *base.Command, args []string) {
313	modload.LoadTests = *listTest
314	work.BuildInit()
315	out := newTrackingWriter(os.Stdout)
316	defer out.w.Flush()
317
318	if *listFmt == "" {
319		if *listM {
320			*listFmt = "{{.String}}"
321			if *listVersions {
322				*listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}`
323			}
324		} else {
325			*listFmt = "{{.ImportPath}}"
326		}
327	}
328
329	var do func(interface{})
330	if *listJson {
331		do = func(x interface{}) {
332			b, err := json.MarshalIndent(x, "", "\t")
333			if err != nil {
334				out.Flush()
335				base.Fatalf("%s", err)
336			}
337			out.Write(b)
338			out.Write(nl)
339		}
340	} else {
341		var cachedCtxt *Context
342		context := func() *Context {
343			if cachedCtxt == nil {
344				cachedCtxt = newContext(&cfg.BuildContext)
345			}
346			return cachedCtxt
347		}
348		fm := template.FuncMap{
349			"join":    strings.Join,
350			"context": context,
351			"module":  modload.ModuleInfo,
352		}
353		tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
354		if err != nil {
355			base.Fatalf("%s", err)
356		}
357		do = func(x interface{}) {
358			if err := tmpl.Execute(out, x); err != nil {
359				out.Flush()
360				base.Fatalf("%s", err)
361			}
362			if out.NeedNL() {
363				out.Write(nl)
364			}
365		}
366	}
367
368	if *listM {
369		// Module mode.
370		if *listCompiled {
371			base.Fatalf("go list -compiled cannot be used with -m")
372		}
373		if *listDeps {
374			// TODO(rsc): Could make this mean something with -m.
375			base.Fatalf("go list -deps cannot be used with -m")
376		}
377		if *listExport {
378			base.Fatalf("go list -export cannot be used with -m")
379		}
380		if *listFind {
381			base.Fatalf("go list -find cannot be used with -m")
382		}
383		if *listTest {
384			base.Fatalf("go list -test cannot be used with -m")
385		}
386
387		if modload.Init(); !modload.Enabled() {
388			base.Fatalf("go list -m: not using modules")
389		}
390
391		modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
392		if cfg.BuildMod == "vendor" {
393			const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
394
395			if *listVersions {
396				base.Fatalf(actionDisabledFormat, "determine available versions")
397			}
398			if *listU {
399				base.Fatalf(actionDisabledFormat, "determine available upgrades")
400			}
401
402			for _, arg := range args {
403				// In vendor mode, the module graph is incomplete: it contains only the
404				// explicit module dependencies and the modules that supply packages in
405				// the import graph. Reject queries that imply more information than that.
406				if arg == "all" {
407					base.Fatalf(actionDisabledFormat, "compute 'all'")
408				}
409				if strings.Contains(arg, "...") {
410					base.Fatalf(actionDisabledFormat, "match module patterns")
411				}
412			}
413		}
414
415		modload.LoadBuildList()
416
417		mods := modload.ListModules(args, *listU, *listVersions)
418		if !*listE {
419			for _, m := range mods {
420				if m.Error != nil {
421					base.Errorf("go list -m: %v", m.Error.Err)
422				}
423			}
424			base.ExitIfErrors()
425		}
426		for _, m := range mods {
427			do(m)
428		}
429		return
430	}
431
432	// Package mode (not -m).
433	if *listU {
434		base.Fatalf("go list -u can only be used with -m")
435	}
436	if *listVersions {
437		base.Fatalf("go list -versions can only be used with -m")
438	}
439
440	// These pairings make no sense.
441	if *listFind && *listDeps {
442		base.Fatalf("go list -deps cannot be used with -find")
443	}
444	if *listFind && *listTest {
445		base.Fatalf("go list -test cannot be used with -find")
446	}
447
448	load.IgnoreImports = *listFind
449	var pkgs []*load.Package
450	if *listE {
451		pkgs = load.PackagesAndErrors(args)
452	} else {
453		pkgs = load.Packages(args)
454	}
455
456	if cache.Default() == nil {
457		// These flags return file names pointing into the build cache,
458		// so the build cache must exist.
459		if *listCompiled {
460			base.Fatalf("go list -compiled requires build cache")
461		}
462		if *listExport {
463			base.Fatalf("go list -export requires build cache")
464		}
465		if *listTest {
466			base.Fatalf("go list -test requires build cache")
467		}
468	}
469
470	if *listTest {
471		c := cache.Default()
472		// Add test binaries to packages to be listed.
473		for _, p := range pkgs {
474			if p.Error != nil {
475				continue
476			}
477			if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
478				var pmain, ptest, pxtest *load.Package
479				var err error
480				if *listE {
481					pmain, ptest, pxtest = load.TestPackagesAndErrors(p, nil)
482				} else {
483					pmain, ptest, pxtest, err = load.TestPackagesFor(p, nil)
484					if err != nil {
485						base.Errorf("can't load test package: %s", err)
486					}
487				}
488				if pmain != nil {
489					pkgs = append(pkgs, pmain)
490					data := *pmain.Internal.TestmainGo
491					h := cache.NewHash("testmain")
492					h.Write([]byte("testmain\n"))
493					h.Write(data)
494					out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
495					if err != nil {
496						base.Fatalf("%s", err)
497					}
498					pmain.GoFiles[0] = c.OutputFile(out)
499				}
500				if ptest != nil && ptest != p {
501					pkgs = append(pkgs, ptest)
502				}
503				if pxtest != nil {
504					pkgs = append(pkgs, pxtest)
505				}
506			}
507		}
508	}
509
510	// Remember which packages are named on the command line.
511	cmdline := make(map[*load.Package]bool)
512	for _, p := range pkgs {
513		cmdline[p] = true
514	}
515
516	if *listDeps {
517		// Note: This changes the order of the listed packages
518		// from "as written on the command line" to
519		// "a depth-first post-order traversal".
520		// (The dependency exploration order for a given node
521		// is alphabetical, same as listed in .Deps.)
522		// Note that -deps is applied after -test,
523		// so that you only get descriptions of tests for the things named
524		// explicitly on the command line, not for all dependencies.
525		pkgs = load.PackageList(pkgs)
526	}
527
528	// Do we need to run a build to gather information?
529	needStale := *listJson || strings.Contains(*listFmt, ".Stale")
530	if needStale || *listExport || *listCompiled {
531		var b work.Builder
532		b.Init()
533		b.IsCmdList = true
534		b.NeedExport = *listExport
535		b.NeedCompiledGoFiles = *listCompiled
536		a := &work.Action{}
537		// TODO: Use pkgsFilter?
538		for _, p := range pkgs {
539			if len(p.GoFiles)+len(p.CgoFiles) > 0 {
540				a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
541			}
542		}
543		b.Do(a)
544	}
545
546	for _, p := range pkgs {
547		// Show vendor-expanded paths in listing
548		p.TestImports = p.Resolve(p.TestImports)
549		p.XTestImports = p.Resolve(p.XTestImports)
550		p.DepOnly = !cmdline[p]
551
552		if *listCompiled {
553			p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports)
554		}
555	}
556
557	if *listTest {
558		all := pkgs
559		if !*listDeps {
560			all = load.PackageList(pkgs)
561		}
562		// Update import paths to distinguish the real package p
563		// from p recompiled for q.test.
564		// This must happen only once the build code is done
565		// looking at import paths, because it will get very confused
566		// if it sees these.
567		old := make(map[string]string)
568		for _, p := range all {
569			if p.ForTest != "" {
570				new := p.ImportPath + " [" + p.ForTest + ".test]"
571				old[new] = p.ImportPath
572				p.ImportPath = new
573			}
574			p.DepOnly = !cmdline[p]
575		}
576		// Update import path lists to use new strings.
577		m := make(map[string]string)
578		for _, p := range all {
579			for _, p1 := range p.Internal.Imports {
580				if p1.ForTest != "" {
581					m[old[p1.ImportPath]] = p1.ImportPath
582				}
583			}
584			for i, old := range p.Imports {
585				if new := m[old]; new != "" {
586					p.Imports[i] = new
587				}
588			}
589			for old := range m {
590				delete(m, old)
591			}
592		}
593		// Recompute deps lists using new strings, from the leaves up.
594		for _, p := range all {
595			deps := make(map[string]bool)
596			for _, p1 := range p.Internal.Imports {
597				deps[p1.ImportPath] = true
598				for _, d := range p1.Deps {
599					deps[d] = true
600				}
601			}
602			p.Deps = make([]string, 0, len(deps))
603			for d := range deps {
604				p.Deps = append(p.Deps, d)
605			}
606			sort.Strings(p.Deps)
607		}
608	}
609
610	// Record non-identity import mappings in p.ImportMap.
611	for _, p := range pkgs {
612		for i, srcPath := range p.Internal.RawImports {
613			path := p.Imports[i]
614			if path != srcPath {
615				if p.ImportMap == nil {
616					p.ImportMap = make(map[string]string)
617				}
618				p.ImportMap[srcPath] = path
619			}
620		}
621	}
622
623	for _, p := range pkgs {
624		do(&p.PackagePublic)
625	}
626}
627
628// TrackingWriter tracks the last byte written on every write so
629// we can avoid printing a newline if one was already written or
630// if there is no output at all.
631type TrackingWriter struct {
632	w    *bufio.Writer
633	last byte
634}
635
636func newTrackingWriter(w io.Writer) *TrackingWriter {
637	return &TrackingWriter{
638		w:    bufio.NewWriter(w),
639		last: '\n',
640	}
641}
642
643func (t *TrackingWriter) Write(p []byte) (n int, err error) {
644	n, err = t.w.Write(p)
645	if n > 0 {
646		t.last = p[n-1]
647	}
648	return
649}
650
651func (t *TrackingWriter) Flush() {
652	t.w.Flush()
653}
654
655func (t *TrackingWriter) NeedNL() bool {
656	return t.last != '\n'
657}
658