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 }