- #!/usr/bin/env bash
- # Summary: Rehash rbenv shims (run this after installing executables)
-
- set -e
- [ -n "$RBENV_DEBUG" ] && set -x
-
- SHIM_PATH="${RBENV_ROOT}/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 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 executable 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 > "$PROTOTYPE_SHIM_PATH" <<SH
- #!/usr/bin/env bash
- set -e
- [ -n "\$RBENV_DEBUG" ] && set -x
-
- program="\${0##*/}"
- if [ "\$program" = "ruby" ]; then
- for arg; do
- case "\$arg" in
- -e* | -- ) break ;;
- */* )
- if [ -f "\$arg" ]; then
- export RBENV_DIR="\${arg%/*}"
- break
- fi
- ;;
- esac
- done
- fi
-
- export RBENV_ROOT="$RBENV_ROOT"
- exec "$(command -v rbenv)" exec "\$program" "\$@"
- SH
- chmod +x "$PROTOTYPE_SHIM_PATH"
- }
-
- # If the contents of the prototype shim file differ from the contents
- # of the first shim in the shims directory, assume rbenv has been
- # upgraded and the existing shims need to be removed.
- remove_outdated_shims() {
- for shim in *; do
- if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
- for shim in *; do rm -f "$shim"; done
- fi
- break
- done
- }
-
- # The basename of each argument passed to `make_shims` will be
- # registered for installation as a shim. In this way, plugins may call
- # `make_shims` with a glob to register many shims at once.
- make_shims() {
- local shims="$@"
-
- for file in $shims; do
- local shim="${file##*/}"
- register_shim "$shim"
- done
- }
-
- # Create an empty array for the list of registered shims and an empty
- # string to use as a search index.
- registered_shims=()
- registered_shims_index=""
-
- # We will keep track of shims registered for installation with the
- # global `reigstered_shims` array and with a global search index
- # string. The array will let us iterate over all registered shims. The
- # index string will let us quickly check whether a shim with the given
- # name has been registered or not.
- register_shim() {
- local shim="$@"
- registered_shims["${#registered_shims[@]}"]="$shim"
- registered_shims_index="$registered_shims_index/$shim/"
- }
-
- # To install all the registered shims, we iterate over the
- # `registered_shims` array and create a link if one does not already
- # exist.
- install_registered_shims() {
- local shim
- for shim in "${registered_shims[@]}"; do
- [ -e "$shim" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$shim"
- done
- }
-
- # Once the registered shims have been installed, we make a second pass
- # over the contents of the shims directory. Any file that is present
- # in the directory but has not been registered as a shim should be
- # removed.
- remove_stale_shims() {
- local shim
- for shim in *; do
- if [[ "$registered_shims_index" != *"/$shim/"* ]]; then
- rm -f "$shim"
- fi
- done
- }
-
-
- # Change to the shims directory.
- cd "$SHIM_PATH"
- shopt -s nullglob
-
- # Create the prototype shim, then register shims for all known
- # executables.
- create_prototype_shim
- remove_outdated_shims
- make_shims ../versions/*/bin/*
-
- # Restore the previous working directory.
- cd "$OLDPWD"
-
- # Allow plugins to register shims.
- for script in $(rbenv-hooks rehash); do
- source "$script"
- done
-
- # Change back to the shims directory to install the registered shims
- # and remove stale shims.
- cd "$SHIM_PATH"
- install_registered_shims
- remove_stale_shims
|