github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/src/cmd/go/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 main
     6  
     7  import (
     8  	"bufio"
     9  	"encoding/json"
    10  	"io"
    11  	"os"
    12  	"strings"
    13  	"text/template"
    14  )
    15  
    16  var cmdList = &Command{
    17  	UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]",
    18  	Short:     "list packages",
    19  	Long: `
    20  List lists the packages named by the import paths, one per line.
    21  
    22  The default output shows the package import path:
    23  
    24      code.google.com/p/google-api-go-client/books/v1
    25      code.google.com/p/goauth2/oauth
    26      code.google.com/p/sqlite
    27  
    28  The -f flag specifies an alternate format for the list, using the
    29  syntax of package template.  The default output is equivalent to -f
    30  '{{.ImportPath}}'. The struct being passed to the template is:
    31  
    32      type Package struct {
    33          Dir           string // directory containing package sources
    34          ImportPath    string // import path of package in dir
    35          ImportComment string // path in import comment on package statement
    36          Name          string // package name
    37          Doc           string // package documentation string
    38          Target        string // install path
    39          Shlib         string // the shared library that contains this package (only set when -linkshared)
    40          Goroot        bool   // is this package in the Go root?
    41          Standard      bool   // is this package part of the standard Go library?
    42          Stale         bool   // would 'go install' do anything for this package?
    43          Root          string // Go root or Go path dir containing this package
    44  
    45          // Source files
    46          GoFiles        []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
    47          CgoFiles       []string // .go sources files that import "C"
    48          IgnoredGoFiles []string // .go sources ignored due to build constraints
    49          CFiles         []string // .c source files
    50          CXXFiles       []string // .cc, .cxx and .cpp source files
    51          MFiles         []string // .m source files
    52          HFiles         []string // .h, .hh, .hpp and .hxx source files
    53          SFiles         []string // .s source files
    54          SwigFiles      []string // .swig files
    55          SwigCXXFiles   []string // .swigcxx files
    56          SysoFiles      []string // .syso object files to add to archive
    57  
    58          // Cgo directives
    59          CgoCFLAGS    []string // cgo: flags for C compiler
    60          CgoCPPFLAGS  []string // cgo: flags for C preprocessor
    61          CgoCXXFLAGS  []string // cgo: flags for C++ compiler
    62          CgoLDFLAGS   []string // cgo: flags for linker
    63          CgoPkgConfig []string // cgo: pkg-config names
    64  
    65          // Dependency information
    66          Imports []string // import paths used by this package
    67          Deps    []string // all (recursively) imported dependencies
    68  
    69          // Error information
    70          Incomplete bool            // this package or a dependency has an error
    71          Error      *PackageError   // error loading package
    72          DepsErrors []*PackageError // errors loading dependencies
    73  
    74          TestGoFiles  []string // _test.go files in package
    75          TestImports  []string // imports from TestGoFiles
    76          XTestGoFiles []string // _test.go files outside package
    77          XTestImports []string // imports from XTestGoFiles
    78      }
    79  
    80  The template function "join" calls strings.Join.
    81  
    82  The template function "context" returns the build context, defined as:
    83  
    84  	type Context struct {
    85  		GOARCH        string   // target architecture
    86  		GOOS          string   // target operating system
    87  		GOROOT        string   // Go root
    88  		GOPATH        string   // Go path
    89  		CgoEnabled    bool     // whether cgo can be used
    90  		UseAllFiles   bool     // use files regardless of +build lines, file names
    91  		Compiler      string   // compiler to assume when computing target paths
    92  		BuildTags     []string // build constraints to match in +build lines
    93  		ReleaseTags   []string // releases the current release is compatible with
    94  		InstallSuffix string   // suffix to use in the name of the install dir
    95  	}
    96  
    97  For more information about the meaning of these fields see the documentation
    98  for the go/build package's Context type.
    99  
   100  The -json flag causes the package data to be printed in JSON format
   101  instead of using the template format.
   102  
   103  The -e flag changes the handling of erroneous packages, those that
   104  cannot be found or are malformed.  By default, the list command
   105  prints an error to standard error for each erroneous package and
   106  omits the packages from consideration during the usual printing.
   107  With the -e flag, the list command never prints errors to standard
   108  error and instead processes the erroneous packages with the usual
   109  printing.  Erroneous packages will have a non-empty ImportPath and
   110  a non-nil Error field; other information may or may not be missing
   111  (zeroed).
   112  
   113  For more about build flags, see 'go help build'.
   114  
   115  For more about specifying packages, see 'go help packages'.
   116  	`,
   117  }
   118  
   119  func init() {
   120  	cmdList.Run = runList // break init cycle
   121  	addBuildFlags(cmdList)
   122  }
   123  
   124  var listE = cmdList.Flag.Bool("e", false, "")
   125  var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
   126  var listJson = cmdList.Flag.Bool("json", false, "")
   127  var nl = []byte{'\n'}
   128  
   129  func runList(cmd *Command, args []string) {
   130  	buildModeInit()
   131  	out := newTrackingWriter(os.Stdout)
   132  	defer out.w.Flush()
   133  
   134  	var do func(*Package)
   135  	if *listJson {
   136  		do = func(p *Package) {
   137  			b, err := json.MarshalIndent(p, "", "\t")
   138  			if err != nil {
   139  				out.Flush()
   140  				fatalf("%s", err)
   141  			}
   142  			out.Write(b)
   143  			out.Write(nl)
   144  		}
   145  	} else {
   146  		var cachedCtxt *Context
   147  		context := func() *Context {
   148  			if cachedCtxt == nil {
   149  				cachedCtxt = newContext(&buildContext)
   150  			}
   151  			return cachedCtxt
   152  		}
   153  		fm := template.FuncMap{
   154  			"join":    strings.Join,
   155  			"context": context,
   156  		}
   157  		tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
   158  		if err != nil {
   159  			fatalf("%s", err)
   160  		}
   161  		do = func(p *Package) {
   162  			if err := tmpl.Execute(out, p); err != nil {
   163  				out.Flush()
   164  				fatalf("%s", err)
   165  			}
   166  			if out.NeedNL() {
   167  				out.Write(nl)
   168  			}
   169  		}
   170  	}
   171  
   172  	load := packages
   173  	if *listE {
   174  		load = packagesAndErrors
   175  	}
   176  
   177  	for _, pkg := range load(args) {
   178  		// Show vendor-expanded paths in listing
   179  		pkg.TestImports = pkg.vendored(pkg.TestImports)
   180  		pkg.XTestImports = pkg.vendored(pkg.XTestImports)
   181  
   182  		do(pkg)
   183  	}
   184  }
   185  
   186  // TrackingWriter tracks the last byte written on every write so
   187  // we can avoid printing a newline if one was already written or
   188  // if there is no output at all.
   189  type TrackingWriter struct {
   190  	w    *bufio.Writer
   191  	last byte
   192  }
   193  
   194  func newTrackingWriter(w io.Writer) *TrackingWriter {
   195  	return &TrackingWriter{
   196  		w:    bufio.NewWriter(w),
   197  		last: '\n',
   198  	}
   199  }
   200  
   201  func (t *TrackingWriter) Write(p []byte) (n int, err error) {
   202  	n, err = t.w.Write(p)
   203  	if n > 0 {
   204  		t.last = p[n-1]
   205  	}
   206  	return
   207  }
   208  
   209  func (t *TrackingWriter) Flush() {
   210  	t.w.Flush()
   211  }
   212  
   213  func (t *TrackingWriter) NeedNL() bool {
   214  	return t.last != '\n'
   215  }