1 // Copyright 2016 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.
20 var cmdBug
= &Command
{
23 Short
: "start a bug report",
25 Bug opens the default browser and starts a new bug report.
26 The report includes useful system information.
31 cmdBug
.Flag
.BoolVar(&buildV
, "v", false, "")
34 func runBug(cmd
*Command
, args
[]string) {
36 buf
.WriteString(bugHeader
)
37 inspectGoVersion(&buf
)
38 fmt
.Fprint(&buf
, "#### System details\n\n")
39 fmt
.Fprintln(&buf
, "```")
40 fmt
.Fprintf(&buf
, "go version %s %s/%s\n", runtime
.Version(), runtime
.GOOS
, runtime
.GOARCH
)
42 env
= append(env
, extraEnvVars()...)
43 for _
, e
:= range env
{
44 // Hide the TERM environment variable from "go bug".
47 fmt
.Fprintf(&buf
, "%s=\"%s\"\n", e
.name
, e
.value
)
53 fmt
.Fprintln(&buf
, "```")
56 url
:= "https://github.com/golang/go/issues/new?body=" + queryEscape(body
)
57 if !openBrowser(url
) {
58 fmt
.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
63 const bugHeader
= `Please answer these questions before submitting your issue. Thanks!
66 If possible, provide a recipe for reproducing the error.
67 A complete runnable program is good.
68 A link on play.golang.org is best.
71 #### What did you expect to see?
74 #### What did you see instead?
79 func printGoDetails(w io
.Writer
) {
80 printCmdOut(w
, "GOROOT/bin/go version: ", filepath
.Join(runtime
.GOROOT(), "bin/go"), "version")
81 printCmdOut(w
, "GOROOT/bin/go tool compile -V: ", filepath
.Join(runtime
.GOROOT(), "bin/go"), "tool", "compile", "-V")
84 func printOSDetails(w io
.Writer
) {
87 printCmdOut(w
, "uname -v: ", "uname", "-v")
88 printCmdOut(w
, "", "sw_vers")
90 printCmdOut(w
, "uname -sr: ", "uname", "-sr")
91 printCmdOut(w
, "", "lsb_release", "-a")
93 case "openbsd", "netbsd", "freebsd", "dragonfly":
94 printCmdOut(w
, "uname -v: ", "uname", "-v")
96 out
, err
:= ioutil
.ReadFile("/etc/release")
98 fmt
.Fprintf(w
, "/etc/release: %s\n", out
)
101 fmt
.Printf("failed to read /etc/release: %v\n", err
)
107 func printCDetails(w io
.Writer
) {
108 printCmdOut(w
, "lldb --version: ", "lldb", "--version")
109 cmd
:= exec
.Command("gdb", "--version")
110 out
, err
:= cmd
.Output()
112 // There's apparently no combination of command line flags
113 // to get gdb to spit out its version without the license and warranty.
114 // Print up to the first newline.
115 fmt
.Fprintf(w
, "gdb --version: %s\n", firstLine(out
))
118 fmt
.Printf("failed to run gdb --version: %v\n", err
)
123 func inspectGoVersion(w io
.Writer
) {
124 data
, err
:= httpGET("https://golang.org/VERSION?m=text")
127 fmt
.Printf("failed to read from golang.org/VERSION: %v\n", err
)
132 // golang.org/VERSION currently returns a whitespace-free string,
133 // but just in case, protect against that changing.
134 // Similarly so for runtime.Version.
135 release
:= string(bytes
.TrimSpace(data
))
136 vers
:= strings
.TrimSpace(runtime
.Version())
143 // Devel version or outdated release. Either way, this request is apropos.
144 fmt
.Fprintf(w
, "#### Does this issue reproduce with the latest release (%s)?\n\n\n", release
)
147 // printCmdOut prints the output of running the given command.
148 // It ignores failures; 'go bug' is best effort.
149 func printCmdOut(w io
.Writer
, prefix
, path
string, args
...string) {
150 cmd
:= exec
.Command(path
, args
...)
151 out
, err
:= cmd
.Output()
154 fmt
.Printf("%s %s: %v\n", path
, strings
.Join(args
, " "), err
)
158 fmt
.Fprintf(w
, "%s%s\n", prefix
, bytes
.TrimSpace(out
))
161 // firstLine returns the first line of a given byte slice.
162 func firstLine(buf
[]byte) []byte {
163 idx
:= bytes
.IndexByte(buf
, '\n')
167 return bytes
.TrimSpace(buf
)
170 // printGlibcVersion prints information about the glibc version.
171 // It ignores failures.
172 func printGlibcVersion(w io
.Writer
) {
173 tempdir
:= os
.TempDir()
177 src
:= []byte(`int main() {}`)
178 srcfile
:= filepath
.Join(tempdir
, "go-bug.c")
179 outfile
:= filepath
.Join(tempdir
, "go-bug")
180 err
:= ioutil
.WriteFile(srcfile
, src
, 0644)
184 defer os
.Remove(srcfile
)
185 cmd
:= exec
.Command("gcc", "-o", outfile
, srcfile
)
186 if _
, err
= cmd
.CombinedOutput(); err
!= nil {
189 defer os
.Remove(outfile
)
191 cmd
= exec
.Command("ldd", outfile
)
192 out
, err
:= cmd
.CombinedOutput()
196 re
:= regexp
.MustCompile(`libc\.so[^ ]* => ([^ ]+)`)
197 m
:= re
.FindStringSubmatch(string(out
))
201 cmd
= exec
.Command(m
[1])
202 out
, err
= cmd
.Output()
206 fmt
.Fprintf(w
, "%s: %s\n", m
[1], firstLine(out
))
208 // print another line (the one containing version string) in case of musl libc
209 if idx
:= bytes
.IndexByte(out
, '\n'); bytes
.Index(out
, []byte("musl")) != -1 && idx
> -1 {
210 fmt
.Fprintf(w
, "%s\n", firstLine(out
[idx
+1:]))