@@ -81,6 +81,9 @@ if (isWindows) {
81
81
windowsVerbatimArguments : true ,
82
82
} , 'got expected options' )
83
83
84
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
85
+ // the contents will have a trailing space if no args are passed
86
+ t . equal ( contents , `@echo off\nscript "quoted parameter"; second command ` )
84
87
t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
85
88
cleanup ( )
86
89
t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
@@ -93,6 +96,7 @@ if (isWindows) {
93
96
whichPaths . set ( 'blrorp' , '/bin/blrorp' )
94
97
t . teardown ( ( ) => {
95
98
whichPaths . delete ( 'blrorp' )
99
+ delete process . env . ComSpec
96
100
} )
97
101
const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
98
102
event : 'event' ,
@@ -147,6 +151,114 @@ if (isWindows) {
147
151
t . end ( )
148
152
} )
149
153
154
+ t . test ( 'single escapes when initial command is not a batch file' , ( t ) => {
155
+ whichPaths . set ( 'script' , '/path/script.exe' )
156
+ t . teardown ( ( ) => whichPaths . delete ( 'script' ) )
157
+
158
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
159
+ event : 'event' ,
160
+ path : 'path' ,
161
+ cmd : 'script' ,
162
+ args : [ '"quoted parameter";' , 'second command' ] ,
163
+ } )
164
+ t . equal ( shell , 'cmd' , 'default shell applies' )
165
+ t . match ( args , [ '/d' , '/s' , '/c' , / \. c m d $ / ] , 'got expected args' )
166
+ t . match ( opts , {
167
+ env : {
168
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
169
+ npm_lifecycle_event : 'event' ,
170
+ npm_lifecycle_script : 'script' ,
171
+ npm_config_node_gyp : require . resolve ( 'node-gyp/bin/node-gyp.js' ) ,
172
+ } ,
173
+ stdio : undefined ,
174
+ cwd : 'path' ,
175
+ windowsVerbatimArguments : true ,
176
+ } , 'got expected options' )
177
+
178
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
179
+ t . equal ( contents , `@echo off\nscript ^"\\^"quoted parameter\\^";^" ^"second command^"` )
180
+ t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
181
+ cleanup ( )
182
+ t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
183
+
184
+ t . end ( )
185
+ } )
186
+
187
+ t . test ( 'double escapes when initial command is a batch file' , ( t ) => {
188
+ whichPaths . set ( 'script' , '/path/script.cmd' )
189
+ t . teardown ( ( ) => whichPaths . delete ( 'script' ) )
190
+
191
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
192
+ event : 'event' ,
193
+ path : 'path' ,
194
+ cmd : 'script' ,
195
+ args : [ '"quoted parameter";' , 'second command' ] ,
196
+ } )
197
+ t . equal ( shell , 'cmd' , 'default shell applies' )
198
+ t . match ( args , [ '/d' , '/s' , '/c' , / \. c m d $ / ] , 'got expected args' )
199
+ t . match ( opts , {
200
+ env : {
201
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
202
+ npm_lifecycle_event : 'event' ,
203
+ npm_lifecycle_script : 'script' ,
204
+ npm_config_node_gyp : require . resolve ( 'node-gyp/bin/node-gyp.js' ) ,
205
+ } ,
206
+ stdio : undefined ,
207
+ cwd : 'path' ,
208
+ windowsVerbatimArguments : true ,
209
+ } , 'got expected options' )
210
+
211
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
212
+ t . equal ( contents , [
213
+ '@echo off' ,
214
+ `script ^"^^\\^"\\^^\\^"quoted parameter\\^^\\^";^^\\^"^" ^"^^\\^"second command^^\\^"^"` ,
215
+ ] . join ( '\n' ) )
216
+ t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
217
+ cleanup ( )
218
+ t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
219
+
220
+ t . end ( )
221
+ } )
222
+
223
+ t . test ( 'correctly identifies initial cmd with spaces' , ( t ) => {
224
+ // we do blind lookups in our test fixture here, however node-which
225
+ // will remove surrounding quotes
226
+ whichPaths . set ( '"my script"' , '/path/script.cmd' )
227
+ t . teardown ( ( ) => whichPaths . delete ( 'my script' ) )
228
+
229
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
230
+ event : 'event' ,
231
+ path : 'path' ,
232
+ cmd : '"my script"' ,
233
+ args : [ '"quoted parameter";' , 'second command' ] ,
234
+ } )
235
+ t . equal ( shell , 'cmd' , 'default shell applies' )
236
+ t . match ( args , [ '/d' , '/s' , '/c' , / \. c m d $ / ] , 'got expected args' )
237
+ t . match ( opts , {
238
+ env : {
239
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
240
+ npm_lifecycle_event : 'event' ,
241
+ npm_lifecycle_script : 'script' ,
242
+ npm_config_node_gyp : require . resolve ( 'node-gyp/bin/node-gyp.js' ) ,
243
+ } ,
244
+ stdio : undefined ,
245
+ cwd : 'path' ,
246
+ windowsVerbatimArguments : true ,
247
+ } , 'got expected options' )
248
+
249
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
250
+ t . equal ( contents , [
251
+ '@echo off' ,
252
+ // eslint-disable-next-line max-len
253
+ `"my script" ^"^^\\^"\\^^\\^"quoted parameter\\^^\\^";^^\\^"^" ^"^^\\^"second command^^\\^"^"` ,
254
+ ] . join ( '\n' ) )
255
+ t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
256
+ cleanup ( )
257
+ t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
258
+
259
+ t . end ( )
260
+ } )
261
+
150
262
t . end ( )
151
263
} )
152
264
} else {
@@ -176,6 +288,38 @@ if (isWindows) {
176
288
windowsVerbatimArguments : undefined ,
177
289
} , 'got expected options' )
178
290
291
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
292
+ t . equal ( contents , `#!/usr/bin/env sh\nscript '"quoted parameter";' 'second command'` )
293
+ t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
294
+ cleanup ( )
295
+ t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
296
+
297
+ t . end ( )
298
+ } )
299
+
300
+ t . test ( 'skips /usr/bin/env if scriptShell is absolute' , ( t ) => {
301
+ const [ shell , args , opts , cleanup ] = makeSpawnArgs ( {
302
+ event : 'event' ,
303
+ path : 'path' ,
304
+ cmd : 'script' ,
305
+ args : [ '"quoted parameter";' , 'second command' ] ,
306
+ scriptShell : '/bin/sh' ,
307
+ } )
308
+ t . equal ( shell , '/bin/sh' , 'kept provided setting' )
309
+ t . match ( args , [ '-c' , / \. s h $ / ] , 'got expected args' )
310
+ t . match ( opts , {
311
+ env : {
312
+ npm_package_json : / p a c k a g e \. j s o n $ / ,
313
+ npm_lifecycle_event : 'event' ,
314
+ npm_lifecycle_script : 'script' ,
315
+ } ,
316
+ stdio : undefined ,
317
+ cwd : 'path' ,
318
+ windowsVerbatimArguments : undefined ,
319
+ } , 'got expected options' )
320
+
321
+ const contents = fs . readFileSync ( args [ args . length - 1 ] , { encoding : 'utf8' } )
322
+ t . equal ( contents , `#!/bin/sh\nscript '"quoted parameter";' 'second command'` )
179
323
t . ok ( fs . existsSync ( args [ args . length - 1 ] ) , 'script file was written' )
180
324
cleanup ( )
181
325
t . not ( fs . existsSync ( args [ args . length - 1 ] ) , 'cleanup removes script file' )
0 commit comments