github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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] [-tags 'tag list'] [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}}'.  One extra template function is available, "join",
    31  which calls strings.Join. 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          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          HFiles   []string       // .h source files
    50          SFiles   []string       // .s source files
    51          SysoFiles []string      // .syso object files to add to archive
    52          SwigFiles []string      // .swig files
    53          SwigCXXFiles []string   // .swigcxx files
    54  
    55          // Cgo directives
    56          CgoCFLAGS    []string // cgo: flags for C compiler
    57          CgoLDFLAGS   []string // cgo: flags for linker
    58          CgoPkgConfig []string // cgo: pkg-config names
    59  
    60          // Dependency information
    61          Imports []string // import paths used by this package
    62          Deps    []string // all (recursively) imported dependencies
    63  
    64          // Error information
    65          Incomplete bool            // this package or a dependency has an error
    66          Error      *PackageError   // error loading package
    67          DepsErrors []*PackageError // errors loading dependencies
    68  
    69          TestGoFiles  []string // _test.go files in package
    70          TestImports  []string // imports from TestGoFiles
    71          XTestGoFiles []string // _test.go files outside package
    72          XTestImports []string // imports from XTestGoFiles
    73      }
    74  
    75  The -json flag causes the package data to be printed in JSON format
    76  instead of using the template format.
    77  
    78  The -e flag changes the handling of erroneous packages, those that
    79  cannot be found or are malformed.  By default, the list command
    80  prints an error to standard error for each erroneous package and
    81  omits the packages from consideration during the usual printing.
    82  With the -e flag, the list command never prints errors to standard
    83  error and instead processes the erroneous packages with the usual
    84  printing.  Erroneous packages will have a non-empty ImportPath and
    85  a non-nil Error field; other information may or may not be missing
    86  (zeroed).
    87  
    88  The -tags flag specifies a list of build tags, like in the 'go build'
    89  command.
    90  
    91  For more about specifying packages, see 'go help packages'.
    92  	`,
    93  }
    94  
    95  func init() {
    96  	cmdList.Run = runList // break init cycle
    97  	cmdList.Flag.Var(buildCompiler{}, "compiler", "")
    98  	cmdList.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
    99  }
   100  
   101  var listE = cmdList.Flag.Bool("e", false, "")
   102  var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
   103  var listJson = cmdList.Flag.Bool("json", false, "")
   104  var nl = []byte{'\n'}
   105  
   106  func runList(cmd *Command, args []string) {
   107  	out := newTrackingWriter(os.Stdout)
   108  	defer out.w.Flush()
   109  
   110  	var do func(*Package)
   111  	if *listJson {
   112  		do = func(p *Package) {
   113  			b, err := json.MarshalIndent(p, "", "\t")
   114  			if err != nil {
   115  				out.Flush()
   116  				fatalf("%s", err)
   117  			}
   118  			out.Write(b)
   119  			out.Write(nl)
   120  		}
   121  	} else {
   122  		tmpl, err := template.New("main").Funcs(template.FuncMap{"join": strings.Join}).Parse(*listFmt)
   123  		if err != nil {
   124  			fatalf("%s", err)
   125  		}
   126  		do = func(p *Package) {
   127  			if err := tmpl.Execute(out, p); err != nil {
   128  				out.Flush()
   129  				fatalf("%s", err)
   130  			}
   131  			if out.NeedNL() {
   132  				out.Write([]byte{'\n'})
   133  			}
   134  		}
   135  	}
   136  
   137  	load := packages
   138  	if *listE {
   139  		load = packagesAndErrors
   140  	}
   141  
   142  	for _, pkg := range load(args) {
   143  		do(pkg)
   144  	}
   145  }
   146  
   147  // TrackingWriter tracks the last byte written on every write so
   148  // we can avoid printing a newline if one was already written or
   149  // if there is no output at all.
   150  type TrackingWriter struct {
   151  	w    *bufio.Writer
   152  	last byte
   153  }
   154  
   155  func newTrackingWriter(w io.Writer) *TrackingWriter {
   156  	return &TrackingWriter{
   157  		w:    bufio.NewWriter(w),
   158  		last: '\n',
   159  	}
   160  }
   161  
   162  func (t *TrackingWriter) Write(p []byte) (n int, err error) {
   163  	n, err = t.w.Write(p)
   164  	if n > 0 {
   165  		t.last = p[n-1]
   166  	}
   167  	return
   168  }
   169  
   170  func (t *TrackingWriter) Flush() {
   171  	t.w.Flush()
   172  }
   173  
   174  func (t *TrackingWriter) NeedNL() bool {
   175  	return t.last != '\n'
   176  }