mirror of
https://github.com/pyenv/pyenv.git
synced 2024-11-21 20:47:00 -05:00
Atomic rehash
This commit is contained in:
parent
3efdf6a243
commit
dd8a005c7d
1 changed files with 42 additions and 8 deletions
|
@ -1,31 +1,67 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
SHIM_PATH="${HOME}/.rbenv/shims"
|
||||
PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.rbenv-shim"
|
||||
|
||||
# Create the shims directory if it doesn't already exist.
|
||||
mkdir -p "$SHIM_PATH"
|
||||
|
||||
# Ensure only one instance of rbenv-rehash is running at a time by
|
||||
# setting the shell's `noclobber` option and attempting to write to
|
||||
# the prototype shim file. If the file already exists, print a warning
|
||||
# to stderr and exit with a non-zero status.
|
||||
set -o noclobber
|
||||
{ echo > "$PROTOTYPE_SHIM_PATH"
|
||||
} 2>/dev/null ||
|
||||
{ echo "rbenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
|
||||
exit 1
|
||||
} >&2
|
||||
set +o noclobber
|
||||
|
||||
# If we were able to obtain a lock, register a trap to clean up the
|
||||
# prototype shim when the process exits.
|
||||
trap remove_prototype_shim SIGINT SIGTERM EXIT
|
||||
|
||||
remove_prototype_shim() {
|
||||
rm -f "$PROTOTYPE_SHIM_PATH"
|
||||
}
|
||||
|
||||
# The prototype shim file is a script that re-execs itself, passing
|
||||
# its filename and any arguments to `rbenv exec`. This file is
|
||||
# hard-linked for every binary and then removed. The linking technique
|
||||
# is fast, uses less disk space than unique files, and also serves as
|
||||
# a locking mechanism.
|
||||
create_prototype_shim() {
|
||||
cat > .rbenv-shim <<SH
|
||||
cat > "$PROTOTYPE_SHIM_PATH" <<SH
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
exec rbenv exec "\${0##*/}" "\$@"
|
||||
SH
|
||||
chmod +x .rbenv-shim
|
||||
chmod +x "$PROTOTYPE_SHIM_PATH"
|
||||
}
|
||||
|
||||
# Make shims by iterating over every filename argument and creating a
|
||||
# hard link from the prototype shim to a file of the same name in the
|
||||
# shims directory, if one does not already exist.
|
||||
make_shims() {
|
||||
local glob="$@"
|
||||
|
||||
for file in $glob; do
|
||||
local shim="${file##*/}"
|
||||
[ -e "$shim" ] || ln -f .rbenv-shim "$shim"
|
||||
[ -e "$shim" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$shim"
|
||||
done
|
||||
}
|
||||
|
||||
mkdir -p "${HOME}/.rbenv/shims"
|
||||
cd "${HOME}/.rbenv/shims"
|
||||
rm -f *
|
||||
# Empty out the shims directory and make it the working directory.
|
||||
rm -f "$SHIM_PATH"/*
|
||||
cd "$SHIM_PATH"
|
||||
|
||||
# Create the prototype shim, then make shims for all known binaries.
|
||||
create_prototype_shim
|
||||
make_shims ../versions/*/bin/*
|
||||
|
||||
# Find and run any plugins that might want to make shims too.
|
||||
shopt -s nullglob
|
||||
RBENV_REHASH_PLUGINS=(/etc/rbenv.d/rehash/*.bash ${HOME}/.rbenv/rbenv.d/rehash/*.bash)
|
||||
shopt -u nullglob
|
||||
|
@ -33,5 +69,3 @@ shopt -u nullglob
|
|||
for script in ${RBENV_REHASH_PLUGINS[@]}; do
|
||||
source $script
|
||||
done
|
||||
|
||||
rm -f .rbenv-shim
|
||||
|
|
Loading…
Reference in a new issue