Skip to content

Commit e58cb78

Browse files
committed
Allow to not escape the command on get_wrapped_command
1 parent 08b9a35 commit e58cb78

File tree

2 files changed

+31
-20
lines changed

2 files changed

+31
-20
lines changed

readthedocs/doc_builder/backends/sphinx.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,16 +242,17 @@ def venv_sphinx_version(self):
242242
In this case, the output will be ``2.0.0``.
243243
"""
244244

245-
246245
command = [
247246
self.python_env.venv_bin(filename='python'),
248247
'-c'
249-
'"import sphinx;print(sphinx.__version__)"',
248+
'"import sphinx; print(sphinx.__version__)"',
250249
]
250+
251251
cmd_ret = self.run(
252252
*command,
253-
cwd=self.project.checkout_path(self.version.slug),
254253
bin_path=self.python_env.venv_bin(),
254+
cwd=self.project.checkout_path(self.version.slug),
255+
escape_command=False,
255256
)
256257
return cmd_ret.output
257258

readthedocs/doc_builder/environments.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -296,14 +296,20 @@ class DockerBuildCommand(BuildCommand):
296296
Build command to execute in docker container
297297
"""
298298

299-
def run(self):
299+
def __init__(self, *args, escape_command=True, **kwargs):
300300
"""
301-
Execute command in existing Docker container.
301+
Override default to extend behavior.
302302
303-
:param cmd_input: input to pass to command in STDIN
304-
:type cmd_input: str
305-
:param combine_output: combine STDERR into STDOUT
303+
:param escape_command: whether escape special chars the command before
304+
executing it in the container. This should only be disabled on
305+
trusted or internal commands.
306+
:type escape_command: bool
306307
"""
308+
self.escape_command = escape_command
309+
super(DockerBuildCommand, self).__init__(*args, **kwargs)
310+
311+
def run(self):
312+
"""Execute command in existing Docker container."""
307313
log.info(
308314
"Running in container %s: '%s' [%s]",
309315
self.build_env.container_id,
@@ -316,7 +322,7 @@ def run(self):
316322
try:
317323
exec_cmd = client.exec_create(
318324
container=self.build_env.container_id,
319-
cmd=self.get_wrapped_command(),
325+
cmd=self.get_wrapped_command(self.escape_command),
320326
stdout=True,
321327
stderr=True,
322328
)
@@ -352,13 +358,15 @@ def run(self):
352358

353359
def get_wrapped_command(self):
354360
"""
355-
Escape special bash characters in command to wrap in shell.
361+
Wrap command in a shell and optionally escape special bash characters.
356362
357363
In order to set the current working path inside a docker container, we
358-
need to wrap the command in a shell call manually. Some characters will
359-
be interpreted as shell characters without escaping, such as: ``pip
360-
install requests<0.8``. This escapes a good majority of those
361-
characters.
364+
need to wrap the command in a shell call manually.
365+
366+
Some characters will be interpreted as shell characters without
367+
escaping, such as: ``pip install requests<0.8``. When passing
368+
``escape_command=True`` in the init method this escapes a good majority
369+
of those characters.
362370
"""
363371
bash_escape_re = re.compile(
364372
r"([\t\ \!\"\#\$\&\'\(\)\*\:\;\<\>\?\@"
@@ -367,16 +375,18 @@ def get_wrapped_command(self):
367375
prefix = ''
368376
if self.bin_path:
369377
prefix += 'PATH={}:$PATH '.format(self.bin_path)
378+
379+
command = (
380+
' '.join([
381+
bash_escape_re.sub(r'\\\1', part) if self.escape_command else part
382+
for part in self.command
383+
])
384+
)
370385
return (
371386
"/bin/sh -c 'cd {cwd} && {prefix}{cmd}'".format(
372387
cwd=self.cwd,
373388
prefix=prefix,
374-
cmd=(
375-
' '.join([
376-
bash_escape_re.sub(r'\\\1', part)
377-
for part in self.command
378-
])
379-
),
389+
cmd=command,
380390
)
381391
)
382392

0 commit comments

Comments
 (0)