...
Source file src/pkg/cmd/go/internal/tool/tool.go
1
2
3
4
5
6 package tool
7
8 import (
9 "fmt"
10 "os"
11 "os/exec"
12 "sort"
13 "strings"
14
15 "cmd/go/internal/base"
16 "cmd/go/internal/cfg"
17 )
18
19 var CmdTool = &base.Command{
20 Run: runTool,
21 UsageLine: "go tool [-n] command [args...]",
22 Short: "run specified go tool",
23 Long: `
24 Tool runs the go tool command identified by the arguments.
25 With no arguments it prints the list of known tools.
26
27 The -n flag causes tool to print the command that would be
28 executed but not execute it.
29
30 For more about each tool command, see 'go doc cmd/<command>'.
31 `,
32 }
33
34 var toolN bool
35
36
37
38
39 func isGccgoTool(tool string) bool {
40 switch tool {
41 case "cgo", "fix", "cover", "godoc", "vet":
42 return true
43 }
44 return false
45 }
46
47 func init() {
48 CmdTool.Flag.BoolVar(&toolN, "n", false, "")
49 }
50
51 func runTool(cmd *base.Command, args []string) {
52 if len(args) == 0 {
53 listTools()
54 return
55 }
56 toolName := args[0]
57
58 for _, c := range toolName {
59 switch {
60 case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
61 default:
62 fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
63 base.SetExitStatus(2)
64 return
65 }
66 }
67 toolPath := base.Tool(toolName)
68 if toolPath == "" {
69 return
70 }
71 if toolN {
72 cmd := toolPath
73 if len(args) > 1 {
74 cmd += " " + strings.Join(args[1:], " ")
75 }
76 fmt.Printf("%s\n", cmd)
77 return
78 }
79 args[0] = toolPath
80 toolCmd := &exec.Cmd{
81 Path: toolPath,
82 Args: args,
83 Stdin: os.Stdin,
84 Stdout: os.Stdout,
85 Stderr: os.Stderr,
86 }
87 err := toolCmd.Run()
88 if err != nil {
89
90
91
92
93
94 if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || cfg.BuildX {
95 fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
96 }
97 base.SetExitStatus(1)
98 return
99 }
100 }
101
102
103 func listTools() {
104 f, err := os.Open(base.ToolDir)
105 if err != nil {
106 fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
107 base.SetExitStatus(2)
108 return
109 }
110 defer f.Close()
111 names, err := f.Readdirnames(-1)
112 if err != nil {
113 fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
114 base.SetExitStatus(2)
115 return
116 }
117
118 sort.Strings(names)
119 for _, name := range names {
120
121 name = strings.ToLower(name)
122
123 if base.ToolIsWindows && strings.HasSuffix(name, base.ToolWindowsExtension) {
124 name = name[:len(name)-len(base.ToolWindowsExtension)]
125 }
126
127
128 if cfg.BuildToolchainName == "gccgo" && !isGccgoTool(name) {
129 continue
130 }
131 fmt.Println(name)
132 }
133 }
134
View as plain text