@@ -81,6 +81,7 @@ class BuildCommand(BuildCommandResultMixin):
81
81
:param build_env: build environment to use to execute commands
82
82
:param bin_path: binary path to add to PATH resolution
83
83
:param description: a more grokable description of the command being run
84
+ :param kwargs: allow to subclass this class and extend it
84
85
"""
85
86
86
87
def __init__ (
@@ -95,6 +96,7 @@ def __init__(
95
96
bin_path = None ,
96
97
description = None ,
97
98
record_as_success = False ,
99
+ ** kwargs ,
98
100
):
99
101
self .command = command
100
102
self .shell = shell
@@ -164,8 +166,13 @@ def run(self):
164
166
environment ['PATH' ] = ':' .join (env_paths )
165
167
166
168
try :
169
+ # When using ``shell=True`` the command should be flatten
170
+ command = self .command
171
+ if self .shell :
172
+ command = self .get_command ()
173
+
167
174
proc = subprocess .Popen (
168
- self . command ,
175
+ command ,
169
176
shell = self .shell ,
170
177
# This is done here for local builds, but not for docker,
171
178
# as we want docker to expand inside the container
@@ -294,14 +301,20 @@ class DockerBuildCommand(BuildCommand):
294
301
Build command to execute in docker container
295
302
"""
296
303
297
- def run (self ):
304
+ def __init__ (self , * args , escape_command = True , ** kwargs ):
298
305
"""
299
- Execute command in existing Docker container .
306
+ Override default to extend behavior .
300
307
301
- :param cmd_input: input to pass to command in STDIN
302
- :type cmd_input: str
303
- :param combine_output: combine STDERR into STDOUT
308
+ :param escape_command: whether escape special chars the command before
309
+ executing it in the container. This should only be disabled on
310
+ trusted or internal commands.
311
+ :type escape_command: bool
304
312
"""
313
+ self .escape_command = escape_command
314
+ super (DockerBuildCommand , self ).__init__ (* args , ** kwargs )
315
+
316
+ def run (self ):
317
+ """Execute command in existing Docker container."""
305
318
log .info (
306
319
"Running in container %s: '%s' [%s]" ,
307
320
self .build_env .container_id ,
@@ -350,13 +363,15 @@ def run(self):
350
363
351
364
def get_wrapped_command (self ):
352
365
"""
353
- Escape special bash characters in command to wrap in shell .
366
+ Wrap command in a shell and optionally escape special bash characters .
354
367
355
368
In order to set the current working path inside a docker container, we
356
- need to wrap the command in a shell call manually. Some characters will
357
- be interpreted as shell characters without escaping, such as: ``pip
358
- install requests<0.8``. This escapes a good majority of those
359
- characters.
369
+ need to wrap the command in a shell call manually.
370
+
371
+ Some characters will be interpreted as shell characters without
372
+ escaping, such as: ``pip install requests<0.8``. When passing
373
+ ``escape_command=True`` in the init method this escapes a good majority
374
+ of those characters.
360
375
"""
361
376
bash_escape_re = re .compile (
362
377
r"([\t\ \!\"\#\$\&\'\(\)\*\:\;\<\>\?\@"
@@ -365,16 +380,18 @@ def get_wrapped_command(self):
365
380
prefix = ''
366
381
if self .bin_path :
367
382
prefix += 'PATH={}:$PATH ' .format (self .bin_path )
383
+
384
+ command = (
385
+ ' ' .join ([
386
+ bash_escape_re .sub (r'\\\1' , part ) if self .escape_command else part
387
+ for part in self .command
388
+ ])
389
+ )
368
390
return (
369
391
"/bin/sh -c 'cd {cwd} && {prefix}{cmd}'" .format (
370
392
cwd = self .cwd ,
371
393
prefix = prefix ,
372
- cmd = (
373
- ' ' .join ([
374
- bash_escape_re .sub (r'\\\1' , part )
375
- for part in self .command
376
- ])
377
- ),
394
+ cmd = command ,
378
395
)
379
396
)
380
397
0 commit comments