cmd/go/internal/modfetch/codehost: quote arguments to commands printed from -x

Some of the arguments — particularly format strings passed to git commands — may
contain spaces, and it's useful to be able to paste commands from 'go get -x
foo' directly into a shell to reproduce their output.

Change-Id: I4f0c0b4e05db8b5232458e9a271f2ccbb665e85a
Reviewed-on: https://go-review.googlesource.com/126955
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2018-07-31 14:37:43 -04:00
parent ce06f5a222
commit f152f83a6e

View file

@ -201,6 +201,10 @@ func Run(dir string, cmdline ...interface{}) ([]byte, error) {
return RunWithStdin(dir, nil, cmdline...)
}
// bashQuoter escapes characters that have special meaning in double-quoted strings in the bash shell.
// See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html.
var bashQuoter = strings.NewReplacer(`"`, `\"`, `$`, `\$`, "`", "\\`", `\`, `\\`)
func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte, error) {
if dir != "" {
muIface, ok := dirLock.Load(dir)
@ -214,11 +218,31 @@ func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte,
cmd := str.StringList(cmdline...)
if cfg.BuildX {
var text string
text := new(strings.Builder)
if dir != "" {
text = "cd " + dir + "; "
text.WriteString("cd ")
text.WriteString(dir)
text.WriteString("; ")
}
for i, arg := range cmd {
if i > 0 {
text.WriteByte(' ')
}
switch {
case strings.ContainsAny(arg, "'"):
// Quote args that could be mistaken for quoted args.
text.WriteByte('"')
text.WriteString(bashQuoter.Replace(arg))
text.WriteByte('"')
case strings.ContainsAny(arg, "$`\\*?[\"\t\n\v\f\r \u0085\u00a0"):
// Quote args that contain special characters, glob patterns, or spaces.
text.WriteByte('\'')
text.WriteString(arg)
text.WriteByte('\'')
default:
text.WriteString(arg)
}
}
text += strings.Join(cmd, " ")
fmt.Fprintf(os.Stderr, "%s\n", text)
start := time.Now()
defer func() {