From 967a6d11ae8710a671b49a88ba0d32490f249a80 Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Tue, 11 Jul 2023 09:15:01 +0200 Subject: [PATCH] Default run.shell to /bin/sh `/bin/bash` is not availabe on some popular distributions, for example NixOS. Defaulting to the more conservative `/bin/sh` improves portability. --- invoke/config.py | 10 +++++----- invoke/runners.py | 2 +- tests/config.py | 2 +- tests/runners.py | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/invoke/config.py b/invoke/config.py index 54f780be..a8044b65 100644 --- a/invoke/config.py +++ b/invoke/config.py @@ -440,16 +440,16 @@ def global_defaults() -> Dict[str, Any]: .. versionadded:: 1.0 """ - # On Windows, which won't have /bin/bash, check for a set COMSPEC env + # On Windows, which won't have /bin/sh, check for a set COMSPEC env # var (https://en.wikipedia.org/wiki/COMSPEC) or fallback to an # unqualified cmd.exe otherwise. if WINDOWS: shell = os.environ.get("COMSPEC", "cmd.exe") - # Else, assume Unix, most distros of which have /bin/bash available. - # TODO: consider an automatic fallback to /bin/sh for systems lacking - # /bin/bash; however users may configure run.shell quite easily, so... + # Else, assume a POSIX compatible Unix, where /bin/sh is mandated by + # the standard. Users on more exotic platforms are expected to configure + # run.shell manually. else: - shell = "/bin/bash" + shell = "/bin/sh" return { # TODO: we document 'debug' but it's not truly implemented outside diff --git a/invoke/runners.py b/invoke/runners.py index f1c888f4..411d29fc 100644 --- a/invoke/runners.py +++ b/invoke/runners.py @@ -335,7 +335,7 @@ def run(self, command: str, **kwargs: Any) -> Optional["Result"]: Default: ``False``. :param str shell: - Which shell binary to use. Default: ``/bin/bash`` (on Unix; + Which shell binary to use. Default: ``/bin/sh`` (on Unix; ``COMSPEC`` or ``cmd.exe`` on Windows.) :param timeout: diff --git a/tests/config.py b/tests/config.py index 34a070c0..bce3fa6b 100644 --- a/tests/config.py +++ b/tests/config.py @@ -107,7 +107,7 @@ def basic_settings(self): "out_stream": None, "pty": False, "replace_env": False, - "shell": "/bin/bash", + "shell": "/bin/sh", "warn": False, "watchers": [], }, diff --git a/tests/runners.py b/tests/runners.py index 94c63d8b..0d84c8e4 100644 --- a/tests/runners.py +++ b/tests/runners.py @@ -81,7 +81,7 @@ def _expect_platform_shell(shell): if WINDOWS: assert shell.endswith("cmd.exe") else: - assert shell == "/bin/bash" + assert shell == "/bin/sh" def _make_tcattrs(cc_is_ints=True, echo=False): @@ -218,10 +218,10 @@ def kwarg_beats_config(self): assert runner.run(_, pty=True).pty is True class shell: - def defaults_to_bash_or_cmdexe_when_pty_True(self): + def defaults_to_sh_or_cmdexe_when_pty_True(self): _expect_platform_shell(self._run(_, pty=True).shell) - def defaults_to_bash_or_cmdexe_when_pty_False(self): + def defaults_to_sh_or_cmdexe_when_pty_False(self): _expect_platform_shell(self._run(_, pty=False).shell) def may_be_overridden(self): @@ -1651,14 +1651,14 @@ def overridden_fallback_affects_result_pty_value(self): class shell: @mock_pty(insert_os=True) - def defaults_to_bash_or_cmdexe_when_pty_True(self, mock_os): + def defaults_to_sh_or_cmdexe_when_pty_True(self, mock_os): # NOTE: yea, windows can't run pty is true, but this is really # testing config behavior, so...meh self._run(_, pty=True) _expect_platform_shell(mock_os.execve.call_args_list[0][0][0]) @mock_subprocess(insert_Popen=True) - def defaults_to_bash_or_cmdexe_when_pty_False(self, mock_Popen): + def defaults_to_sh_or_cmdexe_when_pty_False(self, mock_Popen): self._run(_, pty=False) _expect_platform_shell( mock_Popen.call_args_list[0][1]["executable"]