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 }