bundler-bin.sh 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/bin/bash
  2. #
  3. # bundler-bin provides a Bash function that updates your PATH environment
  4. # variable to include a project's ./bin directory if the project's Ruby gem
  5. # dependencies are being managed with bundler.
  6. #
  7. # You can find bundler here: http://github.com/wycats/bundler
  8. #
  9. # Gems that are managed by bundler will install their scripts in a directory
  10. # called <project-root>/bin, and you should run these commands in preference
  11. # to the commands that are installed with your system's gems. If your
  12. # project's bin directory is not in your path it's very easy to forget to
  13. # specify the correct command, which can cause no end of subtle problems.
  14. # bundler-bin fixes this problem by automatically updating your PATH as you
  15. # change directories. It defines a function for updating PATH via the Bash
  16. # PROMPT_COMMAND hook.
  17. #
  18. # Usage:
  19. #
  20. # 1. Copy bundler-bin.sh to ~/.bundler-bin.sh.
  21. # 2. Set PROJECT_ROOT to the parent directory of your bundled projects
  22. # (e.g. ~/code). Why is this needed? See update_bundler_path below.
  23. # 3. Source it from your ~/.bashrc file.
  24. #
  25. # For example:
  26. #
  27. # $ cp bundler-bin/bundler-bin.sh ~/.bundler-bin.sh
  28. # $ echo "PROJECT_ROOT=~/code" >> ~/.bashrc
  29. # $ echo "[ -f ~/.bundler-bin.sh ] && source ~/.bundler-bin.sh" >> ~/.bashrc
  30. #
  31. # That's it... cd into a bundled project and try `echo $PATH` to see if
  32. # it works!
  33. #
  34. # Copyright (c) 2010 Graham Ashton
  35. #
  36. # Permission is hereby granted, free of charge, to any person obtaining a copy
  37. # of this software and associated documentation files (the "Software"), to deal
  38. # in the Software without restriction, including without limitation the rights
  39. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  40. # copies of the Software, and to permit persons to whom the Software is
  41. # furnished to do so, subject to the following conditions:
  42. #
  43. # The above copyright notice and this permission notice shall be included in
  44. # all copies or substantial portions of the Software.
  45. #
  46. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  47. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  48. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  49. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  50. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  51. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  52. # THE SOFTWARE.
  53. ## Variables
  54. PROJECT_ROOT="${PROJECT_ROOT:-HOME/src}"
  55. ## Functions
  56. bundled_project_path()
  57. {
  58. local path="$(pwd)"
  59. while [ $path != "/" ]; do
  60. if [ -e "$path/Gemfile" ]; then
  61. echo $path
  62. return $(true)
  63. fi
  64. path="$(readlink -f $(dirname $path))"
  65. done
  66. return $(false)
  67. }
  68. prepend_project_bin()
  69. {
  70. local current_path="$1"
  71. local project_path=$(bundled_project_path)
  72. if [ -n "$project_path" ]; then
  73. echo -n "$project_path/bin:"
  74. fi
  75. echo "$current_path"
  76. }
  77. within_project_root()
  78. {
  79. local path="$1"
  80. [[ $path =~ "^$PROJECT_ROOT" ]]
  81. }
  82. update_bundler_path()
  83. {
  84. local old_ifs=$IFS
  85. IFS=":"
  86. local dir
  87. local new_path=""
  88. # PATH is reconstructed every time the prompt is redrawn. Directories
  89. # within PROJECT_ROOT are removed, which prevents your PATH from
  90. # collecting lots of unwanted clutter as you cd between projects.
  91. for dir in $PATH; do
  92. if within_project_root $dir; then
  93. continue
  94. fi
  95. if [ -z "$new_path" ]; then
  96. new_path="$dir"
  97. else
  98. new_path="$new_path:$dir"
  99. fi
  100. done
  101. IFS=$old_ifs
  102. export PATH="$(prepend_project_bin $new_path)"
  103. }
  104. PROMPT_COMMAND=update_bundler_path