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