25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

149 satır
3.7 KiB

  1. #!/usr/bin/env bash
  2. # Summary: Rehash pyenv shims (run this after installing executables)
  3. set -e
  4. [ -n "$PYENV_DEBUG" ] && set -x
  5. SHIM_PATH="${PYENV_ROOT}/shims"
  6. PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.pyenv-shim"
  7. # Create the shims directory if it doesn't already exist.
  8. mkdir -p "$SHIM_PATH"
  9. # Ensure only one instance of pyenv-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. { if [ -w "$SHIM_PATH" ]; then
  17. echo "pyenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
  18. else
  19. echo "pyenv: cannot rehash: $SHIM_PATH isn't writable"
  20. fi
  21. exit 1
  22. } >&2
  23. set +o noclobber
  24. # If we were able to obtain a lock, register a trap to clean up the
  25. # prototype shim when the process exits.
  26. trap remove_prototype_shim EXIT
  27. remove_prototype_shim() {
  28. rm -f "$PROTOTYPE_SHIM_PATH"
  29. }
  30. # The prototype shim file is a script that re-execs itself, passing
  31. # its filename and any arguments to `pyenv exec`. This file is
  32. # hard-linked for every executable and then removed. The linking
  33. # technique is fast, uses less disk space than unique files, and also
  34. # serves as a locking mechanism.
  35. create_prototype_shim() {
  36. cat > "$PROTOTYPE_SHIM_PATH" <<SH
  37. #!/usr/bin/env bash
  38. set -e
  39. [ -n "\$PYENV_DEBUG" ] && set -x
  40. program="\${0##*/}"
  41. if [ "\$program" = "python" ]; then
  42. for arg; do
  43. case "\$arg" in
  44. -c* | -- ) break ;;
  45. */* )
  46. if [ -f "\$arg" ]; then
  47. export PYENV_DIR="\${arg%/*}"
  48. break
  49. fi
  50. ;;
  51. esac
  52. done
  53. fi
  54. export PYENV_ROOT="$PYENV_ROOT"
  55. exec "$(command -v pyenv)" exec "\$program" "\$@"
  56. SH
  57. chmod +x "$PROTOTYPE_SHIM_PATH"
  58. }
  59. # If the contents of the prototype shim file differ from the contents
  60. # of the first shim in the shims directory, assume pyenv has been
  61. # upgraded and the existing shims need to be removed.
  62. remove_outdated_shims() {
  63. local shim
  64. for shim in "$SHIM_PATH"/*; do
  65. if ! diff "$PROTOTYPE_SHIM_PATH" "$shim" >/dev/null 2>&1; then
  66. rm -f "$SHIM_PATH"/*
  67. fi
  68. break
  69. done
  70. }
  71. # List basenames of executables for every Python version
  72. list_executable_names() {
  73. local file
  74. for file in "$PYENV_ROOT"/versions/*/bin/*; do
  75. echo "${file##*/}"
  76. done
  77. }
  78. # The basename of each argument passed to `make_shims` will be
  79. # registered for installation as a shim. In this way, plugins may call
  80. # `make_shims` with a glob to register many shims at once.
  81. make_shims() {
  82. local file shim
  83. for file; do
  84. shim="${file##*/}"
  85. register_shim "$shim"
  86. done
  87. }
  88. registered_shims=" "
  89. # Registers the name of a shim to be generated.
  90. register_shim() {
  91. registered_shims="${registered_shims}${1} "
  92. }
  93. # Install all the shims registered via `make_shims` or `register_shim` directly.
  94. install_registered_shims() {
  95. local shim file
  96. for shim in $registered_shims; do
  97. file="${SHIM_PATH}/${shim}"
  98. [ -e "$file" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$file"
  99. done
  100. }
  101. # Once the registered shims have been installed, we make a second pass
  102. # over the contents of the shims directory. Any file that is present
  103. # in the directory but has not been registered as a shim should be
  104. # removed.
  105. remove_stale_shims() {
  106. local shim
  107. for shim in "$SHIM_PATH"/*; do
  108. if [[ "$registered_shims" != *" ${shim##*/} "* ]]; then
  109. rm -f "$shim"
  110. fi
  111. done
  112. }
  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 $(list_executable_names | sort -u)
  119. # Allow plugins to register shims.
  120. OLDIFS="$IFS"
  121. IFS=$'\n' scripts=(`pyenv-hooks rehash`)
  122. IFS="$OLDIFS"
  123. for script in "${scripts[@]}"; do
  124. source "$script"
  125. done
  126. install_registered_shims
  127. remove_stale_shims