github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/go/tool.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 "fmt" 9 "go/build" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "sort" 15 "strings" 16 ) 17 18 var cmdTool = &Command{ 19 Run: runTool, 20 UsageLine: "tool [-n] command [args...]", 21 Short: "run specified go tool", 22 Long: ` 23 Tool runs the go tool command identified by the arguments. 24 With no arguments it prints the list of known tools. 25 26 The -n flag causes tool to print the command that would be 27 executed but not execute it. 28 29 For more about each tool command, see 'go tool command -h'. 30 `, 31 } 32 33 var ( 34 toolGOOS = runtime.GOOS 35 toolGOARCH = runtime.GOARCH 36 toolIsWindows = toolGOOS == "windows" 37 toolDir = build.ToolDir 38 39 toolN bool 40 ) 41 42 func init() { 43 cmdTool.Flag.BoolVar(&toolN, "n", false, "") 44 } 45 46 const toolWindowsExtension = ".exe" 47 48 func tool(toolName string) string { 49 toolPath := filepath.Join(toolDir, toolName) 50 if toolIsWindows && toolName != "pprof" { 51 toolPath += toolWindowsExtension 52 } 53 // Give a nice message if there is no tool with that name. 54 if _, err := os.Stat(toolPath); err != nil { 55 if isInGoToolsRepo(toolName) { 56 fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName) 57 } else { 58 fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) 59 } 60 setExitStatus(3) 61 exit() 62 } 63 return toolPath 64 } 65 66 func isInGoToolsRepo(toolName string) bool { 67 switch toolName { 68 case "cover", "vet": 69 return true 70 } 71 return false 72 } 73 74 func runTool(cmd *Command, args []string) { 75 if len(args) == 0 { 76 listTools() 77 return 78 } 79 toolName := args[0] 80 // The tool name must be lower-case letters, numbers or underscores. 81 for _, c := range toolName { 82 switch { 83 case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_': 84 default: 85 fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName) 86 setExitStatus(2) 87 return 88 } 89 } 90 toolPath := tool(toolName) 91 if toolPath == "" { 92 return 93 } 94 if toolIsWindows && toolName == "pprof" { 95 args = append([]string{"perl", toolPath}, args[1:]...) 96 var err error 97 toolPath, err = exec.LookPath("perl") 98 if err != nil { 99 fmt.Fprintf(os.Stderr, "go tool: perl not found\n") 100 setExitStatus(3) 101 return 102 } 103 } 104 if toolN { 105 fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " ")) 106 return 107 } 108 toolCmd := &exec.Cmd{ 109 Path: toolPath, 110 Args: args, 111 Stdin: os.Stdin, 112 Stdout: os.Stdout, 113 Stderr: os.Stderr, 114 } 115 err := toolCmd.Run() 116 if err != nil { 117 // Only print about the exit status if the command 118 // didn't even run (not an ExitError) or it didn't exit cleanly 119 // or we're printing command lines too (-x mode). 120 // Assume if command exited cleanly (even with non-zero status) 121 // it printed any messages it wanted to print. 122 if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX { 123 fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err) 124 } 125 setExitStatus(1) 126 return 127 } 128 } 129 130 // listTools prints a list of the available tools in the tools directory. 131 func listTools() { 132 f, err := os.Open(toolDir) 133 if err != nil { 134 fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err) 135 setExitStatus(2) 136 return 137 } 138 defer f.Close() 139 names, err := f.Readdirnames(-1) 140 if err != nil { 141 fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err) 142 setExitStatus(2) 143 return 144 } 145 146 sort.Strings(names) 147 for _, name := range names { 148 // Unify presentation by going to lower case. 149 name = strings.ToLower(name) 150 // If it's windows, don't show the .exe suffix. 151 if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) { 152 name = name[:len(name)-len(toolWindowsExtension)] 153 } 154 fmt.Println(name) 155 } 156 }