You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 line
4.1 KiB

13 年之前
13 年之前
13 年之前
13 年之前
13 年之前
13 年之前
13 年之前
13 年之前
13 年之前
  1. #!/usr/bin/env bash
  2. # Summary: Rehash rbenv shims (run this after installing executables)
  3. set -e
  4. [ -n "$RBENV_DEBUG" ] && set -x
  5. SHIM_PATH="${RBENV_ROOT}/shims"
  6. PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.rbenv-shim"
  7. # Create the shims directory if it doesn't already exist.
  8. mkdir -p "$SHIM_PATH"
  9. # Ensure only one instance of rbenv-rehash is running at a time by
  10. # setting the shell's `noclobber` option and attempting to write to
  11. # the prototype shim file. If the file already exists, print a warning
  12. # to stderr and exit with a non-zero status.
  13. set -o noclobber
  14. { echo > "$PROTOTYPE_SHIM_PATH"
  15. } 2>/dev/null ||
  16. { echo "rbenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
  17. exit 1
  18. } >&2
  19. set +o noclobber
  20. # If we were able to obtain a lock, register a trap to clean up the
  21. # prototype shim when the process exits.
  22. trap remove_prototype_shim EXIT
  23. remove_prototype_shim() {
  24. rm -f "$PROTOTYPE_SHIM_PATH"
  25. }
  26. # The prototype shim file is a script that re-execs itself, passing
  27. # its filename and any arguments to `rbenv exec`. This file is
  28. # hard-linked for every executable and then removed. The linking
  29. # technique is fast, uses less disk space than unique files, and also
  30. # serves as a locking mechanism.
  31. create_prototype_shim() {
  32. cat > "$PROTOTYPE_SHIM_PATH" <<SH
  33. #!/usr/bin/env bash
  34. set -e
  35. [ -n "\$RBENV_DEBUG" ] && set -x
  36. program="\${0##*/}"
  37. if [ "\$program" = "ruby" ]; then
  38. for arg; do
  39. case "\$arg" in
  40. -e* | -- ) break ;;
  41. */* )
  42. if [ -f "\$arg" ]; then
  43. export RBENV_DIR="\${arg%/*}"
  44. break
  45. fi
  46. ;;
  47. esac
  48. done
  49. fi
  50. export RBENV_ROOT="$RBENV_ROOT"
  51. exec "$(command -v rbenv)" exec "\$program" "\$@"
  52. SH
  53. chmod +x "$PROTOTYPE_SHIM_PATH"
  54. }
  55. # If the contents of the prototype shim file differ from the contents
  56. # of the first shim in the shims directory, assume rbenv has been
  57. # upgraded and the existing shims need to be removed.
  58. remove_outdated_shims() {
  59. for shim in *; do
  60. if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
  61. for shim in *; do rm -f "$shim"; done
  62. fi
  63. break
  64. done
  65. }
  66. # The basename of each argument passed to `make_shims` will be
  67. # registered for installation as a shim. In this way, plugins may call
  68. # `make_shims` with a glob to register many shims at once.
  69. make_shims() {
  70. local shims="$@"
  71. for file in $shims; do
  72. local shim="${file##*/}"
  73. register_shim "$shim"
  74. done
  75. }
  76. # Create an empty array for the list of registered shims and an empty
  77. # string to use as a search index.
  78. registered_shims=()
  79. registered_shims_index=""
  80. # We will keep track of shims registered for installation with the
  81. # global `reigstered_shims` array and with a global search index
  82. # string. The array will let us iterate over all registered shims. The
  83. # index string will let us quickly check whether a shim with the given
  84. # name has been registered or not.
  85. register_shim() {
  86. local shim="$@"
  87. registered_shims["${#registered_shims[@]}"]="$shim"
  88. registered_shims_index="$registered_shims_index/$shim/"
  89. }
  90. # To install all the registered shims, we iterate over the
  91. # `registered_shims` array and create a link if one does not already
  92. # exist.
  93. install_registered_shims() {
  94. local shim
  95. for shim in "${registered_shims[@]}"; do
  96. [ -e "$shim" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$shim"
  97. done
  98. }
  99. # Once the registered shims have been installed, we make a second pass
  100. # over the contents of the shims directory. Any file that is present
  101. # in the directory but has not been registered as a shim should be
  102. # removed.
  103. remove_stale_shims() {
  104. local shim
  105. for shim in *; do
  106. if [[ "$registered_shims_index" != *"/$shim/"* ]]; then
  107. rm -f "$shim"
  108. fi
  109. done
  110. }
  111. # Change to the shims directory.
  112. cd "$SHIM_PATH"
  113. shopt -s nullglob
  114. # Create the prototype shim, then register shims for all known
  115. # executables.
  116. create_prototype_shim
  117. remove_outdated_shims
  118. make_shims ../versions/*/bin/*
  119. # Restore the previous working directory.
  120. cd "$OLDPWD"
  121. # Allow plugins to register shims.
  122. for script in $(rbenv-hooks rehash); do
  123. source "$script"
  124. done
  125. # Change back to the shims directory to install the registered shims
  126. # and remove stale shims.
  127. cd "$SHIM_PATH"
  128. install_registered_shims
  129. remove_stale_shims