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