gimme 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #!/bin/bash
  2. # A meta micro manager for the masses.
  3. # USAGE:
  4. # gimme [-f|--force] stuff
  5. # gimme [-l|--list|--installed]
  6. # gimme [--old|--outdated]
  7. # gimme [-v|--verbose|--debug]
  8. # gimme [-h|--help|help]
  9. ###############################################################################
  10. [ "$GIMME_URL" ] || export GIMME_URL="https://github.com/KylePDavis/gimme"
  11. [ "$GIMME_DIR" ] || export GIMME_DIR="$HOME/.gimme"
  12. [ "$GIMME_GIMMES_DIR" ] || export GIMME_GIMMES_DIR="$GIMME_DIR/gimmes"
  13. [ "$GIMME_LINK" ] || export GIMME_LINK="$HOME/bin/gimme"
  14. [ "$GIMME_LINK_DIR" ] || export GIMME_LINK_DIR=$(dirname "$GIMME_LINK")
  15. [ "$GIMMES" ] || export GIMMES=""
  16. [ "$INIT_GIMMES" ] || export INIT_GIMMES=""
  17. [ "$OS" ] || export OS=$(uname -s)
  18. [ "$DEBUG" ] || export DEBUG=
  19. [ "$FORCE" ] || export FORCE=
  20. ###############################################################################
  21. ! [[ "$DEBUG" ]] || set -x
  22. has() {
  23. if [[ "$FORCE" ]] && echo " $INIT_GIMMES " | grep -q " $1 "; then
  24. false
  25. else
  26. command -v "$1" >/dev/null
  27. fi
  28. }
  29. gimme_pkg() {
  30. if [[ "$OS" = "Darwin" ]]; then
  31. if ! has brew; then
  32. has curl || gimme_pkg curl
  33. [[ -d "$HOME/homebrew" ]] || (mkdir "$HOME/homebrew" 2>/dev/null && curl -L "https://github.com/Homebrew/brew/tarball/master" | tar xz --strip 1 -C "$HOME/homebrew" && "$HOME/homebrew/bin/brew" update)
  34. fi
  35. if [[ "$1" ]]; then
  36. if brew cat --cask "$1" &>/dev/null; then
  37. if brew list --cask "$1" &>/dev/null; then
  38. if [[ "$FORCE" ]]; then
  39. brew reinstall --cask "$@"
  40. else
  41. echo "# SKIPPED: $GIMME (force reinstall/upgrade via: gimme -f $GIMME)"
  42. fi
  43. else
  44. brew install --cask "$@"
  45. fi
  46. elif brew cat "$1" &>/dev/null; then
  47. if brew list "$1" &>/dev/null; then
  48. if [[ "$FORCE" ]]; then
  49. brew upgrade "$@" || echo "# WARN: forced upgrade failed (it may already be up to date)"
  50. else
  51. echo "# SKIPPED: $GIMME (force upgrade via: gimme -f $GIMME)"
  52. fi
  53. else
  54. brew install "$@"
  55. fi
  56. else
  57. brew search "$1"
  58. fi
  59. fi
  60. elif [[ "$1" ]]; then
  61. if has apt-get; then
  62. sudo apt-get -y install "$@"
  63. elif has yum; then
  64. sudo yum -y install "$@"
  65. elif has apk; then
  66. sudo apk add "$@"
  67. else
  68. echo "ERROR: This OS is not currently supported. See the website for details: $GIMME_URL"
  69. fi
  70. fi
  71. }
  72. if [[ "$ZSH_VERSION" ]]; then
  73. setopt posixargzero
  74. fi
  75. if [[ "$0" =~ -?(z|ba)sh ]]; then # sourced or piped
  76. if [[ "$ZSH_EVAL_CONTEXT" =~ :file$ || "${BASH_SOURCE[*]}" ]]; then # sourced
  77. # if 'gimme' is not Add gimme to the PATH if not already found
  78. if ! [[ "$PATH" == *"$GIMME_DIR"* ]]; then
  79. export PATH="$PATH:$GIMME_DIR"
  80. fi
  81. # setup autocompletion for gimmes
  82. _gimme_completely() {
  83. if [[ "$2" = -* ]]; then
  84. COMPREPLY=( $(compgen -W "-v --verbose --debug --force --version --help -l --list --installed --old --outdated" -- "$2") )
  85. else
  86. COMPREPLY=( $(cd "$GIMME_GIMMES_DIR"; find . -path "./$2*" \! -type d \! -name '.*' \! -name '_*' | cut -c3- ) )
  87. fi
  88. }
  89. complete -F _gimme_completely gimme
  90. else # piped
  91. set -o errexit -o pipefail
  92. # gimmes/gcc: inlined for curl-based installs
  93. if [[ "$OS" = "Darwin" ]]; then
  94. if ! "xcode-select" --version &>/dev/null; then
  95. echo "Try again after installing the Xcode command-line tools by running: xcode-select --install"
  96. exit 1
  97. fi
  98. if ! xcodebuild -help &>/dev/null; then
  99. echo "Try again after agreeing to the Xcode license by running: sudo xcodebuild -license"
  100. exit 1
  101. fi
  102. else
  103. has gcc || gimme_pkg build-essential || gimme_pkg gcc
  104. fi
  105. # gimmes/git: inlined for curl-based installs
  106. has git || gimme_pkg git
  107. if ! [[ -d "$GIMME_DIR" ]]; then
  108. echo "Installing '$GIMME_DIR/gimme' ..."
  109. mkdir -p "$GIMME_DIR"
  110. git clone "$GIMME_URL" "$GIMME_DIR"
  111. mkdir -p "$(dirname "$GIMME_LINK")"
  112. ln -sf "$GIMME_DIR/gimme" "$GIMME_LINK"
  113. echo "Installed '$GIMME_DIR/gimme'"
  114. echo "You can use this script directly or include in your shell's startup profile script to enable tab completion."
  115. echo "Example usage 'gimme stuff' or 'gimme dev/stuff' or even 'gimme gimme'!"
  116. else
  117. echo "Updating '$GIMME_DIR/gimme' ..."
  118. cd "$GIMME_DIR"
  119. OLD_REV="$(git rev-parse HEAD)"
  120. git pull
  121. NEW_REV="$(git rev-parse HEAD)"
  122. if [[ "$NEW_REV" != "$OLD_REV" ]]; then
  123. echo "Updates to '$GIMME_DIR/gimme' ..."
  124. git log --oneline "$OLD_REV.."
  125. fi
  126. echo "Updated '$GIMME_DIR/gimme'"
  127. fi
  128. fi
  129. else # normal usage
  130. set -o errexit -o pipefail
  131. export -f has gimme_pkg
  132. [[ "$INIT_GIMMES" ]] || export INIT_GIMMES="$@"
  133. DID_GIMME=
  134. for GIMME; do
  135. case "$GIMME" in
  136. -v|--verbose|--debug)
  137. DEBUG=1
  138. continue
  139. ;;
  140. -f|--force)
  141. FORCE=1
  142. continue
  143. ;;
  144. --version)
  145. echo "Version:"
  146. git log -1
  147. exit 0
  148. ;;
  149. -h|--help|"")
  150. sed -n -e'/^#[[:space:]]/p' -e'/^###/q' "$0"
  151. echo "# GIMMES:"
  152. echo $(cd "$GIMME_GIMMES_DIR"; find . -type f -perm +1 | sed -e's/^..//' -e'/^_/d' | sort)
  153. exit 0
  154. ;;
  155. -l|--list|--installed)
  156. echo "# BREW (cask):"
  157. brew cask list
  158. echo
  159. echo "# BREW:"
  160. brew list
  161. echo
  162. echo "# NPM:"
  163. npm -g ls --depth 0
  164. echo
  165. echo "# PIP:"
  166. pip list --format=columns
  167. exit 0
  168. ;;
  169. --old|--outdated)
  170. echo "# BREW (cask):"
  171. brew cask outdated
  172. echo
  173. echo "# BREW:"
  174. brew outdated
  175. echo
  176. echo "# NPM:"
  177. npm outdated -g --depth 0
  178. echo
  179. echo "# PIP:"
  180. pip list --format=columns --outdated
  181. exit 0
  182. ;;
  183. -*)
  184. echo "# ERROR: Unknown option: $GIMME"
  185. continue
  186. ;;
  187. esac
  188. ! [[ "$DEBUG" ]] || set -x
  189. echo "# WANT: $GIMME"
  190. ! [[ "$GIMMES" == *" $GIMME "* ]] || exit 0
  191. export GIMMES+=" $GIMME " GIMME
  192. P="$GIMME_GIMMES_DIR/$GIMME"
  193. if ! [[ -f "$P" ]]; then
  194. # find _default handler
  195. while P=$(dirname "$P") && [[ "$P" = "$GIMME_GIMMES_DIR"* ]]; do
  196. if [[ -f "$P/_default" ]]; then
  197. P="$P/_default"
  198. break;
  199. fi
  200. done
  201. # no default
  202. if ! [[ "$P" = "$GIMME_GIMMES_DIR"* ]]; then
  203. echo "# ERROR: Unable to find $GIMME_GIMMES_DIR/_default handler"
  204. exit 1
  205. fi
  206. fi
  207. if [[ -x "$P" ]]; then
  208. DID_GIMME=1
  209. [[ "$PATH" = "$LINK_DIR"* ]] || export PATH="$LINK_DIR:$PATH"
  210. if (if [[ "$DEBUG" ]]; then bash -x "$P"; else bash "$P"; fi); then
  211. echo "# DONE: $GIMME"
  212. else
  213. OUCH=$?
  214. echo "# FAIL: Error for gimme \"$GIMME\" (EXIT_CODE=$OUCH)"
  215. exit $OUCH
  216. fi
  217. else
  218. echo "# WARN: the gimme \"$GIMME\" was SKIPPED because \"$P\" is not marked executable!"
  219. fi
  220. done
  221. [[ "$DID_GIMME" ]] || echo "# WARN: nothing to do... try: gimme --help"
  222. fi