Skip to content

Commit df425e3

Browse files
mgornyphilpep
authored andcommitted
Fix command -v compatibility with dash shell
Fix the `command -v` exit status handling to account for dash being `/bin/sh` (this is e.g. the default on Debian). Unlike bash, dash exits with status 127 if the requested program does not exist -- and testinfra wrongly interpreted that as `command` being unavailable. Instead of attempting to use `command -v` and `which` in order, peform an additional (cached) `command -v command` invocation to determine whether `command` is available. Furthermore, assume that `command -v` can return any non-zero status for command not existing, per POSIX. This fixes exists() and find_command() raising an exception on systems using dash as `/bin/sh` and lacking `which(1)`. Fixes #668
1 parent 351e8c6 commit df425e3

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

testinfra/host.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import testinfra.backend
1616
import testinfra.modules
17+
from testinfra.utils import cached_property
1718

1819

1920
class Host:
@@ -27,26 +28,30 @@ def __init__(self, backend):
2728
def __repr__(self):
2829
return "<testinfra.host.Host {}>".format(self.backend.get_pytest_id())
2930

31+
@cached_property
32+
def has_command_v(self):
33+
"""Return True if `command -v` is available"""
34+
return self.run("command -v command").rc == 0
35+
3036
def exists(self, command):
3137
"""Return True if given command exist in $PATH"""
32-
rc = self.run_expect([0, 1, 127], "command -v %s", command).rc
33-
if rc == 127:
34-
return self.run_expect([0, 1], "which %s", command).rc == 0
38+
if self.has_command_v:
39+
out = self.run("command -v %s", command)
3540
else:
36-
return rc == 0
41+
out = self.run_expect([0, 1], "which %s", command)
42+
return out.rc == 0
3743

3844
def find_command(self, command, extrapaths=("/sbin", "/usr/sbin")):
3945
"""Return path of given command
4046
4147
raise ValueError if command cannot be found
4248
"""
43-
out = self.run_expect([0, 1, 127], "command -v %s", command)
49+
if self.has_command_v:
50+
out = self.run("command -v %s", command)
51+
else:
52+
out = self.run_expect([0, 1], "which %s", command)
4453
if out.rc == 0:
4554
return out.stdout.rstrip("\r\n")
46-
if out.rc == 127:
47-
out = self.run_expect([0, 1], "which %s", command)
48-
if out.rc == 0:
49-
return out.stdout.rstrip("\r\n")
5055
for basedir in extrapaths:
5156
path = os.path.join(basedir, command)
5257
if self.exists(path):

0 commit comments

Comments
 (0)