...
Source file src/pkg/cmd/go/internal/base/base.go
1
2
3
4
5
6
7 package base
8
9 import (
10 "bytes"
11 "errors"
12 "flag"
13 "fmt"
14 "go/scanner"
15 "log"
16 "os"
17 "os/exec"
18 "strings"
19 "sync"
20
21 "cmd/go/internal/cfg"
22 "cmd/go/internal/str"
23 )
24
25
26
27 type Command struct {
28
29
30 Run func(cmd *Command, args []string)
31
32
33
34 UsageLine string
35
36
37 Short string
38
39
40 Long string
41
42
43 Flag flag.FlagSet
44
45
46
47 CustomFlags bool
48
49
50
51
52 Commands []*Command
53 }
54
55 var Go = &Command{
56 UsageLine: "go",
57 Long: `Go is a tool for managing Go source code.`,
58
59 }
60
61
62 func (c *Command) LongName() string {
63 name := c.UsageLine
64 if i := strings.Index(name, " ["); i >= 0 {
65 name = name[:i]
66 }
67 if name == "go" {
68 return ""
69 }
70 return strings.TrimPrefix(name, "go ")
71 }
72
73
74 func (c *Command) Name() string {
75 name := c.LongName()
76 if i := strings.LastIndex(name, " "); i >= 0 {
77 name = name[i+1:]
78 }
79 return name
80 }
81
82 func (c *Command) Usage() {
83 fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine)
84 fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName())
85 SetExitStatus(2)
86 Exit()
87 }
88
89
90
91 func (c *Command) Runnable() bool {
92 return c.Run != nil
93 }
94
95 var atExitFuncs []func()
96
97 func AtExit(f func()) {
98 atExitFuncs = append(atExitFuncs, f)
99 }
100
101 func Exit() {
102 for _, f := range atExitFuncs {
103 f()
104 }
105 os.Exit(exitStatus)
106 }
107
108 func Fatalf(format string, args ...interface{}) {
109 Errorf(format, args...)
110 Exit()
111 }
112
113 func Errorf(format string, args ...interface{}) {
114 log.Printf(format, args...)
115 SetExitStatus(1)
116 }
117
118 func ExitIfErrors() {
119 if exitStatus != 0 {
120 Exit()
121 }
122 }
123
124 var exitStatus = 0
125 var exitMu sync.Mutex
126
127 func SetExitStatus(n int) {
128 exitMu.Lock()
129 if exitStatus < n {
130 exitStatus = n
131 }
132 exitMu.Unlock()
133 }
134
135 func GetExitStatus() int {
136 return exitStatus
137 }
138
139
140
141
142 func Run(cmdargs ...interface{}) {
143 cmdline := str.StringList(cmdargs...)
144 if cfg.BuildN || cfg.BuildX {
145 fmt.Printf("%s\n", strings.Join(cmdline, " "))
146 if cfg.BuildN {
147 return
148 }
149 }
150
151 cmd := exec.Command(cmdline[0], cmdline[1:]...)
152 cmd.Stdout = os.Stdout
153 cmd.Stderr = os.Stderr
154 if err := cmd.Run(); err != nil {
155 Errorf("%v", err)
156 }
157 }
158
159
160 func RunStdin(cmdline []string) {
161 cmd := exec.Command(cmdline[0], cmdline[1:]...)
162 cmd.Stdin = os.Stdin
163 cmd.Stdout = os.Stdout
164 cmd.Stderr = os.Stderr
165 cmd.Env = cfg.OrigEnv
166 StartSigHandlers()
167 if err := cmd.Run(); err != nil {
168 Errorf("%v", err)
169 }
170 }
171
172
173
174 var Usage func()
175
176
177
178
179 func ExpandScanner(err error) error {
180
181 if err, ok := err.(scanner.ErrorList); ok {
182
183
184
185
186
187 var buf bytes.Buffer
188 for _, e := range err {
189 e.Pos.Filename = ShortPath(e.Pos.Filename)
190 buf.WriteString("\n")
191 buf.WriteString(e.Error())
192 }
193 return errors.New(buf.String())
194 }
195 return err
196 }
197
View as plain text