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