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