patchShebangs: rewrite ".../bin/env python" to /nix/store/.../python
Currently "/usr/bin/env python" is rewritten to "/nix/store/.../env python". That doesn't really improve anything because the interpreter still have to be located in $PATH at runtime. The result is that many nix package expressions do .../bin/env fixup themselves. Instead of everyone having to do this patching locally, add the functionality to the standard environment patchShebangs function so that everyone can benefit.
This commit is contained in:
parent
29c11ef8a5
commit
7bf209db50
@ -655,20 +655,57 @@ patchShebangs() {
|
|||||||
# Rewrite all script interpreter file names (`#! /path') under the
|
# Rewrite all script interpreter file names (`#! /path') under the
|
||||||
# specified directory tree to paths found in $PATH. E.g.,
|
# specified directory tree to paths found in $PATH. E.g.,
|
||||||
# /bin/sh will be rewritten to /nix/store/<hash>-some-bash/bin/sh.
|
# /bin/sh will be rewritten to /nix/store/<hash>-some-bash/bin/sh.
|
||||||
|
# /usr/bin/env gets special treatment so that ".../bin/env python" is
|
||||||
|
# rewritten to /nix/store/<hash>/bin/python.
|
||||||
# Interpreters that are already in the store are left untouched.
|
# Interpreters that are already in the store are left untouched.
|
||||||
header "patching script interpreter paths"
|
header "patching script interpreter paths"
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local f
|
local f
|
||||||
|
local oldPath
|
||||||
|
local newPath
|
||||||
|
local arg0
|
||||||
|
local args
|
||||||
|
local oldInterpreterLine
|
||||||
|
local newInterpreterLine
|
||||||
|
|
||||||
for f in $(find "$dir" -type f -perm +0100); do
|
for f in $(find "$dir" -type f -perm +0100); do
|
||||||
local oldPath=$(sed -ne '1 s,^#![ ]*\([^ ]*\).*$,\1,p' "$f")
|
if [ $(head -1 "$f" | head -c +2) != '#!' ]; then
|
||||||
|
# missing shebang => not a script
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
oldInterpreterLine=$(head -1 "$f" | tail -c +3)
|
||||||
|
read oldPath arg0 args <<< "$oldInterpreterLine"
|
||||||
|
|
||||||
|
if $(echo "$oldPath" | grep -q "/bin/env$"); then
|
||||||
|
# Check for unsupported 'env' functionality:
|
||||||
|
# - options: something starting with a '-'
|
||||||
|
# - environment variables: foo=bar
|
||||||
|
if $(echo "$arg0" | grep -q -- "^-.*\|.*=.*"); then
|
||||||
|
echo "unsupported interpreter directive \"$oldInterpreterLine\" (set dontPatchShebangs=1 and handle shebang patching yourself)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
newPath="$(command -v "$arg0")"
|
||||||
|
else
|
||||||
|
if [ "$oldPath" = "" ]; then
|
||||||
|
# If no interpreter is specified linux will use /bin/sh. Set
|
||||||
|
# oldpath="/bin/sh" so that we get /nix/store/.../sh.
|
||||||
|
oldPath="/bin/sh"
|
||||||
|
fi
|
||||||
|
newPath="$(command -v "$(basename "$oldPath")")"
|
||||||
|
args="$arg0 $args"
|
||||||
|
fi
|
||||||
|
|
||||||
|
newInterpreterLine="$newPath $args"
|
||||||
|
|
||||||
if [ -n "$oldPath" -a "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then
|
if [ -n "$oldPath" -a "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then
|
||||||
local newPath=$(type -P $(basename $oldPath) || true)
|
|
||||||
if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
|
if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
|
||||||
echo "$f: interpreter changed from $oldPath to $newPath"
|
echo "$f: interpreter directive changed from \"$oldInterpreterLine\" to \"$newInterpreterLine\""
|
||||||
sed -i -e "1 s,$oldPath,$newPath," "$f"
|
sed -i -e "1 s|.*|#\!$newInterpreterLine|" "$f"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
stopNest
|
stopNest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user