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