Browse code

bump mattn/go-shellwords v1.0.5

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2019/04/06 08:10:59
Showing 5 changed files
... ...
@@ -10,7 +10,7 @@ github.com/gorilla/mux v1.7.0
10 10
 github.com/Microsoft/opengcs a10967154e143a36014584a6f664344e3bb0aa64
11 11
 github.com/konsorten/go-windows-terminal-sequences v1.0.1
12 12
 github.com/kr/pty 521317be5ebc228a0f0ede099fa2a0b5ece22e49 # v1.1.4
13
-github.com/mattn/go-shellwords v1.0.3
13
+github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5
14 14
 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1
15 15
 github.com/tchap/go-patricia v2.2.6
16 16
 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 # v0.1.0
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"errors"
5 5
 	"os"
6 6
 	"regexp"
7
+	"strings"
7 8
 )
8 9
 
9 10
 var (
... ...
@@ -21,13 +22,17 @@ func isSpace(r rune) bool {
21 21
 	return false
22 22
 }
23 23
 
24
-func replaceEnv(s string) string {
24
+func replaceEnv(getenv func(string) string, s string) string {
25
+	if getenv == nil {
26
+		getenv = os.Getenv
27
+	}
28
+
25 29
 	return envRe.ReplaceAllStringFunc(s, func(s string) string {
26 30
 		s = s[1:]
27 31
 		if s[0] == '{' {
28 32
 			s = s[1 : len(s)-1]
29 33
 		}
30
-		return os.Getenv(s)
34
+		return getenv(s)
31 35
 	})
32 36
 }
33 37
 
... ...
@@ -35,16 +40,24 @@ type Parser struct {
35 35
 	ParseEnv      bool
36 36
 	ParseBacktick bool
37 37
 	Position      int
38
+
39
+	// If ParseEnv is true, use this for getenv.
40
+	// If nil, use os.Getenv.
41
+	Getenv func(string) string
38 42
 }
39 43
 
40 44
 func NewParser() *Parser {
41
-	return &Parser{ParseEnv, ParseBacktick, 0}
45
+	return &Parser{
46
+		ParseEnv:      ParseEnv,
47
+		ParseBacktick: ParseBacktick,
48
+		Position:      0,
49
+	}
42 50
 }
43 51
 
44 52
 func (p *Parser) Parse(line string) ([]string, error) {
45 53
 	args := []string{}
46 54
 	buf := ""
47
-	var escaped, doubleQuoted, singleQuoted, backQuote bool
55
+	var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool
48 56
 	backtick := ""
49 57
 
50 58
 	pos := -1
... ...
@@ -68,12 +81,12 @@ loop:
68 68
 		}
69 69
 
70 70
 		if isSpace(r) {
71
-			if singleQuoted || doubleQuoted || backQuote {
71
+			if singleQuoted || doubleQuoted || backQuote || dollarQuote {
72 72
 				buf += string(r)
73 73
 				backtick += string(r)
74 74
 			} else if got {
75 75
 				if p.ParseEnv {
76
-					buf = replaceEnv(buf)
76
+					buf = replaceEnv(p.Getenv, buf)
77 77
 				}
78 78
 				args = append(args, buf)
79 79
 				buf = ""
... ...
@@ -84,7 +97,7 @@ loop:
84 84
 
85 85
 		switch r {
86 86
 		case '`':
87
-			if !singleQuoted && !doubleQuoted {
87
+			if !singleQuoted && !doubleQuoted && !dollarQuote {
88 88
 				if p.ParseBacktick {
89 89
 					if backQuote {
90 90
 						out, err := shellRun(backtick)
... ...
@@ -100,18 +113,55 @@ loop:
100 100
 				backtick = ""
101 101
 				backQuote = !backQuote
102 102
 			}
103
+		case ')':
104
+			if !singleQuoted && !doubleQuoted && !backQuote {
105
+				if p.ParseBacktick {
106
+					if dollarQuote {
107
+						out, err := shellRun(backtick)
108
+						if err != nil {
109
+							return nil, err
110
+						}
111
+						if r == ')' {
112
+							buf = buf[:len(buf)-len(backtick)-2] + out
113
+						} else {
114
+							buf = buf[:len(buf)-len(backtick)-1] + out
115
+						}
116
+					}
117
+					backtick = ""
118
+					dollarQuote = !dollarQuote
119
+					continue
120
+				}
121
+				backtick = ""
122
+				dollarQuote = !dollarQuote
123
+			}
124
+		case '(':
125
+			if !singleQuoted && !doubleQuoted && !backQuote {
126
+				if !dollarQuote && strings.HasSuffix(buf, "$") {
127
+					dollarQuote = true
128
+					buf += "("
129
+					continue
130
+				} else {
131
+					return nil, errors.New("invalid command line string")
132
+				}
133
+			}
103 134
 		case '"':
104
-			if !singleQuoted {
135
+			if !singleQuoted && !dollarQuote {
105 136
 				doubleQuoted = !doubleQuoted
106 137
 				continue
107 138
 			}
108 139
 		case '\'':
109
-			if !doubleQuoted {
140
+			if !doubleQuoted && !dollarQuote {
110 141
 				singleQuoted = !singleQuoted
111 142
 				continue
112 143
 			}
113 144
 		case ';', '&', '|', '<', '>':
114 145
 			if !(escaped || singleQuoted || doubleQuoted || backQuote) {
146
+				if r == '>' && len(buf) > 0 {
147
+					if c := buf[0]; '0' <= c && c <= '9' {
148
+						i -= 1
149
+						got = false
150
+					}
151
+				}
115 152
 				pos = i
116 153
 				break loop
117 154
 			}
... ...
@@ -119,19 +169,19 @@ loop:
119 119
 
120 120
 		got = true
121 121
 		buf += string(r)
122
-		if backQuote {
122
+		if backQuote || dollarQuote {
123 123
 			backtick += string(r)
124 124
 		}
125 125
 	}
126 126
 
127 127
 	if got {
128 128
 		if p.ParseEnv {
129
-			buf = replaceEnv(buf)
129
+			buf = replaceEnv(p.Getenv, buf)
130 130
 		}
131 131
 		args = append(args, buf)
132 132
 	}
133 133
 
134
-	if escaped || singleQuoted || doubleQuoted || backQuote {
134
+	if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote {
135 135
 		return nil, errors.New("invalid command line string")
136 136
 	}
137 137
 
138 138
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+// +build !go1.6
1
+
2
+package shellwords
3
+
4
+import (
5
+	"os"
6
+	"os/exec"
7
+	"runtime"
8
+	"strings"
9
+)
10
+
11
+func shellRun(line string) (string, error) {
12
+	var b []byte
13
+	var err error
14
+	if runtime.GOOS == "windows" {
15
+		b, err = exec.Command(os.Getenv("COMSPEC"), "/c", line).Output()
16
+	} else {
17
+		b, err = exec.Command(os.Getenv("SHELL"), "-c", line).Output()
18
+	}
19
+	if err != nil {
20
+		return "", err
21
+	}
22
+	return strings.TrimSpace(string(b)), nil
23
+}
... ...
@@ -1,4 +1,4 @@
1
-// +build !windows
1
+// +build !windows,go1.6
2 2
 
3 3
 package shellwords
4 4
 
... ...
@@ -13,6 +13,9 @@ func shellRun(line string) (string, error) {
13 13
 	shell := os.Getenv("SHELL")
14 14
 	b, err := exec.Command(shell, "-c", line).Output()
15 15
 	if err != nil {
16
+		if eerr, ok := err.(*exec.ExitError); ok {
17
+			b = eerr.Stderr
18
+		}
16 19
 		return "", errors.New(err.Error() + ":" + string(b))
17 20
 	}
18 21
 	return strings.TrimSpace(string(b)), nil
... ...
@@ -1,3 +1,5 @@
1
+// +build windows,go1.6
2
+
1 3
 package shellwords
2 4
 
3 5
 import (
... ...
@@ -11,6 +13,9 @@ func shellRun(line string) (string, error) {
11 11
 	shell := os.Getenv("COMSPEC")
12 12
 	b, err := exec.Command(shell, "/c", line).Output()
13 13
 	if err != nil {
14
+		if eerr, ok := err.(*exec.ExitError); ok {
15
+			b = eerr.Stderr
16
+		}
14 17
 		return "", errors.New(err.Error() + ":" + string(b))
15 18
 	}
16 19
 	return strings.TrimSpace(string(b)), nil