]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modfetch/codehost: quote arguments to commands printed from -x
authorBryan C. Mills <bcmills@google.com>
Tue, 31 Jul 2018 18:37:43 +0000 (14:37 -0400)
committerBryan C. Mills <bcmills@google.com>
Tue, 31 Jul 2018 19:14:46 +0000 (19:14 +0000)
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>

src/cmd/go/internal/modfetch/codehost/codehost.go

index 9c07b96957cdbb5d58be22a7705e28ef687157d1..4103ddc717f4912005cf9374519ccb85b6ead5c3 100644 (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() {