#!/bin/sh
# Set the shebang of installed python scripts to the system default python version.
# Determines the system default version by dereferencing /usr/bin/python.
# Only modifies shebangs that aren't already versioned, so that we don't break
# scripts that were automatically versioned by setuptools, etc.
# Track the number of problems found with unversioned shebangs.
ERRORS_FOUND=0
fail() {
echo "${0##*/} ERROR: $*"
exit 1
}
# If using normal root, avoid changing anything.
if [ -z "$RPM_BUILD_ROOT" ] || [ "$RPM_BUILD_ROOT" = "/" ]; then
exit 0
fi
# If we don't have a python interpreter, avoid changing anything.
python_symlink=${1:-/usr/bin/python}
if [ ! -x "${python_symlink}" ]; then
exit 0
fi
# If we don't have the symlink's target, something is wrong.
default_python="$(readlink -ne ${python_symlink})"
if [ ! -x "${default_python}" ]; then
fail "Target of /usr/bin/python does not exist or is not executable"
fi
default_python_version="$(echo "${default_python}" | grep -Eo '[0-9.]+$')"
if [ -z "${default_python_version}" ]; then
fail "Unable to determine default python version from ${default_python}"
fi
# Remove dots from versions for consistent comparison.
compare_default_python_version="$(echo "${default_python_version}" | tr -d '.')"
# Find files with an unversioned python shebang in the first line.
for pythonfile in $(
find "${RPM_BUILD_ROOT}" -type f \
-exec awk '/^#![[:space:]]*\/(usr\/)?(local\/)?bin\/(env )?python($|[[:space:]])/ {print FILENAME} {nextfile}' \
'{}' +
); do
target_path="${pythonfile#${RPM_BUILD_ROOT}}"
# For each found file, we see if we can tell its intended python version
# by looking at the filename (foo-X.X) or path (/foo/pythonX.X/bar).
path_python_version="$(echo "${target_path}" | grep -Eo '[0-9.]+$')"
if [ -z "${path_python_version}" ]; then
path_python_version="$(echo "${target_path}" | grep -Po '(?<=/python)[0-9.]+' | sort -u)"
fi
# Make sure we didn't get multiple version results from the path.
versions_found="$(echo -e "${path_python_version}" | wc -l)"
if [ "${versions_found}" -gt 1 ]; then
ERRORS_FOUND="$(( ${ERRORS_FOUND} + 1 ))"
echo "Found multiple version strings (${versions_found}: $(echo "${path_python_version}" | xargs))" \
"in path ${target_path} with unversioned shebang." \
"Version the python shebang in your spec file to avoid this."
continue
elif [ -n "${path_python_version}" ]; then
# Remove dots from versions for consistent comparison.
compare_path_python_version="$(echo "${path_python_version}" | tr -d '.')"
# If we determined a python version from the path, and it doesn't match our
# system python version, and the shebang was unversioned, then we fail
# so the package can be fixed.
if [ "${compare_path_python_version}" != "${compare_default_python_version}" ]; then
ERRORS_FOUND="$(( ${ERRORS_FOUND} + 1 ))"
echo "Unexpected version ${path_python_version} (wanted ${default_python_version})" \
"in path ${target_path} with unversioned shebang." \
"Version the python shebang in your spec file to avoid this."
continue
fi
fi
# Make sure we change the file, since the find/awk
# should have only let in files we want to change.
shebang_line_before="$(head -n1 ${pythonfile})"
echo "${0##*/}: Rewriting shebang in \$RPM_BUILD_ROOT${target_path} to use ${default_python##*/}"
sed -i -r -e \
'1s,^#![[:space:]]*/(usr/)?(local/)?bin/(env )?python($|[[:space:]]),#!'${default_python}'\4,' \
"${pythonfile}"
shebang_line_after="$(head -n1 ${pythonfile})"
if [ "${shebang_line_before}" = "${shebang_line_after}" ]; then
ERRORS_FOUND="$(( ${ERRORS_FOUND} + 1 ))"
echo "Expected to modify shebang but could not: ${pythonfile}"
continue
fi
done
if [ "${ERRORS_FOUND}" -ne 0 ]; then
fail "Found ${ERRORS_FOUND} errors related to unversioned shebangs"
fi
@KyuuKazami