utility 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #!/usr/bin/env bash
  2. source "${rvm_scripts_path}/functions/utility_logging"
  3. source "${rvm_scripts_path}/functions/utility_package"
  4. source "${rvm_scripts_path}/functions/utility_rubygems"
  5. source "${rvm_scripts_path}/functions/utility_system"
  6. __rvm_strings()
  7. {
  8. \typeset strings ruby_strings
  9. ruby_strings=($(echo ${rvm_ruby_args:-$rvm_ruby_string}))
  10. for rvm_ruby_string in "${ruby_strings[@]}" ; do
  11. strings="$strings $(__rvm_select ; echo $rvm_ruby_string)"
  12. done
  13. echo $strings
  14. return 0
  15. }
  16. # Return a list of directories under a given base path.
  17. # Derived from rvm_ruby_string.
  18. __rvm_ruby_string_paths_under()
  19. {
  20. \typeset __search_path part parts IFS
  21. IFS=" "
  22. __search_path="${1%/}" # Strip off any trailing slash
  23. if [[ -n "${ZSH_VERSION:-}" ]]
  24. then parts=(${=rvm_ruby_string//-/ })
  25. else parts=(${rvm_ruby_string//-/ }) # Strip white space.
  26. fi
  27. echo "$__search_path"
  28. for part in "${parts[@]}"
  29. do
  30. __search_path="$__search_path/$part"
  31. echo "$__search_path"
  32. done
  33. }
  34. # Strip whitespace and normalize it all.
  35. __rvm_strip()
  36. {
  37. __rvm_sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[[:space:]]\{1,\}/ /g'
  38. return $?
  39. }
  40. # remove all entries from $PATH starting with $1
  41. __rvm_remove_from_path()
  42. {
  43. export PATH
  44. \typeset _value
  45. _value="${1//+(\/)//}"
  46. # Guard to prevent removal of the entire path
  47. # https://github.com/rvm/rvm/issues/4759
  48. if
  49. [[ $_value == "/*" ]]
  50. then
  51. return
  52. fi
  53. # remove multiple slashes https://github.com/rvm/rvm/issues/1364
  54. while [[ "$PATH" == *"//"* ]] ; do PATH="${PATH/\/\///}" ; done
  55. while [[ "$PATH" == *"/:"* ]] ; do PATH="${PATH/\/:/:}" ; done
  56. if
  57. __rvm_string_match ":$PATH:" "*:${_value}:*"
  58. then
  59. \typeset -a _path
  60. _path=()
  61. __rvm_custom_separated_array _path : "${PATH}"
  62. __rvm_remove_from_array _path "${_value}" "${_path[@]}"
  63. __rvm_join_array PATH : _path
  64. fi
  65. }
  66. __rvm_add_to_path()
  67. {
  68. export PATH
  69. if (( $# != 2 )) || [[ -z "$2" ]]
  70. then
  71. rvm_error "__rvm_add_to_path requires two parameters"
  72. return 1
  73. fi
  74. __rvm_remove_from_path "$2"
  75. case "$1" in
  76. prepend) PATH="$2:$PATH" ;;
  77. append) PATH="$PATH:$2" ;;
  78. #*) anything else will just remove it from PATH - not adding back
  79. esac
  80. if
  81. [[ -n "${rvm_user_path_prefix:-}" ]]
  82. then
  83. __rvm_remove_from_path "${rvm_user_path_prefix}"
  84. PATH="${rvm_user_path_prefix}:$PATH"
  85. fi
  86. builtin hash -r
  87. }
  88. rvm_is_a_shell_function()
  89. {
  90. \typeset _message
  91. if
  92. (( ${rvm_is_not_a_shell_function:-0} )) &&
  93. [[ "${1:-}" != "no_warning" ]]
  94. then
  95. if rvm_pretty_print stderr
  96. then rvm_log "" # newline when error is shown to user
  97. fi
  98. if rvm_pretty_print stderr
  99. then rvm_error "${rvm_notify_clr:-}RVM is not a function, selecting rubies with '${rvm_error_clr:-}rvm use ...${rvm_notify_clr:-}' will not work."
  100. else rvm_error "RVM is not a function, selecting rubies with 'rvm use ...' will not work."
  101. fi
  102. if
  103. [[ -n "${SUDO_USER:-}" ]]
  104. then
  105. rvm_warn '
  106. Please avoid using "sudo" in front of "rvm".
  107. RVM knows when to use "sudo" and will use it only when it is necessary.
  108. '
  109. else
  110. rvm_warn '
  111. You need to change your terminal emulator preferences to allow login shell.
  112. Sometimes it is required to use `/bin/bash --login` as the command.
  113. Please visit https://rvm.io/integration/gnome-terminal/ for an example.
  114. '
  115. fi
  116. fi
  117. return ${rvm_is_not_a_shell_function:-0}
  118. }
  119. __rvm_version_sort()
  120. {
  121. \command \awk -F'[.-]' -v OFS=. '{ # split on "." and "-", merge back with "."
  122. original=$0 # save original to preserve it before the line is changed
  123. for (n=1; n<10; n++) { # iterate through max 9 components of version
  124. $n=tolower($n) # ignore case for sorting
  125. if ($n == "") $n="0" # treat non existing parts as 0
  126. if ($n ~ /^p[0-9]/) $n=substr($n, 2) # old ruby -p notation
  127. if ($n ~ /^[0-9](rc|b)/) $n=substr($n, 1, 1)". "substr($n, 2) # old jruby 0RC1 notation
  128. if (n == 1 && $n ~ /^[0-9]/) $n="zzz."$n # first group must be a string
  129. if (n > 1 && $n ~ /^[a-z]/) $n=" "$n # names go before numbers thanks to space
  130. }
  131. print $0"\t"original # print the transformed version and original separated by \t
  132. # so we can extract original after sorting
  133. }' \
  134. | LC_ALL=C \sort -t. -k 1,1d -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n \
  135. | \awk -F'\t' '{print $2}'
  136. }
  137. __rvm_version_compare()
  138. {
  139. \typeset first
  140. # first is the lower version number
  141. first="$( \command \printf "%b" "$1\n$3\n" | __rvm_version_sort | \command \head -n1 )"
  142. case "$2" in
  143. (-eq|==|=)
  144. [[ "$1" == "$3" ]] || return $?
  145. ;;
  146. (-ne|!=)
  147. [[ "$1" != "$3" ]] || return $?
  148. ;;
  149. (-gt|\>)
  150. if [[ "$first" == "head" ]]
  151. then [[ "$first" == "$1" && "$1" != "$3" ]] || return $?
  152. else [[ "$first" == "$3" && "$1" != "$3" ]] || return $?
  153. fi
  154. ;;
  155. (-ge|\>=)
  156. if [[ "$first" == "head" ]]
  157. then [[ "$first" == "$1" || "$1" == "$3" ]] || return $?
  158. else [[ "$first" == "$3" || "$1" == "$3" ]] || return $?
  159. fi
  160. ;;
  161. (-lt|\<)
  162. if [[ "$first" == "head" ]]
  163. then [[ "$first" == "$3" && "$1" != "$3" ]] || return $?
  164. else [[ "$first" == "$1" && "$1" != "$3" ]] || return $?
  165. fi
  166. ;;
  167. (-le|\<=)
  168. if [[ "$first" == "head" ]]
  169. then [[ "$first" == "$3" || "$1" == "$3" ]] || return $?
  170. else [[ "$first" == "$1" || "$1" == "$3" ]] || return $?
  171. fi
  172. ;;
  173. (*)
  174. rvm_error "Unsupported operator '$2'."
  175. return 1
  176. ;;
  177. esac
  178. return 0
  179. }
  180. # parse comma separated string into an array
  181. # Ex. __rvm_custom_separated_array strings - ruby_string
  182. # adds all elements from `ruby_string` to `strings` array
  183. __rvm_custom_separated_array()
  184. {
  185. \typeset IFS
  186. IFS=$2
  187. if [[ -n "${ZSH_VERSION:-}" ]]
  188. then eval "$1+=( \${=3} )"
  189. else eval "$1+=( \$3 )"
  190. fi
  191. }
  192. __rvm_remove_from_array()
  193. {
  194. \typeset _array_name _iterator _search
  195. \typeset -a _temp_array
  196. _array_name="$1"
  197. _search="$2"
  198. shift 2
  199. _temp_array=()
  200. for _iterator
  201. do
  202. __rvm_string_match "$_iterator" "$_search" || _temp_array+=( "$_iterator" )
  203. done
  204. eval "$_array_name=( \"\${_temp_array[@]}\" )"
  205. }
  206. __rvm_join_array()
  207. {
  208. \typeset IFS
  209. IFS="$2"
  210. eval "$1=\"\${$3[*]}\""
  211. }
  212. # take a variable and cut it only to contain only count fields from separator
  213. # Usage: __rvm_take_n variable count separator
  214. __rvm_take_n()
  215. {
  216. \typeset IFS __temp_counter
  217. \typeset -a __temp_arr1 __temp_arr2
  218. IFS=$3
  219. if [[ -n "${ZSH_VERSION:-}" ]]
  220. then eval "__temp_arr1=( \${=$1} )"
  221. else eval "__temp_arr1=( \$$1 )"
  222. fi
  223. __temp_counter=0
  224. __temp_arr2=()
  225. while (( __temp_counter < $2 ))
  226. do __temp_arr2+=( "${__temp_arr1[__array_start+__temp_counter++]}" )
  227. done
  228. eval "$1=\"\${__temp_arr2[*]}\""
  229. }
  230. __rvm_add_once()
  231. {
  232. \typeset IFS
  233. IFS="|"
  234. eval "[[ \"${IFS}\${${1}[*]}${IFS}\" == \*\"${IFS}\${2}${IFS}\"\* ]] || ${1}+=( \"\${2}\" )"
  235. }
  236. __rvm_find_first_file()
  237. {
  238. \typeset _first_file _variable_first_file __file_enum
  239. _first_file=""
  240. _variable_first_file="$1"
  241. shift
  242. for __file_enum in "$@"
  243. do
  244. if
  245. [[ -f "$__file_enum" ]]
  246. then
  247. eval "$_variable_first_file=\"\$__file_enum\""
  248. return 0
  249. fi
  250. done
  251. eval "$_variable_first_file=\"\""
  252. return 1
  253. }
  254. file_exists_at_url_command()
  255. {
  256. __rvm_curl --silent --insecure --location --list-only \
  257. --max-time ${rvm_max_time_flag:-5} --head "$@" 2>&1 |
  258. __rvm_grep -E 'HTTP/[0-9\.]+ 200' >/dev/null 2>&1 ||
  259. {
  260. \typeset __ret=$?
  261. case ${__ret} in
  262. (28)
  263. rvm_warn "RVM was not able to check existence of remote files with timeout of ${rvm_max_time_flag:-3} seconds
  264. you can increase the timeout by setting it in ~/.rvmrc => rvm_max_time_flag=10"
  265. ;;
  266. esac
  267. return ${__ret}
  268. }
  269. }
  270. file_exists_at_url()
  271. (
  272. if
  273. [[ -n "${1:-}" ]]
  274. then
  275. unset curl
  276. file_exists_at_url_command "$1" --insecure ||
  277. {
  278. \typeset __ret=$?
  279. case ${__ret} in
  280. (60)
  281. # detect double --insecure and avoid duplication, see:
  282. # https://github.com/rvm/rvm/issues/2640#issuecomment-35669722
  283. file_exists_at_url_command "$1" || return $?
  284. return 0
  285. ;;
  286. (*)
  287. # anything else then 60 just return it
  288. return ${__ret}
  289. ;;
  290. esac
  291. }
  292. else
  293. rvm_warn "Warning: URL was not passed to file_exists_at_url"
  294. return 1
  295. fi
  296. )
  297. __rvm_try_sudo()
  298. (
  299. \typeset -a command_to_run
  300. \typeset sudo_path sbin_path missing_paths
  301. command_to_run=( "$@" )
  302. (( UID == 0 )) ||
  303. case "$rvm_autolibs_flag_number" in
  304. (0)
  305. rvm_debug "Running '$*' would require sudo."
  306. return 0
  307. ;;
  308. (1)
  309. rvm_warn "Running '$*' would require sudo."
  310. return 0
  311. ;;
  312. (2)
  313. rvm_requiremnts_fail error "Running '$*' would require sudo."
  314. return 1
  315. ;;
  316. (*)
  317. if
  318. is_a_function __rvm_sudo
  319. then
  320. missing_paths=""
  321. for sbin_path in /sbin /usr/sbin /usr/local/sbin
  322. do
  323. if [[ -d "${sbin_path}" ]] && [[ ":$PATH:" != *":${sbin_path}:"* ]]
  324. then missing_paths+=":${sbin_path}"
  325. fi
  326. done
  327. if [[ -n "${missing_paths}" ]]
  328. then command_to_run=( /usr/bin/env PATH="${PATH}${missing_paths}" "${command_to_run[@]}" )
  329. fi
  330. command_to_run=( __rvm_sudo -p "%p password required for '$*': " "${command_to_run[@]}" )
  331. else
  332. rvm_error "Running '$*' would require sudo, but 'sudo' is not found!"
  333. return 1
  334. fi
  335. ;;
  336. esac
  337. "${command_to_run[@]}" || return $?
  338. )
  339. __rvm_run_wrapper()
  340. ( # ( = subprocess
  341. file="$1"
  342. action="${2:-}"
  343. shift 2
  344. rubies_string="${1:-}"
  345. args=( $@ )
  346. source "$rvm_scripts_path"/base
  347. source "$rvm_scripts_path"/$file
  348. )
  349. __rvm_calculate_space_free()
  350. {
  351. # OpenBSD does not have 'df -m' param
  352. __free_space="$( \command \df -Pk "$1" | __rvm_awk 'BEGIN{x=4} /Free/{x=3} $3=="Avail"{x=3} END{print $x}' )"
  353. if [[ "${__free_space}" == *M ]]
  354. then __free_space="${__free_space%M}" # some systems ignore -k and print M
  355. else __free_space="$(( __free_space / 1024 ))"
  356. fi
  357. }
  358. __rvm_calculate_space_used()
  359. {
  360. __used_space="$( \command \du -msc "$@" | __rvm_awk 'END {print $1}' )"
  361. __used_space="${__used_space%M}"
  362. }
  363. __rvm_require()
  364. {
  365. [[ -f "$1" ]] && source "$1"
  366. }