@@ -2,8 +2,10 @@ package shellUtils
2
2
3
3
import (
4
4
"bytes"
5
+ "fmt"
5
6
"os"
6
7
"os/exec"
8
+ "strings"
7
9
"sync"
8
10
)
9
11
@@ -19,22 +21,63 @@ func RunCommandAsyncWithChan(command string, finishedChan chan bool) *ExecuteCom
19
21
return runCommand (command , true , finishedChan )
20
22
}
21
23
24
+ func RunPowerShellAsyncWithChan (command string , finishedChan chan bool ) * ExecuteCommandResult {
25
+ return runPowerShell (command , true , finishedChan )
26
+ }
27
+
22
28
func runCommand (command string , isAsync bool , finishedChan chan bool ) * ExecuteCommandResult {
23
29
stdout := new (bytes.Buffer )
24
30
stderr := new (bytes.Buffer )
25
31
var result * ExecuteCommandResult
26
32
if isAsync {
27
33
result = executeCommand (command , & ExecuteCommandConfig {
34
+ TargetRunner : GetCommandTargetRunner (),
35
+ PrimaryArgs : GetCommandPrimaryArgs (),
28
36
Stdout : stdout ,
29
37
Stderr : stderr ,
30
38
autoSetOutput : true ,
31
39
FinishedChan : finishedChan ,
32
- }, true )
40
+ IsAsync : true ,
41
+ })
42
+ return result
43
+ } else {
44
+ result = executeCommand (command , & ExecuteCommandConfig {
45
+ TargetRunner : GetCommandTargetRunner (),
46
+ PrimaryArgs : GetCommandPrimaryArgs (),
47
+ Stdout : stdout ,
48
+ Stderr : stderr ,
49
+ })
50
+ }
51
+
52
+ result .Stdout = stdout .String ()
53
+ result .Stderr = stderr .String ()
54
+
55
+ return result
56
+ }
57
+
58
+ func runPowerShell (command string , isAsync bool , finishedChan chan bool ) * ExecuteCommandResult {
59
+ stdout := new (bytes.Buffer )
60
+ stderr := new (bytes.Buffer )
61
+ var result * ExecuteCommandResult
62
+ if isAsync {
63
+ result = executePowerShell (command , & ExecuteCommandConfig {
64
+ TargetRunner : GetPowerShellRunner (),
65
+ PrimaryArgs : GetPowerShellPrimaryArgs (),
66
+ Stdout : stdout ,
67
+ Stderr : stderr ,
68
+ autoSetOutput : true ,
69
+ FinishedChan : finishedChan ,
70
+ IsAsync : true ,
71
+ RemovePowerShellPrompt : true ,
72
+ })
33
73
return result
34
74
} else {
35
- result = ExecuteCommand (command , & ExecuteCommandConfig {
36
- Stdout : stdout ,
37
- Stderr : stderr ,
75
+ result = executePowerShell (command , & ExecuteCommandConfig {
76
+ TargetRunner : GetCommandTargetRunner (),
77
+ PrimaryArgs : GetPowerShellPrimaryArgs (),
78
+ Stdout : stdout ,
79
+ Stderr : stderr ,
80
+ RemovePowerShellPrompt : true ,
38
81
})
39
82
}
40
83
@@ -45,45 +88,165 @@ func runCommand(command string, isAsync bool, finishedChan chan bool) *ExecuteCo
45
88
}
46
89
47
90
func ExecuteCommand (command string , config * ExecuteCommandConfig ) * ExecuteCommandResult {
48
- return executeCommand (command , config , false )
91
+ if config == nil {
92
+ config = & ExecuteCommandConfig {
93
+ TargetRunner : GetCommandTargetRunner (),
94
+ PrimaryArgs : GetCommandPrimaryArgs (),
95
+ }
96
+ } else if config .IsAsync {
97
+ config .IsAsync = false
98
+ }
99
+
100
+ return executeCommand (command , config )
49
101
}
50
102
51
103
func ExecuteCommandAsync (command string , config * ExecuteCommandConfig ) * ExecuteCommandResult {
52
- return executeCommand (command , config , true )
104
+ if config == nil {
105
+ config = & ExecuteCommandConfig {
106
+ TargetRunner : GetCommandTargetRunner (),
107
+ PrimaryArgs : GetCommandPrimaryArgs (),
108
+ IsAsync : true ,
109
+ }
110
+ }
111
+
112
+ return executeCommand (command , config )
113
+ }
114
+
115
+ func ExecutePowerShellAsync (command string , config * ExecuteCommandConfig ) * ExecuteCommandResult {
116
+ if config == nil {
117
+ config = & ExecuteCommandConfig {
118
+ TargetRunner : GetPowerShellRunner (),
119
+ PrimaryArgs : GetPowerShellPrimaryArgs (),
120
+ IsAsync : true ,
121
+ }
122
+ }
123
+
124
+ return executePowerShell (command , config )
125
+ }
126
+
127
+ func GetCommandTargetRunner () string {
128
+ if os .PathSeparator == '/' {
129
+ return ShellToUseUnix
130
+ } else {
131
+ return ShellToUseWin
132
+ }
133
+ }
134
+
135
+ func GetPowerShellRunner () string {
136
+ return PowerShellCmd
137
+ }
138
+
139
+ func GetCommandPrimaryArgs () []string {
140
+ if os .PathSeparator == '/' {
141
+ return []string {"-c" }
142
+ }
143
+ return []string {"/c" }
53
144
}
54
145
146
+ func GetPowerShellPrimaryArgs () []string {
147
+ return []string {"-nologo" , "-noprofile" , "-NonInteractive" }
148
+ }
149
+
150
+ // executeCommand is the internal version of the execute command function.
151
+ // WARNING: the config argument MUST NOT be nil.
55
152
func executeCommand (
56
153
command string ,
57
154
config * ExecuteCommandConfig ,
58
- isAsync bool ,
59
155
) * ExecuteCommandResult {
60
- if config == nil {
61
- config = & ExecuteCommandConfig {}
156
+ var cmd * exec.Cmd
157
+ result := & ExecuteCommandResult {
158
+ autoSetOutput : config .autoSetOutput ,
159
+ mutex : & sync.Mutex {},
160
+ }
161
+
162
+ cmd = exec .Command (config .TargetRunner , append (config .PrimaryArgs , command )... )
163
+ if len (config .ExtraFiles ) != 0 {
164
+ cmd .ExtraFiles = append (cmd .ExtraFiles , config .ExtraFiles ... )
62
165
}
63
166
167
+ cmd .Stdout = config .Stdout
168
+ cmd .Stdin = config .Stdin
169
+ cmd .Stderr = config .Stderr
170
+ cmd .Args = append (cmd .Args , config .AdditionalArgs ... )
171
+ cmd .Env = append (cmd .Env , config .AdditionalEnv ... )
172
+
173
+ result .cmd = cmd
174
+ result .FinishedChan = config .FinishedChan
175
+
176
+ finishUpCommand (cmd , config , result )
177
+
178
+ return result
179
+ }
180
+
181
+ // executeCommand is the internal version of the execute powershell function.
182
+ // executes the given powershell script/command/set of commands using the
183
+ // "powershell" (it might be powershell 5.1 which ships with windows by default).
184
+ // WARNING: the config argument MUST NOT be nil.
185
+ func executePowerShell (
186
+ command string ,
187
+ config * ExecuteCommandConfig ,
188
+ ) * ExecuteCommandResult {
64
189
var cmd * exec.Cmd
65
190
result := & ExecuteCommandResult {
66
191
autoSetOutput : config .autoSetOutput ,
67
192
mutex : & sync.Mutex {},
68
193
}
69
- if os .PathSeparator == '/' {
70
- cmd = exec .Command (ShellToUseUnix , "-c" , command )
194
+
195
+ if config .RemovePowerShellPrompt && ! strings .Contains (command , "function prompt" ) {
196
+ // hacky way of getting rid of powershell prompt
197
+ command = PowerShellPromptOverride + command
198
+ }
199
+
200
+ cmd = exec .Command (config .TargetRunner , config .PrimaryArgs ... )
201
+ if len (config .ExtraFiles ) != 0 {
71
202
cmd .ExtraFiles = append (cmd .ExtraFiles , config .ExtraFiles ... )
72
- } else {
73
- cmd = exec .Command (ShellToUseWin , "/C" , command )
74
203
}
75
204
76
205
cmd .Stdout = config .Stdout
77
- cmd .Stdin = config .Stdin
206
+
207
+ pStdin , err := cmd .StdinPipe ()
208
+ if err != nil {
209
+ result .Error = err
210
+ return result
211
+ }
212
+
213
+ if config .Stdin != nil {
214
+ wrappedStdin := & StdinWrapper {
215
+ InnerWriter : pStdin ,
216
+ }
217
+
218
+ result .pipedStdin = wrappedStdin
219
+ wrappedStdin .OnWrite = append (wrappedStdin .OnWrite , func (p []byte ) (n int , err error ) {
220
+ return config .Stdin .Read (p )
221
+ })
222
+ } else {
223
+ result .pipedStdin = pStdin
224
+ }
225
+
78
226
cmd .Stderr = config .Stderr
79
227
cmd .Args = append (cmd .Args , config .AdditionalArgs ... )
80
228
cmd .Env = append (cmd .Env , config .AdditionalEnv ... )
81
229
82
230
result .cmd = cmd
83
231
result .FinishedChan = config .FinishedChan
232
+ _ , err = fmt .Fprint (result .pipedStdin , command )
233
+ if err != nil {
234
+ result .Error = err
235
+ return result
236
+ }
84
237
85
- if isAsync {
238
+ finishUpCommand (cmd , config , result )
239
+ return result
240
+ }
241
+
242
+ func finishUpCommand (
243
+ cmd * exec.Cmd ,
244
+ config * ExecuteCommandConfig ,
245
+ result * ExecuteCommandResult ,
246
+ ) {
247
+ if config .IsAsync {
86
248
go func () {
249
+ result .ClosePipes ()
87
250
result .Error = cmd .Run ()
88
251
result .IsFinished = true
89
252
if result .autoSetOutput {
@@ -103,11 +266,11 @@ func executeCommand(
103
266
}
104
267
}()
105
268
} else {
269
+ result .ClosePipes ()
106
270
result .Error = cmd .Run ()
107
271
result .IsFinished = true
108
272
}
109
273
110
- return result
111
274
}
112
275
113
276
// GetGitStats function will return the git stats in the following format:
0 commit comments