1
2
3
4
5
6 package list
7
8 import (
9 "bufio"
10 "bytes"
11 "context"
12 "encoding/json"
13 "errors"
14 "fmt"
15 "io"
16 "os"
17 "reflect"
18 "runtime"
19 "sort"
20 "strconv"
21 "strings"
22 "sync"
23 "text/template"
24
25 "cmd/go/internal/base"
26 "cmd/go/internal/cache"
27 "cmd/go/internal/cfg"
28 "cmd/go/internal/load"
29 "cmd/go/internal/modinfo"
30 "cmd/go/internal/modload"
31 "cmd/go/internal/str"
32 "cmd/go/internal/work"
33
34 "golang.org/x/sync/semaphore"
35 )
36
37 var CmdList = &base.Command{
38
39
40 UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]",
41 Short: "list packages or modules",
42 Long: `
43 List lists the named packages, one per line.
44 The most commonly-used flags are -f and -json, which control the form
45 of the output printed for each package. Other list flags, documented below,
46 control more specific details.
47
48 The default output shows the package import path:
49
50 bytes
51 encoding/json
52 github.com/gorilla/mux
53 golang.org/x/net/html
54
55 The -f flag specifies an alternate format for the list, using the
56 syntax of package template. The default output is equivalent
57 to -f '{{.ImportPath}}'. The struct being passed to the template is:
58
59 type Package struct {
60 Dir string // directory containing package sources
61 ImportPath string // import path of package in dir
62 ImportComment string // path in import comment on package statement
63 Name string // package name
64 Doc string // package documentation string
65 Target string // install path
66 Shlib string // the shared library that contains this package (only set when -linkshared)
67 Goroot bool // is this package in the Go root?
68 Standard bool // is this package part of the standard Go library?
69 Stale bool // would 'go install' do anything for this package?
70 StaleReason string // explanation for Stale==true
71 Root string // Go root or Go path dir containing this package
72 ConflictDir string // this directory shadows Dir in $GOPATH
73 BinaryOnly bool // binary-only package (no longer supported)
74 ForTest string // package is only for use in named test
75 Export string // file containing export data (when using -export)
76 BuildID string // build ID of the compiled package (when using -export)
77 Module *Module // info about package's containing module, if any (can be nil)
78 Match []string // command-line patterns matching this package
79 DepOnly bool // package is only a dependency, not explicitly listed
80 DefaultGODEBUG string // default GODEBUG setting, for main packages
81
82 // Source files
83 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
84 CgoFiles []string // .go source files that import "C"
85 CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
86 IgnoredGoFiles []string // .go source files ignored due to build constraints
87 IgnoredOtherFiles []string // non-.go source files ignored due to build constraints
88 CFiles []string // .c source files
89 CXXFiles []string // .cc, .cxx and .cpp source files
90 MFiles []string // .m source files
91 HFiles []string // .h, .hh, .hpp and .hxx source files
92 FFiles []string // .f, .F, .for and .f90 Fortran source files
93 SFiles []string // .s source files
94 SwigFiles []string // .swig files
95 SwigCXXFiles []string // .swigcxx files
96 SysoFiles []string // .syso object files to add to archive
97 TestGoFiles []string // _test.go files in package
98 XTestGoFiles []string // _test.go files outside package
99
100 // Embedded files
101 EmbedPatterns []string // //go:embed patterns
102 EmbedFiles []string // files matched by EmbedPatterns
103 TestEmbedPatterns []string // //go:embed patterns in TestGoFiles
104 TestEmbedFiles []string // files matched by TestEmbedPatterns
105 XTestEmbedPatterns []string // //go:embed patterns in XTestGoFiles
106 XTestEmbedFiles []string // files matched by XTestEmbedPatterns
107
108 // Cgo directives
109 CgoCFLAGS []string // cgo: flags for C compiler
110 CgoCPPFLAGS []string // cgo: flags for C preprocessor
111 CgoCXXFLAGS []string // cgo: flags for C++ compiler
112 CgoFFLAGS []string // cgo: flags for Fortran compiler
113 CgoLDFLAGS []string // cgo: flags for linker
114 CgoPkgConfig []string // cgo: pkg-config names
115
116 // Dependency information
117 Imports []string // import paths used by this package
118 ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
119 Deps []string // all (recursively) imported dependencies
120 TestImports []string // imports from TestGoFiles
121 XTestImports []string // imports from XTestGoFiles
122
123 // Error information
124 Incomplete bool // this package or a dependency has an error
125 Error *PackageError // error loading package
126 DepsErrors []*PackageError // errors loading dependencies
127 }
128
129 Packages stored in vendor directories report an ImportPath that includes the
130 path to the vendor directory (for example, "d/vendor/p" instead of "p"),
131 so that the ImportPath uniquely identifies a given copy of a package.
132 The Imports, Deps, TestImports, and XTestImports lists also contain these
133 expanded import paths. See golang.org/s/go15vendor for more about vendoring.
134
135 The error information, if any, is
136
137 type PackageError struct {
138 ImportStack []string // shortest path from package named on command line to this one
139 Pos string // position of error (if present, file:line:col)
140 Err string // the error itself
141 }
142
143 The module information is a Module struct, defined in the discussion
144 of list -m below.
145
146 The template function "join" calls strings.Join.
147
148 The template function "json" marshals its arguments to JSON.
149
150 The template function "context" returns the build context, defined as:
151
152 type Context struct {
153 GOARCH string // target architecture
154 GOOS string // target operating system
155 GOROOT string // Go root
156 GOPATH string // Go path
157 CgoEnabled bool // whether cgo can be used
158 UseAllFiles bool // use files regardless of //go:build lines, file names
159 Compiler string // compiler to assume when computing target paths
160 BuildTags []string // build constraints to match in //go:build lines
161 ToolTags []string // toolchain-specific build constraints
162 ReleaseTags []string // releases the current release is compatible with
163 InstallSuffix string // suffix to use in the name of the install dir
164 }
165
166 The template function "module" takes a module path as a parameter,
167 and returns information about the module, defined as the Module struct below.
168
169 For more information about the meaning of these fields see the documentation
170 for the go/build package's Context type.
171
172 The -json flag causes the package data to be printed in JSON format
173 instead of using the template format. The JSON flag can optionally be
174 provided with a set of comma-separated required field names to be output.
175 If so, those required fields will always appear in JSON output, but
176 others may be omitted to save work in computing the JSON struct.
177
178 The -compiled flag causes list to set CompiledGoFiles to the Go source
179 files presented to the compiler. Typically this means that it repeats
180 the files listed in GoFiles and then also adds the Go code generated
181 by processing CgoFiles and SwigFiles. The Imports list contains the
182 union of all imports from both GoFiles and CompiledGoFiles.
183
184 The -deps flag causes list to iterate over not just the named packages
185 but also all their dependencies. It visits them in a depth-first post-order
186 traversal, so that a package is listed only after all its dependencies.
187 Packages not explicitly listed on the command line will have the DepOnly
188 field set to true.
189
190 The -e flag changes the handling of erroneous packages, those that
191 cannot be found or are malformed. By default, the list command
192 prints an error to standard error for each erroneous package and
193 omits the packages from consideration during the usual printing.
194 With the -e flag, the list command never prints errors to standard
195 error and instead processes the erroneous packages with the usual
196 printing. Erroneous packages will have a non-empty ImportPath and
197 a non-nil Error field; other information may or may not be missing
198 (zeroed).
199
200 The -export flag causes list to set the Export field to the name of a
201 file containing up-to-date export information for the given package,
202 and the BuildID field to the build ID of the compiled package.
203
204 The -find flag causes list to identify the named packages but not
205 resolve their dependencies: the Imports and Deps lists will be empty.
206 With the -find flag, the -deps, -test and -export commands cannot be
207 used.
208
209 The -test flag causes list to report not only the named packages
210 but also their test binaries (for packages with tests), to convey to
211 source code analysis tools exactly how test binaries are constructed.
212 The reported import path for a test binary is the import path of
213 the package followed by a ".test" suffix, as in "math/rand.test".
214 When building a test, it is sometimes necessary to rebuild certain
215 dependencies specially for that test (most commonly the tested
216 package itself). The reported import path of a package recompiled
217 for a particular test binary is followed by a space and the name of
218 the test binary in brackets, as in "math/rand [math/rand.test]"
219 or "regexp [sort.test]". The ForTest field is also set to the name
220 of the package being tested ("math/rand" or "sort" in the previous
221 examples).
222
223 The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
224 are all absolute paths.
225
226 By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
227 (that is, paths relative to Dir, not absolute paths).
228 The generated files added when using the -compiled and -test flags
229 are absolute paths referring to cached copies of generated Go source files.
230 Although they are Go source files, the paths may not end in ".go".
231
232 The -m flag causes list to list modules instead of packages.
233
234 When listing modules, the -f flag still specifies a format template
235 applied to a Go struct, but now a Module struct:
236
237 type Module struct {
238 Path string // module path
239 Query string // version query corresponding to this version
240 Version string // module version
241 Versions []string // available module versions
242 Replace *Module // replaced by this module
243 Time *time.Time // time version was created
244 Update *Module // available update (with -u)
245 Main bool // is this the main module?
246 Indirect bool // module is only indirectly needed by main module
247 Dir string // directory holding local copy of files, if any
248 GoMod string // path to go.mod file describing module, if any
249 GoVersion string // go version used in module
250 Retracted []string // retraction information, if any (with -retracted or -u)
251 Deprecated string // deprecation message, if any (with -u)
252 Error *ModuleError // error loading module
253 Sum string // checksum for path, version (as in go.sum)
254 GoModSum string // checksum for go.mod (as in go.sum)
255 Origin any // provenance of module
256 Reuse bool // reuse of old module info is safe
257 }
258
259 type ModuleError struct {
260 Err string // the error itself
261 }
262
263 The file GoMod refers to may be outside the module directory if the
264 module is in the module cache or if the -modfile flag is used.
265
266 The default output is to print the module path and then
267 information about the version and replacement if any.
268 For example, 'go list -m all' might print:
269
270 my/main/module
271 golang.org/x/text v0.3.0 => /tmp/text
272 rsc.io/pdf v0.1.1
273
274 The Module struct has a String method that formats this
275 line of output, so that the default format is equivalent
276 to -f '{{.String}}'.
277
278 Note that when a module has been replaced, its Replace field
279 describes the replacement module, and its Dir field is set to
280 the replacement's source code, if present. (That is, if Replace
281 is non-nil, then Dir is set to Replace.Dir, with no access to
282 the replaced source code.)
283
284 The -u flag adds information about available upgrades.
285 When the latest version of a given module is newer than
286 the current one, list -u sets the Module's Update field
287 to information about the newer module. list -u will also set
288 the module's Retracted field if the current version is retracted.
289 The Module's String method indicates an available upgrade by
290 formatting the newer version in brackets after the current version.
291 If a version is retracted, the string "(retracted)" will follow it.
292 For example, 'go list -m -u all' might print:
293
294 my/main/module
295 golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
296 rsc.io/pdf v0.1.1 (retracted) [v0.1.2]
297
298 (For tools, 'go list -m -u -json all' may be more convenient to parse.)
299
300 The -versions flag causes list to set the Module's Versions field
301 to a list of all known versions of that module, ordered according
302 to semantic versioning, earliest to latest. The flag also changes
303 the default output format to display the module path followed by the
304 space-separated version list.
305
306 The -retracted flag causes list to report information about retracted
307 module versions. When -retracted is used with -f or -json, the Retracted
308 field explains why the version was retracted.
309 The strings are taken from comments on the retract directive in the
310 module's go.mod file. When -retracted is used with -versions, retracted
311 versions are listed together with unretracted versions. The -retracted
312 flag may be used with or without -m.
313
314 The arguments to list -m are interpreted as a list of modules, not packages.
315 The main module is the module containing the current directory.
316 The active modules are the main module and its dependencies.
317 With no arguments, list -m shows the main module.
318 With arguments, list -m shows the modules specified by the arguments.
319 Any of the active modules can be specified by its module path.
320 The special pattern "all" specifies all the active modules, first the main
321 module and then dependencies sorted by module path.
322 A pattern containing "..." specifies the active modules whose
323 module paths match the pattern.
324 A query of the form path@version specifies the result of that query,
325 which is not limited to active modules.
326 See 'go help modules' for more about module queries.
327
328 The template function "module" takes a single string argument
329 that must be a module path or query and returns the specified
330 module as a Module struct. If an error occurs, the result will
331 be a Module struct with a non-nil Error field.
332
333 When using -m, the -reuse=old.json flag accepts the name of file containing
334 the JSON output of a previous 'go list -m -json' invocation with the
335 same set of modifier flags (such as -u, -retracted, and -versions).
336 The go command may use this file to determine that a module is unchanged
337 since the previous invocation and avoid redownloading information about it.
338 Modules that are not redownloaded will be marked in the new output by
339 setting the Reuse field to true. Normally the module cache provides this
340 kind of reuse automatically; the -reuse flag can be useful on systems that
341 do not preserve the module cache.
342
343 For more about build flags, see 'go help build'.
344
345 For more about specifying packages, see 'go help packages'.
346
347 For more about modules, see https://go.dev/ref/mod.
348 `,
349 }
350
351 func init() {
352 CmdList.Run = runList
353
354 work.AddBuildFlags(CmdList, work.OmitJSONFlag)
355 work.AddCoverFlags(CmdList, nil)
356 CmdList.Flag.Var(&listJsonFields, "json", "print the package data in JSON format; optionally specify a comma-separated list of field names to include")
357 }
358
359 var (
360 listCompiled = CmdList.Flag.Bool("compiled", false, "set CompiledGoFiles to the Go source files presented to the compiler")
361 listDeps = CmdList.Flag.Bool("deps", false, "iterate through all dependencies, not just those explicitly listed")
362 listE = CmdList.Flag.Bool("e", false, "change the handling of erroneous packages")
363 listExport = CmdList.Flag.Bool("export", false, "set Export to the file name of the up-to-date export data for the package")
364 listFmt = CmdList.Flag.String("f", "", "specify an alternate `format` for the list, using the syntax of package template")
365 listFind = CmdList.Flag.Bool("find", false, "do not resolve dependencies; print only the matching packages")
366 listJson bool
367 listJsonFields jsonFlag
368 listM = CmdList.Flag.Bool("m", false, "list modules instead of packages")
369 listRetracted = CmdList.Flag.Bool("retracted", false, "show retracted modules")
370 listReuse = CmdList.Flag.String("reuse", "", "reuse output from a previous list run stored in the named `file`")
371 listTest = CmdList.Flag.Bool("test", false, "show not only the named packages but also their test binaries")
372 listU = CmdList.Flag.Bool("u", false, "add information about available upgrades")
373 listVersions = CmdList.Flag.Bool("versions", false, "show the list of all known versions for a module")
374 )
375
376
377
378 type jsonFlag map[string]bool
379
380 func (v *jsonFlag) Set(s string) error {
381 if v, err := strconv.ParseBool(s); err == nil {
382 listJson = v
383 return nil
384 }
385 listJson = true
386 if *v == nil {
387 *v = make(map[string]bool)
388 }
389 for f := range strings.SplitSeq(s, ",") {
390 (*v)[f] = true
391 }
392 return nil
393 }
394
395 func (v *jsonFlag) String() string {
396 fields := make([]string, 0, len(*v))
397 for f := range *v {
398 fields = append(fields, f)
399 }
400 sort.Strings(fields)
401 return strings.Join(fields, ",")
402 }
403
404 func (v *jsonFlag) IsBoolFlag() bool {
405 return true
406 }
407
408 func (v *jsonFlag) needAll() bool {
409 return len(*v) == 0
410 }
411
412 func (v *jsonFlag) needAny(fields ...string) bool {
413 if v.needAll() {
414 return true
415 }
416 for _, f := range fields {
417 if (*v)[f] {
418 return true
419 }
420 }
421 return false
422 }
423
424 var nl = []byte{'\n'}
425
426 func runList(ctx context.Context, cmd *base.Command, args []string) {
427 for _, arg := range args {
428 if arg == "" {
429 base.Fatalf("go: invalid package: %q", arg)
430 }
431 }
432
433 moduleLoader := modload.NewLoader()
434 moduleLoader.InitWorkfile()
435
436 if *listFmt != "" && listJson {
437 base.Fatalf("go list -f cannot be used with -json")
438 }
439 if *listReuse != "" && !*listM {
440 base.Fatalf("go list -reuse cannot be used without -m")
441 }
442 if *listReuse != "" && moduleLoader.HasModRoot() {
443 base.Fatalf("go list -reuse cannot be used inside a module")
444 }
445
446 work.BuildInit(moduleLoader)
447 out := newTrackingWriter(os.Stdout)
448 defer out.w.Flush()
449
450 if *listFmt == "" {
451 if *listM {
452 *listFmt = "{{.String}}"
453 if *listVersions {
454 *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}{{if .Deprecated}} (deprecated){{end}}`
455 }
456 } else {
457 *listFmt = "{{.ImportPath}}"
458 }
459 }
460
461 var do func(x any)
462 if listJson {
463 do = func(x any) {
464 if !listJsonFields.needAll() {
465
466 v := reflect.New(reflect.TypeOf(x).Elem()).Elem()
467 v.Set(reflect.ValueOf(x).Elem())
468 for i := 0; i < v.NumField(); i++ {
469 if !listJsonFields.needAny(v.Type().Field(i).Name) {
470 v.Field(i).SetZero()
471 }
472 }
473 x = v.Interface()
474 }
475 b, err := json.MarshalIndent(x, "", "\t")
476 if err != nil {
477 out.Flush()
478 base.Fatalf("%s", err)
479 }
480 out.Write(b)
481 out.Write(nl)
482 }
483 } else {
484 var cachedCtxt *Context
485 context := func() *Context {
486 if cachedCtxt == nil {
487 cachedCtxt = newContext(&cfg.BuildContext)
488 }
489 return cachedCtxt
490 }
491 fm := template.FuncMap{
492 "join": strings.Join,
493 "json": func(v any) (string, error) {
494 b, err := json.Marshal(v)
495 return string(b), err
496 },
497 "context": context,
498 "module": func(path string) *modinfo.ModulePublic { return modload.ModuleInfo(moduleLoader, ctx, path) },
499 }
500 tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
501 if err != nil {
502 base.Fatalf("%s", err)
503 }
504 do = func(x any) {
505 if err := tmpl.Execute(out, x); err != nil {
506 out.Flush()
507 base.Fatalf("%s", err)
508 }
509 if out.NeedNL() {
510 out.Write(nl)
511 }
512 }
513 }
514
515 modload.Init(moduleLoader)
516 if *listRetracted {
517 if cfg.BuildMod == "vendor" {
518 base.Fatalf("go list -retracted cannot be used when vendoring is enabled")
519 }
520 if !moduleLoader.Enabled() {
521 base.Fatalf("go list -retracted can only be used in module-aware mode")
522 }
523 }
524
525 if *listM {
526
527 if *listCompiled {
528 base.Fatalf("go list -compiled cannot be used with -m")
529 }
530 if *listDeps {
531
532 base.Fatalf("go list -deps cannot be used with -m")
533 }
534 if *listExport {
535 base.Fatalf("go list -export cannot be used with -m")
536 }
537 if *listFind {
538 base.Fatalf("go list -find cannot be used with -m")
539 }
540 if *listTest {
541 base.Fatalf("go list -test cannot be used with -m")
542 }
543
544 if modload.Init(moduleLoader); !moduleLoader.Enabled() {
545 base.Fatalf("go: list -m cannot be used with GO111MODULE=off")
546 }
547
548 modload.LoadModFile(moduleLoader, ctx)
549 if cfg.BuildMod == "vendor" {
550 const actionDisabledFormat = "go: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
551
552 if *listVersions {
553 base.Fatalf(actionDisabledFormat, "determine available versions")
554 }
555 if *listU {
556 base.Fatalf(actionDisabledFormat, "determine available upgrades")
557 }
558
559 for _, arg := range args {
560
561
562
563 if arg == "all" {
564 base.Fatalf(actionDisabledFormat, "compute 'all'")
565 }
566 if strings.Contains(arg, "...") {
567 base.Fatalf(actionDisabledFormat, "match module patterns")
568 }
569 }
570 }
571
572 var mode modload.ListMode
573 if *listU {
574 mode |= modload.ListU | modload.ListRetracted | modload.ListDeprecated
575 }
576 if *listRetracted {
577 mode |= modload.ListRetracted
578 }
579 if *listVersions {
580 mode |= modload.ListVersions
581 if *listRetracted {
582 mode |= modload.ListRetractedVersions
583 }
584 }
585 if *listReuse != "" && len(args) == 0 {
586 base.Fatalf("go: list -m -reuse only has an effect with module@version arguments")
587 }
588 mods, err := modload.ListModules(moduleLoader, ctx, args, mode, *listReuse)
589 if !*listE {
590 for _, m := range mods {
591 if m.Error != nil {
592 base.Error(errors.New(m.Error.Err))
593 }
594 }
595 if err != nil {
596 base.Error(err)
597 }
598 base.ExitIfErrors()
599 }
600 for _, m := range mods {
601 do(m)
602 }
603 return
604 }
605
606
607 if *listU {
608 base.Fatalf("go list -u can only be used with -m")
609 }
610 if *listVersions {
611 base.Fatalf("go list -versions can only be used with -m")
612 }
613
614
615 if *listFind && *listDeps {
616 base.Fatalf("go list -deps cannot be used with -find")
617 }
618 if *listFind && *listTest {
619 base.Fatalf("go list -test cannot be used with -find")
620 }
621 if *listFind && *listExport {
622 base.Fatalf("go list -export cannot be used with -find")
623 }
624
625 pkgOpts := load.PackageOpts{
626 IgnoreImports: *listFind,
627 ModResolveTests: *listTest,
628 AutoVCS: true,
629 SuppressBuildInfo: !*listExport && !listJsonFields.needAny("Stale", "StaleReason"),
630 SuppressEmbedFiles: !*listExport && !listJsonFields.needAny("EmbedFiles", "TestEmbedFiles", "XTestEmbedFiles"),
631 }
632 pkgs := load.PackagesAndErrors(moduleLoader, ctx, pkgOpts, args)
633 if !*listE {
634 w := 0
635 for _, pkg := range pkgs {
636 if pkg.Error != nil {
637 base.Errorf("%v", pkg.Error)
638 continue
639 }
640 pkgs[w] = pkg
641 w++
642 }
643 pkgs = pkgs[:w]
644 base.ExitIfErrors()
645 }
646
647 if *listTest {
648 c := cache.Default()
649
650
651 var wg sync.WaitGroup
652 sema := semaphore.NewWeighted(int64(runtime.GOMAXPROCS(0)))
653 type testPackageSet struct {
654 p, pmain, ptest, pxtest *load.Package
655 }
656 var testPackages []testPackageSet
657 for _, p := range pkgs {
658 if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
659 var pmain, ptest, pxtest *load.Package
660 if *listE {
661 sema.Acquire(ctx, 1)
662 wg.Add(1)
663 done := func() {
664 sema.Release(1)
665 wg.Done()
666 }
667 pmain, ptest, pxtest = load.TestPackagesAndErrors(moduleLoader, ctx, done, pkgOpts, p, nil)
668 } else {
669 var perr *load.Package
670 pmain, ptest, pxtest, perr = load.TestPackagesFor(moduleLoader, ctx, pkgOpts, p, nil)
671 if perr != nil {
672 base.Fatalf("go: can't load test package: %s", perr.Error)
673 }
674 }
675 testPackages = append(testPackages, testPackageSet{p, pmain, ptest, pxtest})
676 }
677 }
678 wg.Wait()
679 for _, pkgset := range testPackages {
680 p, pmain, ptest, pxtest := pkgset.p, pkgset.pmain, pkgset.ptest, pkgset.pxtest
681 if pmain != nil {
682 pkgs = append(pkgs, pmain)
683 data := *pmain.Internal.TestmainGo
684 sema.Acquire(ctx, 1)
685 wg.Add(1)
686 go func() {
687 h := cache.NewHash("testmain")
688 h.Write([]byte("testmain\n"))
689 h.Write(data)
690 out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
691 if err != nil {
692 base.Fatalf("%s", err)
693 }
694 pmain.GoFiles[0] = c.OutputFile(out)
695 sema.Release(1)
696 wg.Done()
697 }()
698
699 }
700 if ptest != nil && ptest != p {
701 pkgs = append(pkgs, ptest)
702 }
703 if pxtest != nil {
704 pkgs = append(pkgs, pxtest)
705 }
706 }
707
708 wg.Wait()
709 }
710
711
712 cmdline := make(map[*load.Package]bool)
713 for _, p := range pkgs {
714 cmdline[p] = true
715 }
716
717 if *listDeps {
718
719
720
721
722
723
724
725
726 pkgs = loadPackageList(pkgs)
727 }
728
729
730 needStale := (listJson && listJsonFields.needAny("Stale", "StaleReason")) || strings.Contains(*listFmt, ".Stale")
731 var buildPkgs []*load.Package
732 if needStale || *listExport || (*listCompiled && cfg.BuildCover) {
733 buildPkgs = pkgs
734 } else if *listCompiled {
735
736
737 for _, p := range pkgs {
738 if p.UsesCgo() || p.UsesSwig() {
739
740 buildPkgs = append(buildPkgs, p)
741 continue
742 }
743 p.CompiledGoFiles = str.StringList(p.GoFiles)
744 }
745 }
746 if len(buildPkgs) > 0 {
747 b := work.NewBuilder("", moduleLoader.VendorDirOrEmpty)
748 if *listE {
749 b.AllowErrors = true
750 }
751 defer func() {
752 if err := b.Close(); err != nil {
753 base.Fatal(err)
754 }
755 }()
756
757 b.IsCmdList = true
758 b.NeedExport = *listExport
759 b.NeedCompiledGoFiles = *listCompiled
760 if cfg.BuildCover {
761 load.PrepareForCoverageBuild(moduleLoader, pkgs)
762 }
763 a := &work.Action{}
764
765 for _, p := range buildPkgs {
766 if len(p.GoFiles)+len(p.CgoFiles) > 0 {
767 a.Deps = append(a.Deps, b.AutoAction(moduleLoader, work.ModeInstall, work.ModeInstall, p))
768 }
769 }
770 b.Do(ctx, a)
771 }
772
773 for _, p := range pkgs {
774
775 p.TestImports = p.Resolve(moduleLoader, p.TestImports)
776 p.XTestImports = p.Resolve(moduleLoader, p.XTestImports)
777 p.DepOnly = !cmdline[p]
778
779 if *listCompiled {
780 p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports)
781 }
782 }
783
784 if *listTest || (cfg.BuildPGO == "auto" && len(cmdline) > 1) {
785 all := pkgs
786 if !*listDeps {
787 all = loadPackageList(pkgs)
788 }
789
790
791
792
793
794
795 old := make(map[string]string)
796 for _, p := range all {
797 if p.ForTest != "" || p.Internal.ForMain != "" {
798 new := p.Desc()
799 old[new] = p.ImportPath
800 p.ImportPath = new
801 }
802 p.DepOnly = !cmdline[p]
803 }
804
805 m := make(map[string]string)
806 for _, p := range all {
807 for _, p1 := range p.Internal.Imports {
808 if p1.ForTest != "" || p1.Internal.ForMain != "" {
809 m[old[p1.ImportPath]] = p1.ImportPath
810 }
811 }
812 for i, old := range p.Imports {
813 if new := m[old]; new != "" {
814 p.Imports[i] = new
815 }
816 }
817 clear(m)
818 }
819 }
820
821 if listJsonFields.needAny("Deps", "DepsErrors") {
822 all := pkgs
823
824
825
826
827
828
829
830
831 if !*listDeps {
832 all = load.PackageList(pkgs)
833 }
834 if listJsonFields.needAny("Deps") {
835 for _, p := range all {
836 collectDeps(p)
837 }
838 }
839 if listJsonFields.needAny("DepsErrors") {
840 for _, p := range all {
841 collectDepsErrors(p)
842 }
843 }
844 }
845
846
847
848 if *listRetracted {
849
850
851
852
853
854
855 modToArg := make(map[*modinfo.ModulePublic]string)
856 argToMods := make(map[string][]*modinfo.ModulePublic)
857 var args []string
858 addModule := func(mod *modinfo.ModulePublic) {
859 if mod.Version == "" {
860 return
861 }
862 arg := fmt.Sprintf("%s@%s", mod.Path, mod.Version)
863 if argToMods[arg] == nil {
864 args = append(args, arg)
865 }
866 argToMods[arg] = append(argToMods[arg], mod)
867 modToArg[mod] = arg
868 }
869 for _, p := range pkgs {
870 if p.Module == nil {
871 continue
872 }
873 addModule(p.Module)
874 if p.Module.Replace != nil {
875 addModule(p.Module.Replace)
876 }
877 }
878
879 if len(args) > 0 {
880 var mode modload.ListMode
881 if *listRetracted {
882 mode |= modload.ListRetracted
883 }
884 rmods, err := modload.ListModules(moduleLoader, ctx, args, mode, *listReuse)
885 if err != nil && !*listE {
886 base.Error(err)
887 }
888 for i, arg := range args {
889 rmod := rmods[i]
890 for _, mod := range argToMods[arg] {
891 mod.Retracted = rmod.Retracted
892 if rmod.Error != nil && mod.Error == nil {
893 mod.Error = rmod.Error
894 }
895 }
896 }
897 }
898 }
899
900
901 for _, p := range pkgs {
902 nRaw := len(p.Internal.RawImports)
903 for i, path := range p.Imports {
904 var srcPath string
905 if i < nRaw {
906 srcPath = p.Internal.RawImports[i]
907 } else {
908
909
910
911 srcPath = p.Internal.CompiledImports[i-nRaw]
912 }
913
914 if path != srcPath {
915 if p.ImportMap == nil {
916 p.ImportMap = make(map[string]string)
917 }
918 p.ImportMap[srcPath] = path
919 }
920 }
921 }
922
923 for _, p := range pkgs {
924 do(&p.PackagePublic)
925 }
926 }
927
928
929
930
931 func loadPackageList(roots []*load.Package) []*load.Package {
932 pkgs := load.PackageList(roots)
933
934 if !*listE {
935 for _, pkg := range pkgs {
936 if pkg.Error != nil {
937 base.Errorf("%v", pkg.Error)
938 }
939 }
940 }
941
942 return pkgs
943 }
944
945
946
947 func collectDeps(p *load.Package) {
948 deps := make(map[string]bool)
949
950 for _, p := range p.Internal.Imports {
951 deps[p.ImportPath] = true
952 for _, q := range p.Deps {
953 deps[q] = true
954 }
955 }
956
957 p.Deps = make([]string, 0, len(deps))
958 for dep := range deps {
959 p.Deps = append(p.Deps, dep)
960 }
961 sort.Strings(p.Deps)
962 }
963
964
965
966 func collectDepsErrors(p *load.Package) {
967 depsErrors := make(map[*load.PackageError]bool)
968
969 for _, p := range p.Internal.Imports {
970 if p.Error != nil {
971 depsErrors[p.Error] = true
972 }
973 for _, q := range p.DepsErrors {
974 depsErrors[q] = true
975 }
976 }
977
978 p.DepsErrors = make([]*load.PackageError, 0, len(depsErrors))
979 for deperr := range depsErrors {
980 p.DepsErrors = append(p.DepsErrors, deperr)
981 }
982
983
984
985 sort.Slice(p.DepsErrors, func(i, j int) bool {
986 stki, stkj := p.DepsErrors[i].ImportStack, p.DepsErrors[j].ImportStack
987
988
989
990 if len(stki) == 0 {
991 if len(stkj) != 0 {
992 return true
993 }
994
995 return p.DepsErrors[i].Err.Error() < p.DepsErrors[j].Err.Error()
996 } else if len(stkj) == 0 {
997 return false
998 }
999 pathi, pathj := stki[len(stki)-1], stkj[len(stkj)-1]
1000 return pathi.Pkg < pathj.Pkg
1001 })
1002 }
1003
1004
1005
1006
1007 type TrackingWriter struct {
1008 w *bufio.Writer
1009 last byte
1010 }
1011
1012 func newTrackingWriter(w io.Writer) *TrackingWriter {
1013 return &TrackingWriter{
1014 w: bufio.NewWriter(w),
1015 last: '\n',
1016 }
1017 }
1018
1019 func (t *TrackingWriter) Write(p []byte) (n int, err error) {
1020 n, err = t.w.Write(p)
1021 if n > 0 {
1022 t.last = p[n-1]
1023 }
1024 return
1025 }
1026
1027 func (t *TrackingWriter) Flush() {
1028 t.w.Flush()
1029 }
1030
1031 func (t *TrackingWriter) NeedNL() bool {
1032 return t.last != '\n'
1033 }
1034
View as plain text