github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/internal/list/list.go (about)

     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.
     6  package list
     7  
     8  import (
     9  	"bufio"
    10  	"bytes"
    11  	"encoding/json"
    12  	"io"
    13  	"os"
    14  	"sort"
    15  	"strings"
    16  	"text/template"
    17  
    18  	"cmd/go/internal/base"
    19  	"cmd/go/internal/cache"
    20  	"cmd/go/internal/cfg"
    21  	"cmd/go/internal/load"
    22  	"cmd/go/internal/modload"
    23  	"cmd/go/internal/str"
    24  	"cmd/go/internal/work"
    25  )
    26  
    27  var CmdList = &base.Command{
    28  	// 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: `
    33  List lists the named packages, one per line.
    34  The most commonly-used flags are -f and -json, which control the form
    35  of the output printed for each package. Other list flags, documented below,
    36  control more specific details.
    37  
    38  The default output shows the package import path:
    39  
    40      bytes
    41      encoding/json
    42      github.com/gorilla/mux
    43      golang.org/x/net/html
    44  
    45  The -f flag specifies an alternate format for the list, using the
    46  syntax of package template. The default output is equivalent
    47  to -f '{{.ImportPath}}'. The struct being passed to the template is:
    48  
    49      type Package struct {
    50          Dir           string   // directory containing package sources
    51          ImportPath    string   // import path of package in dir
    52          ImportComment string   // path in import comment on package statement
    53          Name          string   // package name
    54          Doc           string   // package documentation string
    55          Target        string   // install path
    56          Shlib         string   // the shared library that contains this package (only set when -linkshared)
    57          Goroot        bool     // is this package in the Go root?
    58          Standard      bool     // is this package part of the standard Go library?
    59          Stale         bool     // would 'go install' do anything for this package?
    60          StaleReason   string   // explanation for Stale==true
    61          Root          string   // Go root or Go path dir containing this package
    62          ConflictDir   string   // this directory shadows Dir in $GOPATH
    63          BinaryOnly    bool     // binary-only package: 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  
   108  Packages stored in vendor directories report an ImportPath that includes the
   109  path to the vendor directory (for example, "d/vendor/p" instead of "p"),
   110  so that the ImportPath uniquely identifies a given copy of a package.
   111  The Imports, Deps, TestImports, and XTestImports lists also contain these
   112  expanded import paths. See golang.org/s/go15vendor for more about vendoring.
   113  
   114  The error information, if any, is
   115  
   116      type PackageError struct {
   117          ImportStack   []string // shortest path from package named on command line to this one
   118          Pos           string   // position of error (if present, file:line:col)
   119          Err           string   // the error itself
   120      }
   121  
   122  The module information is a Module struct, defined in the discussion
   123  of list -m below.
   124  
   125  The template function "join" calls strings.Join.
   126  
   127  The template function "context" returns the build context, defined as:
   128  
   129      type Context struct {
   130          GOARCH        string   // target architecture
   131          GOOS          string   // target operating system
   132          GOROOT        string   // Go root
   133          GOPATH        string   // Go path
   134          CgoEnabled    bool     // whether cgo can be used
   135          UseAllFiles   bool     // use files regardless of +build lines, file names
   136          Compiler      string   // compiler to assume when computing target paths
   137          BuildTags     []string // build constraints to match in +build lines
   138          ReleaseTags   []string // releases the current release is compatible with
   139          InstallSuffix string   // suffix to use in the name of the install dir
   140      }
   141  
   142  For more information about the meaning of these fields see the documentation
   143  for the go/build package's Context type.
   144  
   145  The -json flag causes the package data to be printed in JSON format
   146  instead of using the template format.
   147  
   148  The -compiled flag causes list to set CompiledGoFiles to the Go source
   149  files presented to the compiler. Typically this means that it repeats
   150  the files listed in GoFiles and then also adds the Go code generated
   151  by processing CgoFiles and SwigFiles. The Imports list contains the
   152  union of all imports from both GoFiles and CompiledGoFiles.
   153  
   154  The -deps flag causes list to iterate over not just the named packages
   155  but also all their dependencies. It visits them in a depth-first post-order
   156  traversal, so that a package is listed only after all its dependencies.
   157  Packages not explicitly listed on the command line will have the DepOnly
   158  field set to true.
   159  
   160  The -e flag changes the handling of erroneous packages, those that
   161  cannot be found or are malformed. By default, the list command
   162  prints an error to standard error for each erroneous package and
   163  omits the packages from consideration during the usual printing.
   164  With the -e flag, the list command never prints errors to standard
   165  error and instead processes the erroneous packages with the usual
   166  printing. Erroneous packages will have a non-empty ImportPath and
   167  a non-nil Error field; other information may or may not be missing
   168  (zeroed).
   169  
   170  The -export flag causes list to set the Export field to the name of a
   171  file containing up-to-date export information for the given package.
   172  
   173  The -find flag causes list to identify the named packages but not
   174  resolve their dependencies: the Imports and Deps lists will be empty.
   175  
   176  The -test flag causes list to report not only the named packages
   177  but also their test binaries (for packages with tests), to convey to
   178  source code analysis tools exactly how test binaries are constructed.
   179  The reported import path for a test binary is the import path of
   180  the package followed by a ".test" suffix, as in "math/rand.test".
   181  When building a test, it is sometimes necessary to rebuild certain
   182  dependencies specially for that test (most commonly the tested
   183  package itself). The reported import path of a package recompiled
   184  for a particular test binary is followed by a space and the name of
   185  the test binary in brackets, as in "math/rand [math/rand.test]"
   186  or "regexp [sort.test]". The ForTest field is also set to the name
   187  of the package being tested ("math/rand" or "sort" in the previous
   188  examples).
   189  
   190  The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
   191  are all absolute paths.
   192  
   193  By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
   194  (that is, paths relative to Dir, not absolute paths).
   195  The generated files added when using the -compiled and -test flags
   196  are absolute paths referring to cached copies of generated Go source files.
   197  Although they are Go source files, the paths may not end in ".go".
   198  
   199  The -m flag causes list to list modules instead of packages.
   200  
   201  When listing modules, the -f flag still specifies a format template
   202  applied to a Go struct, but now a Module struct:
   203  
   204      type Module struct {
   205          Path     string       // module path
   206          Version  string       // module version
   207          Versions []string     // available module versions (with -versions)
   208          Replace  *Module      // replaced by this module
   209          Time     *time.Time   // time version was created
   210          Update   *Module      // available update, if any (with -u)
   211          Main     bool         // is this the main module?
   212          Indirect bool         // is this module only an indirect dependency of main module?
   213          Dir      string       // directory holding files for this module, if any
   214          GoMod    string       // path to go.mod file for this module, if any
   215          Error    *ModuleError // error loading module
   216      }
   217  
   218      type ModuleError struct {
   219          Err string // the error itself
   220      }
   221  
   222  The default output is to print the module path and then
   223  information about the version and replacement if any.
   224  For 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  
   230  The Module struct has a String method that formats this
   231  line of output, so that the default format is equivalent
   232  to -f '{{.String}}'.
   233  
   234  Note that when a module has been replaced, its Replace field
   235  describes the replacement module, and its Dir field is set to
   236  the replacement's source code, if present. (That is, if Replace
   237  is non-nil, then Dir is set to Replace.Dir, with no access to
   238  the replaced source code.)
   239  
   240  The -u flag adds information about available upgrades.
   241  When the latest version of a given module is newer than
   242  the current one, list -u sets the Module's Update field
   243  to information about the newer module.
   244  The Module's String method indicates an available upgrade by
   245  formatting the newer version in brackets after the current version.
   246  For 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  
   254  The -versions flag causes list to set the Module's Versions field
   255  to a list of all known versions of that module, ordered according
   256  to semantic versioning, earliest to latest. The flag also changes
   257  the default output format to display the module path followed by the
   258  space-separated version list.
   259  
   260  The arguments to list -m are interpreted as a list of modules, not packages.
   261  The main module is the module containing the current directory.
   262  The active modules are the main module and its dependencies.
   263  With no arguments, list -m shows the main module.
   264  With arguments, list -m shows the modules specified by the arguments.
   265  Any of the active modules can be specified by its module path.
   266  The special pattern "all" specifies all the active modules, first the main
   267  module and then dependencies sorted by module path.
   268  A pattern containing "..." specifies the active modules whose
   269  module paths match the pattern.
   270  A query of the form path@version specifies the result of that query,
   271  which is not limited to active modules.
   272  See 'go help modules' for more about module queries.
   273  
   274  The template function "module" takes a single string argument
   275  that must be a module path or query and returns the specified
   276  module as a Module struct. If an error occurs, the result will
   277  be a Module struct with a non-nil Error field.
   278  
   279  For more about build flags, see 'go help build'.
   280  
   281  For more about specifying packages, see 'go help packages'.
   282  
   283  For more about modules, see 'go help modules'.
   284  	`,
   285  }
   286  
   287  func init() {
   288  	CmdList.Run = runList // break init cycle
   289  	work.AddBuildFlags(CmdList)
   290  }
   291  
   292  var (
   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  
   306  var nl = []byte{'\n'}
   307  
   308  func 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.TestPackagesFor(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.
   605  type TrackingWriter struct {
   606  	w    *bufio.Writer
   607  	last byte
   608  }
   609  
   610  func newTrackingWriter(w io.Writer) *TrackingWriter {
   611  	return &TrackingWriter{
   612  		w:    bufio.NewWriter(w),
   613  		last: '\n',
   614  	}
   615  }
   616  
   617  func (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  
   625  func (t *TrackingWriter) Flush() {
   626  	t.w.Flush()
   627  }
   628  
   629  func (t *TrackingWriter) NeedNL() bool {
   630  	return t.last != '\n'
   631  }