fix: use "command -v" to find interpreter in $PATH (#3150)
In some environments, `which` doesn't work correctly under Bazel, while
`command -v` does.
I think the difference is that `command` is a shell builtin (and POSIX
compliant), whereas `which` is not:
```
$ sh -c 'builtin command -v python3'
/usr/bin/python3
$ sh -c 'builtin which python3'
sh: line 1: builtin: which: not a shell builtin
```
While `command -v` performs fewer checks under the hood, it is more
portable.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 422e399..08991c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -101,6 +101,8 @@
`# gazelle:python_resolve_sibling_imports true`
* (pypi) Show overridden index URL of packages when downloading metadata have failed.
([#2985](https://github.com/bazel-contrib/rules_python/issues/2985)).
+* (toolchains) use "command -v" to find interpreter in `$PATH`
+ ([#3150](https://github.com/bazel-contrib/rules_python/pull/3150)).
{#v0-0-0-added}
### Added
diff --git a/python/private/runtime_env_toolchain_interpreter.sh b/python/private/runtime_env_toolchain_interpreter.sh
index dd4d648..c78cfe1 100755
--- a/python/private/runtime_env_toolchain_interpreter.sh
+++ b/python/private/runtime_env_toolchain_interpreter.sh
@@ -17,16 +17,14 @@
exit 1
}
-# We use `which` to locate the Python interpreter command on PATH. `command -v`
-# is another option, but it doesn't check whether the file it finds has the
-# executable bit.
+# We use `command -v` to locate the Python interpreter command on PATH.
#
# A tricky situation happens when this wrapper is invoked as part of running a
# tool, e.g. passing a py_binary target to `ctx.actions.run()`. Bazel will unset
# the PATH variable. Then the shell will see there's no PATH and initialize its
-# own, sometimes without exporting it. This causes `which` to fail and this
+# own, sometimes without exporting it. This causes `command -v` to fail and this
# script to think there's no Python interpreter installed. To avoid this we
-# explicitly pass PATH to each `which` invocation. We can't just export PATH
+# explicitly pass PATH to each `command -v` invocation. We can't just export PATH
# because that would modify the environment seen by the final user Python
# program.
#
@@ -37,9 +35,9 @@
# https://github.com/bazelbuild/bazel/issues/8415
# Try the "python3" command name first, then fall back on "python".
-PYTHON_BIN="$(PATH="$PATH" which python3 2> /dev/null)"
+PYTHON_BIN="$(PATH="$PATH" command -v python3 2> /dev/null)"
if [ -z "${PYTHON_BIN:-}" ]; then
- PYTHON_BIN="$(PATH="$PATH" which python 2>/dev/null)"
+ PYTHON_BIN="$(PATH="$PATH" command -v python 2>/dev/null)"
fi
if [ -z "${PYTHON_BIN:-}" ]; then
die "Neither 'python3' nor 'python' were found on the target \