diff options
Diffstat (limited to 'brp-mangle-shebangs')
-rwxr-xr-x | brp-mangle-shebangs | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/brp-mangle-shebangs b/brp-mangle-shebangs new file mode 100755 index 0000000..67a1a7d --- /dev/null +++ b/brp-mangle-shebangs @@ -0,0 +1,142 @@ +#!/bin/bash -eu + +# If using normal root, avoid changing anything. +if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then + exit 0 +fi + +exclude_files="" +exclude_files_from="" +exclude_shebangs="" +exclude_shebangs_from="" + +usage() { + local verbose=$1 && shift + local outfile=$1 && shift + local status=$1 && shift + + ( + echo 'usage: brp-mangle-shebangs [--files <regexp>] [--files-from <file>] [--shebangs <regexp>] [--shebangs-from <file>]' + if [ "${verbose}" == "yes" ]; then + echo ' --files: extended regexp of files to ignore' + echo ' --files-from: file containing a list of extended regexps of files to ignore' + echo ' --shebangs: extended regexp of shebangs to ignore' + echo ' --shebangs-from: file containing a list of extended regexps of shebangs to ignore' + fi + ) >>${outfile} + exit ${status} +} + +while [ $# -gt 0 ] ; do + case "$1" in + --files) + exclude_files="${2}" + shift + ;; + --files=*) + exclude_files="${1##--files=}" + ;; + --files-from) + exclude_files_from="${2}" + shift + ;; + --files-from=*) + exclude_files_from="${1##--files-from=}" + ;; + --shebangs) + exclude_shebangs="${2}" + shift + ;; + --shebangs=*) + exclude_shebangs="${1##--shebangs=}" + ;; + --shebangs-from) + exclude_shebangs_from="${2}" + shift + ;; + --shebangs-from=*) + exclude_shebangs_from="${1##--shebangs-from=}" + ;; + --help|--usage|"-?"|-h) + usage yes /dev/stdout 0 + ;; + *) + echo "Unknown option \"${1}\"" 1>&2 + usage no /dev/stderr 1 + ;; + esac + shift +done + +cd "$RPM_BUILD_ROOT" + +trim() { + printf '%s' "$*" +} + +fail=0 +while IFS= read -r -d $'\0' f; do + file -N --mime-type "$f" | grep -q -P ".+(?=: text/)" || continue + + # Remove the dot + path="${f#.}" + + if [ -n "$exclude_files" ]; then + echo "$path" | grep -q -E "$exclude_files" && continue + fi + if [ -n "$exclude_files_from" ]; then + echo "$path" | grep -q -E -f "$exclude_files_from" && continue + fi + + ts=$(stat -c %y "$f") + + read shebang_line < "$f" || : + orig_shebang=$(trim $(echo "$shebang_line" | grep -Po "#!\K.*" || echo)) + shebang="$orig_shebang" + if [ -n "$exclude_shebangs" ]; then + echo "$shebang" | grep -q -E "$exclude_shebangs" && continue + fi + if [ -n "$exclude_shebangs_from" ]; then + echo "$shebang" | grep -q -E -f "$exclude_shebangs_from" && continue + fi + + if [ -z "$shebang" ]; then + echo >&2 "*** WARNING: $f is executable but has empty or no shebang, removing executable bit" + chmod -x "$f" + touch -d "$ts" "$f" + continue + elif [ -n "${shebang##/*}" ]; then + echo >&2 "*** ERROR: $f has shebang which doesn't start with '/' ($shebang)" + fail=1 + continue + fi + + if ! { echo "$shebang" | grep -q -P "^/(?:usr/)?(?:bin|sbin)/"; }; then + continue + fi + + # Replace "special" env shebang: + # /whatsoever/env /whatever/foo → /whatever/foo + shebang=$(echo "$shebang" | sed -r -e 's@^(.+)/env /(.+)$@/\2@') + # /whatsoever/env foo → /whatsoever/foo + shebang=$(echo "$shebang" | sed -r -e 's@^(.+/)env (.+)$@\1\2@') + + # If the shebang now starts with /bin, change it to /usr/bin + # https://bugzilla.redhat.com/show_bug.cgi?id=1581757 + shebang=$(echo "$shebang" | sed -r -e 's@^/bin/@/usr/bin/@') + + # Replace ambiguous python with python2 + py_shebang=$(echo "$shebang" | sed -r -e 's@/usr/bin/python(\s|$)@/usr/bin/python2\1@') + + if [ "$shebang" != "$py_shebang" ]; then + echo >&2 "*** ERROR: ambiguous python shebang in $path: #!$orig_shebang. Change it to python3 (or python2) explicitly." + fail=1 + elif [ "#!$shebang" != "#!$orig_shebang" ]; then + sed -i -e "1c #!$shebang" "$f" + echo "mangling shebang in $path from $orig_shebang to #!$shebang" + fi + + touch -d "$ts" "$f" +done < <(find -executable -type f -print0) + +exit $fail |