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