#!/usr/bin/env bash

__rvm_setup()
{
  # ZSH has 1 based array indexing, bash has 0 based.
  if [[ -n "${ZSH_VERSION:-""}" ]] ; then
    __shell_array_start=1
    # Set clobber for zsh users, for compatibility with bash's append operator ( >> file ) behavior
    setopt | \grep -qs '^noclobber$'
    rvm_zsh_clobber=$?
    setopt clobber
  else
    __shell_array_start=0 # bash array indexes are 0 based.
  fi ; export __shell_array_start
}

__rvm_teardown()
{
  if [[ -n "${ZSH_VERSION:-""}" ]] ; then

    if [[ ${rvm_zsh_clobber:-0} -eq 0 ]] ; then

      setopt noclobber

    fi

    unset rvm_zsh_clobber

  else
    : # currently we are not doing any option setting for bash.
  fi
  # Ruby strings are scoped to their action.
  # Hence, we ensure we remove them at in
  # the cleanup phase.

  # Clean up after CC switch
  if [[ ${rvm_clang_flag:-0} -gt 0 ]] ; then

    if [[ -n "${rvm_prior_cc:-""}" ]] ; then

      export CC="$rvm_prior_cc"

    else

      unset CC

    fi

  fi

  unset rvm_ruby_strings rvm_head_flag rvm_prior_cc next_token rvm_bin_path rvm_error_message rvm_gems_cache_path rvm_gems_path rvm_gemset_name rvm_interactive_flag rvm_man_path rvm_parse_break rvm_rc_files rvm_ruby_binary rvm_ruby_gem_home rvm_ruby_gem_path rvm_ruby_home rvm_ruby_interpreter rvm_ruby_irbrc rvm_ruby_log_path rvm_ruby_major_version rvm_ruby_minor_version rvm_ruby_package_name rvm_ruby_patch_level rvm_ruby_release_version rvm_ruby_repo_url rvm_ruby_repo_branch rvm_ruby_revision rvm_ruby_selected_flag rvm_ruby_tag rvm_ruby_version rvm_selfcontained rvm_token rvm_ruby_load_path rvm_path_flag rvm_ruby_require rvm_action

  [[ ${rvm_dump_environment_flag:-0} -eq 1 ]] && __rvm_dump_environment

  return 0
}

# Dump the current environment to a file.
__rvm_dump_environment()
{
  # Note: This assumes that there is a ','
  local dump_environment_file dump_environment_type rvm_dump_environment_flag

  dump_environment_file="${rvm_dump_environment_flag/,*/}"

  dump_environment_type="${rvm_dump_environment_flag/*,/}"

  if [[ -n "$dump_environment_file" && -n "$dump_environment_type" ]]; then

    if [[ "$dump_environment_type" == "atheis"* && -f "$dump_environment_file" ]] ; then
      # TODO: Query Darcy about the ln.
      \rm -f "$dump_environment_file" \
        && ln -s /dev/null "$dump_environment_file" >/dev/null 2>&1

    else
      "$rvm_path/scripts/environment-convertor" "$dump_environment_type" \
        "$(__rvm_environment_identifier)" > "$dump_environment_file"
      if [[ "$?" -gt 0 && -f "$dump_environment_file" ]] ; then
        \rm -f "$dump_environment_file"
      fi
    fi
  fi

  return 0
}

# Return a list of directories under a given base path.
# Derived from rvm_ruby_string.
__rvm_ruby_string_paths_under()
{
  local path part parts

  path="${1%/}" # Strip off any trailing slash

  parts=(${rvm_ruby_string//-/ }) # Strip white space.

  echo "$path"

  for part in "${parts[@]}" ; do

    path="$path/$part"

    echo "$path"

  done

  return 0
}

# Query the rvm key-value database for a specific key
# Allow overrides from user specifications in $rvm_path/config/user
__rvm_db()
{
  local value key variable

  key=${1:-""}
  variable=${2:-""}

  if [[ -f "$rvm_path/config/user" ]] ; then
    value="$("$rvm_path/scripts/db" "$rvm_path/config/user" "$key")"
  fi

  if [[ -z "$value" ]] ; then
    value="$("$rvm_path/scripts/db" "$rvm_path/config/db" "$key")"
  fi

  if [[ -n "$value" ]] ; then
    if [[ -z "$variable" ]] ; then
      echo $value
    else
      eval "$variable='$value'"
    fi
  fi

  return 0
}

is_a_function() { type $1 | head -n 1 | \grep -q "function" ; }

__rvm_quote_args()
{
  local quoted_string=""

  for quoted_argument in "$@"; do

    if printf "%s" "$quoted_argument" | \grep -vq "^[[:alnum:]]$"; then

      quoted_string="$quoted_string '$(printf "%s" "$quoted_argument" \
        | sed "s/'/\'\\\'\'/g")'"

    else
      quoted_string="$quoted_string $quoted_argument"
    fi
  done

  echo "$quoted_string" | sed -e 's/^ *//g' -e 's/ *$//g'

  return 0
}

__rvm_quote_args_with_shift()
{
  local shift_value="$1"; shift

  while [[ "$shift_value" -gt 0 && $# -gt 0 ]]; do

    shift

    ((shift_value--))

  done

  __rvm_quote_args "$@"

  return 0
}

__rvm_warn_on_rubyopt()
{
  if [[ -n "${RUBYOPT:-""}" ]]; then
    "$rvm_path/scripts"/log "warn" \
      "Please note: You have the RUBYOPT environment variable set and this \
            may interfere with normal rvm operations. We sugges unsetting it."
    return 1
  else
    return 0
  fi
}

__rvm_strings()
{
  local strings ruby_strings

  ruby_strings=($(echo ${rvm_ruby_args:-$rvm_ruby_string}))

  for rvm_ruby_string in "${ruby_strings[@]}" ; do
    strings="$strings $(__rvm_select ; echo $rvm_ruby_string)"
  done

  echo $strings

  return 0
}

# Push an item onto a given array.
__rvm_push()
{
  local array item

  array=$1 ; shift ; item=$2

  # TODO: allow loop over more arguments.
  eval "index=\$((\${#${array}[*]} + $__shell_array_start))"

  eval "${array}[${index}]=${item}"

  return 0
}

# Clean all *duplicate* items out of the path. (keep first occurrence of each)
__rvm_clean_path()
{
  PATH="$(printf "$PATH" | \tr -s ':' '\n' | awk '!($0 in a){a[$0];print}' \
    | \tr -s '\n' ':' | sed 's#:$##')"

  export PATH

  builtin hash -r
}

# Clean all rvm items out of the current working path.
__rvm_remove_rvm_from_path()
{
  PATH="$(printf "$PATH" \
    | awk -v RS=: -v ORS=: "/${rvm_path//\//\/}/ {next} {print}" \
    | sed -e 's#:$##')"

  export PATH

  builtin hash -r
}

# Run a specified command and log it.
__rvm_run()
{
  local name log temp_log_path command message

  name="${1:-""}"
  command="${2:-""}"
  message="${3:-""}"

  if [[ -n "$message" ]] ; then
    "$rvm_path/scripts/log" "info" "$message"
  fi

  if [[ ${rvm_debug_flag:-0} -gt 0 ]] ; then
    "$rvm_path/scripts/log" "debug" "Executing: $command"
  fi

  if [[ -n "${rvm_ruby_string:-""}" ]] ; then
    temp_log_path="${rvm_log_path:-"$rvm_path/log"}/$rvm_ruby_string"
  else
    temp_log_path="${rvm_log_path:-"$rvm_path/log"}"
  fi

  log="$temp_log_path/$name.log"

  if [[ ! -d "${log%\/*}" ]] ; then
    \mkdir -p "${log%\/*}"
  fi

  \touch "$log" "${log/%.log/.error.log}" # for zsh :(

  printf "[$(date +'%Y-%m-%d %H:%M:%S')] $command\n" | \
    \tee "$log" \
    >> "${log/%log/error.log}"

  if [[ ${rvm_niceness:-0} -gt 0 ]] ; then
    command="nice -n $rvm_niceness $command"
  fi

  eval "$command" \
    >>  "$log" \
    2>> "${log/%log/error.log}"

  result=$?

  if [[ $result -gt 0 ]] ; then
    "$rvm_path/scripts/log" "error" \
      "Error running '$command', please check ${log/%log/error.log}"
  fi

  return ${result:-0}
}

# Runs a command in a given env.
__rvm_run_with_env()
{
  local name environment command message log path

  name="${1:-""}"
  environment="${2:-""}"
  command="${3:-""}"
  message="${4:-""}"

  if [[ -z "$environment" ]] ; then
    environment="$(__rvm_environment_identifier)"
  fi

  if [[ -n "$message" ]] ; then
    "$rvm_path/scripts/log" "info" "$message"
  fi

  if [[ ${rvm_debug_flag:-0} -gt 0 ]] ; then
    "$rvm_path/scripts/log" "debug" \
      "Executing: $command in environment $environment"
  fi

  path="${rvm_log_path:-"$rvm_path/log"}/$rvm_ruby_string"

  log="$path/$name.log"

  if [[ ! -d "$path" ]] ; then
    \mkdir -p "$path"
  fi

  \touch "$log" "${log/%.log/.error.log}" # for zsh :(

  printf "[$(date +'%Y-%m-%d %H:%M:%S')] $command # under $environment\n" \
    | tee "${log}" \
    >> "${log/%log/error.log}"

  if [[ ${rvm_niceness:-0} -gt 0 ]] ; then
    command="nice -n $rvm_niceness $command"
  fi

  (
    rvm_ruby_string="$environment"

    __rvm_use

    eval "$command" \
      >> "${log}" \
      2>> "${log/%log/error.log}"
  )

  result=$?

  if [[ $result -gt 0 ]] ; then
    "$rvm_path/scripts/log" "error" \
      "Error running '$command' under $env_name,\
      \nplease check ${log/%log/error.log}"
  fi

  return ${result:-0}
}

__rvm_nuke_rvm_variables()
{
  unset rvm_head_flag $(env | awk -F= '/^rvm_/{print $1" "}')
}

# Unset ruby-specific variables
__rvm_unset_ruby_variables()
{
  # unset rvm_ruby_flag $(env | awk -F= '/^rvm_ruby_/{printf $1" "}')
  unset rvm_ruby_strings rvm_ruby_binary rvm_ruby_gem_home rvm_ruby_gem_path rvm_ruby_home rvm_ruby_interpreter rvm_ruby_irbrc rvm_ruby_log_path rvm_ruby_major_version rvm_ruby_minor_version rvm_ruby_package_name rvm_ruby_patch_level rvm_ruby_release_version rvm_ruby_repo_url rvm_ruby_repo_branch rvm_ruby_revision rvm_ruby_selected_flag rvm_ruby_tag rvm_ruby_version rvm_ruby_load_path rvm_ruby_require rvm_head_flag
}

# TODO: Should be able to...
#   Unset both rvm variables as well as ruby-specific variables
# Preserve gemset if 'rvm_sticky' is set
# (persist gemset unless clear is explicitely called).
__rvm_cleanse_variables()
{
  __rvm_unset_ruby_variables

  if [[ ${rvm_sticky_flag:-0} -eq 1 ]] ; then
    export rvm_gemset_name
  else
    unset rvm_gemset_name
  fi

  unset rvm_action rvm_irbrc_file rvm_command rvm_error_message rvm_force_flag rvm_all_flag rvm_reconfigure_flag rvm_make_flags rvm_bin_flag rvm_import_flag rvm_export_flag rvm_self_flag rvm_gem_flag rvm_rubygems_flag rvm_debug_flag rvm_delete_flag rvm_summary_flag rvm_test_flag _rvm_spec_flag rvm_json_flag rvm_yaml_flag rvm_shebang_flag rvm_env_flag rvm_tail_flag rvm_use_flag rvm_dir_flag rvm_list_flag rvm_empty_flag rvm_file_name rvm_benchmark_flag rvm_clear_flag rvm_name_flag rvm_verbose_flag rvm_user_flag rvm_system_flag rvm_configure_flags rvm_uninstall_flag rvm_install_flag rvm_llvm_flag rvm_ruby_bits rvm_sticky_flag rvm_rvmrc_flag rvm_gems_flag rvm_only_path_flag rvm_docs_flag rvm_ruby_aliases rvm_patch_names rvm_clang_flag rvm_install_arguments rvm_dump_environment_flag rvm_ruby_alias
}

# Returns the first 1.8.7-compatible (partly) ruby for use
# with things like rbx etc which require a ruby be installed.
__rvm_18_compat_ruby()
{
  local rubies ruby_name

  rubies=($( cd "$rvm_path/rubies" ; find . -maxdepth 1 -mindepth 1 -type d ))

  for ruby_name in "${rubies[@]//.\/}"; do

    if [[ ! -L "$rvm_path/rubies/$ruby_name" ]] ; then

      case $ruby_name in
        *1.8.*|rbx-*|ree-*) rubies="$rubies $ruby_name" ;;
      esac
    fi
  done

  echo $rubies | \tr ' ' '\n' | \sort | \tail -n1

  return 0
}

__rvm_ensure_has_18_compat_ruby()
{
  if [[ -z "$(__rvm_18_compat_ruby)" ]]; then
    # TODO: install currently doesn't return the correct status.
    local compat_result=0

    if ! ( "$rvm_path/scripts/manage" install 1.8.7 ); then

      "$rvm_path/scripts/log" "fail" \
        "To proceed rvm requires a 1.8-compatible ruby is installed.\
        \nWe attempted to install 1.8.7 automatically but it failed.\
        \nPlease install it manually (or a compatible alternative) to proceed."

      compat_result=1

    fi
    # unset original_ruby
    # Question: Why *were* we unsetting original_ruby here
    return $compat_result
  fi

  return 0
}

# Cleans up temp folders for a given prefix ($1),
# typically the current process id.
__rvm_cleanup_temp_for()
{
  result=$? # Capture last command status

  [[ -z "${1:-""}" ]] && return 1

  if [[ -d "${rvm_tmp_path:-"$rvm_path/tmp"}/" ]]; then

    \rm -rf "${rvm_tmp_path:-"$rvm_path/tmp"}/$1"* >/dev/null 2>&1

  fi

  return $result
}

__rvm_set_rvmrc()
{
  local flags

  if [[ "$HOME" != "$PWD" ]] ; then

    if [[ ${rvm_verbose_flag:-0} -gt 0 ]] ; then
      flags="use "
    fi

    if [[ -s .rvmrc ]] ; then

      mv .rvmrc .rvmrc.$(date +%m.%d.%Y-%H:%M:%S)

      "$rvm_path/scripts/log" "warning" \
        ".rvmrc is not empty, moving aside to preserve."

    fi

    local identifier=$(__rvm_environment_identifier)

    printf "
if [[ -d \"\${rvm_path:-\$HOME/.rvm}/environments\" \\
  && -s \"\${rvm_path:-\$HOME/.rvm}/environments/$identifier\" ]] ; then
  \\. \"\${rvm_path:-\$HOME/.rvm}/environments/$identifier\"
else
  rvm --create $flags \"$identifier\"
fi
" >> .rvmrc

  else
    "$rvm_path/scripts/log" "error" \
      ".rvmrc cannot be set in your home directory.\
      \nThe home .rvmrc is for global rvm settings only."
  fi
}

__rvm_load_rvmrc()
{
  [[ ${rvm_ignore_rvmrc:-0} -eq 1 ]] && return 0

  for rvmrc in /etc/rvmrc $HOME/.rvmrc ; do

    if [[ -f "$rvmrc" ]] ; then

      if \grep -q '^\s*rvm .*$' $rvmrc ; then

        "$rvm_path/scripts/log" "error" \
          "$rvmrc is for rvm settings only.\
          \nrvm CLI may NOT be called from within $rvmrc.\
          \nSkipping the loading of $rvmrc"

        return 1

      else

        source "$rvmrc"

      fi

    fi

  done

  return 0
}

# Wrap the specified ruby code file in a Benchmark.bmbm block and execute it.
__rvm_benchmark()
{
  local old_rvm_ruby_string

  code="require \"benchmark\" \n \
    Benchmark.bmbm do |benchmark| \n \
    benchmark.report(\"${rvm_ruby_file}\") do \n"

  printf "\n$code" > "${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb"

  unset code

  cat $rvm_ruby_file >> "${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb"

  printf "\n end \nend\n" >> "${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb"

  rvm_ruby_args="${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb"

  rvm_benchmark_flag=1

  rvm_action="ruby"

  if [[ ${rvm_debug_flag:0} -gt 0 ]] ; then

    printf "\n${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb:\n\
      $(cat ${rvm_tmp_path:-"$rvm_path/tmp"}/$$.rb)"

  fi

  # Override ruby string stuff, pass through.

  old_rvm_ruby_string=$rvm_ruby_string

  # TODO: We can likely do this in a subshell in order to
  #       preserve the original environment?

  unset rvm_ruby_string

  export rvm_ruby_strings

  "$rvm_path/scripts/set" "$rvm_action" $rvm_ruby_args ; result=$?

  # Restore the state pre-sets.
  [[ -n "$old_rvm_ruby_string" ]] && rvm_ruby_string=$old_rvm_ruby_string

  return ${result:-0}
}

# Loop over the currently installed rubies and refresh their binscripts.
__rvm_bin_scripts()
{
  for rvm_ruby_binary in "$rvm_path/rubies"/*/bin/ruby ; do

    if [[ -x "$rvm_ruby_binary" ]] ; then

      rvm_ruby_string=$(dirname "$rvm_ruby_binary" \
        | xargs dirname | xargs basename)

      __rvm_select

      __rvm_bin_script

    fi

  done

  return 0
}

# Write the bin/ wrapper script for currently selected ruby.
# TODO: Adjust binscript to be able to handle all rubies,
#       not just the standard interpreteres.
__rvm_bin_script()
{
  "$rvm_path/scripts/wrapper" "$rvm_ruby_string"

  return $?
}

# Add bin path if not present
__rvm_conditionally_add_bin_path()
{
  if printf "${PATH//:/ }" | \grep -vqF "${rvm_bin_path:-"$rvm_path/bin"} " ; then

    case "${rvm_ruby_string:-"system"}" in
      system)
        PATH="$PATH:${rvm_bin_path:-"$rvm_path/bin"}"
        ;;
      *)
        PATH="${rvm_bin_path:-"$rvm_path/bin"}:$PATH"
        ;;
    esac

    builtin hash -r
  fi

  return 0
}

# Reset any rvm gathered information about the system and its state.
# rvm will refresh the stored information the next time it is called after reset.
__rvm_reset()
{
  local flag flags file files config configs variable

  __rvm_remove_rvm_from_path ; __rvm_conditionally_add_bin_path

  export PATH

  builtin hash -r

  flags=( default passenger editor )

  for flag in "${flags[@]}"; do

    \rm -f "${rvm_bin_path:-"$rvm_path/bin"}"/${flag}_*

  done

  for file in system default ; do

    if [[ -f "$rvm_path/${file}" ]] ; then
      \rm -f "$rvm_path/${file}"
    fi

    if [[ -f "$rvm_path/config/${file}" ]] ; then
      \rm -f "$rvm_path/config/${file}"
    fi

    if [[ -f "$rvm_path/environments/${file}" ]] ; then
      \rm -f "$rvm_path/environments/${file}"
    fi

  done

  # Go back to a clean state.
  __rvm_become "system"

  __rvm_unset_ruby_variables

  configs=(system_ruby system_gem_path system_user_gem_path)

  for system_config in "${configs[@]}" ; do

    "$rvm_path/scripts/db" "$rvm_path/config/user" "$system_config" "delete"

  done

  files=(ruby gem rake irb $(cd "${rvm_bin_path:-"$rvm_path/bin"}" ; \
    find . -mindepth 1 -maxdepth 1 -iname 'default*' -type f \
    | sed -e 's#./##g'))

  for file in "${files[@]}"; do

    if [[ -f "${rvm_bin_path:-"$rvm_path/bin"}/$file" ]] ; then

      \rm -f "${rvm_bin_path:-"$rvm_path/bin"}/$file"

    fi

  done

  return 0
}

# Implode removes the entire rvm installation under $rvm_path.
__rvm_implode()
{
  while : ; do

    "$rvm_path/scripts/log" "warn" \
      "Are you SURE you wish for rvm to implode?\
      \nThis will recursively remove $rvm_path ?\
      \n(type 'yes' or 'no')> "

    read response

    if [[ "yes" = "$response" ]] ; then

      if [[ "/" = "$rvm_path" ]] ; then

        "$rvm_path/scripts/log" "error" \
          "remove '/' ?!... Ni!"

      else

        if [[ -d "$rvm_path" ]] ; then

          "$rvm_path/scripts/log" "info" \
            "Hai! Removing $rvm_path"

          \rm -rf "$rvm_path/"

          echo "$rvm_path has been removed."

        else

          "$rvm_path/scripts/log" "info" \
            "It appears that $rvm_path is already non existant."

        fi
      fi
      break

    elif [[ "no" = "$response" ]] ; then

      "$rvm_path/scripts/log" "info" \
        "Cancelling implosion, no harm done :)"
      break

    fi
  done

  return 0
}

# Output the current ruby's rvm source path.
__rvm_source_dir()
{
  if [[ ${rvm_ruby_selected_flag:-0} -eq 0 ]] ; then __rvm_select ; fi

  if [[ -z "$rvm_ruby_src_path" ]] ; then

    "$rvm_path/scripts/log" "fail" \
      "No source directory exists for the default implementation."

  else

    echo "$rvm_ruby_src_path"

  fi

  return 0
}

# Initialize rvm, ensuring that the path and directories are as expected.
__rvm_initialize()
{
  rvm_ruby_load_path="."
  rvm_ruby_require=""

  __rvm_clean_path ; __rvm_conditionally_add_bin_path ; export PATH

  if [[ ! -d "${rvm_tmp_path:-"$rvm_path/tmp"}" ]] ; then
    \mkdir -p "${rvm_tmp_path:-"$rvm_path/tmp"}"
  fi

  return 0
}

# Update rubygems or binscripts based on CLI selection.
__rvm_update()
{
  (
    builtin cd "$rvm_path"

    # TODO:
    if [[ ${rvm_head_flag:-0} -eq 1 || ${rvm_self_flag:-0} -eq 1 \
      || "update" = "${rvm_action:-""}" || ${rvm_update_flag:-0} -eq 1 ]] ; then
    "$rvm_path/scripts/log" "warn" \
        "'rvm update --head' is depreciated, use 'rvm get head' instead"
      "$rvm_path/scripts/get" head
    fi

    if [[ ${rvm_bin_flag:-0} -eq 1 ]] ; then
      __rvm_bin_scripts
    fi

    # Update to the latest rubygems.
    if [[ ${rvm_rubygems_flag:-0} -eq 1 ]] ; then
      "$rvm_path/scripts/rubygems" current
    fi
  )
  unset rvm_update_flag rvm_action rvm_self_flag \
    rvm_ruby_revision rvm_bin_flag rvm_rubygems_flag

  return 0
}

__rvm_reboot()
{
  "$rvm_path/scripts/log" "warn" \
    "Do you wish to reboot rvm?\
    \n('yes', or 'no')> "

  local response="no"

  read response

  if [[ "yes" = "$response" ]] ; then
    builtin cd $rvm_path

    __rvm_reset

    mv "$rvm_path/archives" "$HOME/.archives"

    if [[ "/" = "$rvm_path" ]] ; then
      "$rvm_path/scripts/log" "error" "remove '/' ?!... NO!"
    else
      if [[ -d "$rvm_path" ]] ; then \rm -rf "$rvm_path/" ; fi
    fi

    gem install rvm $rvm_gem_options

    "$rvm_path/scripts/get" latest

    source "$rvm_path/scripts/rvm"
  else
    "$rvm_path/scripts/log" "info" "Carry on then..."
  fi

  return 0
}

# Create the irbrc for the currently selected ruby installation.
__rvm_irbrc()
{
  if [[ -d "$rvm_ruby_home" && ! -s "$rvm_ruby_irbrc" ]] ; then
    \cp "$rvm_path/scripts/irbrc" "$rvm_ruby_irbrc"
  fi
  return $?
}

# Save or restore the rvm's state. This is a toggle action.
# Meant for use before and after an operation that might reset
# the currently selected ruby.
# TODO: Determine if we should a) yank this out or b) actually use it :)
__rvm_state()
{
  if [[ -z "$rvm_state" ]] ; then

    rvm_state="$(__rvm_environment_identifier)"

    rvm_state="${rvm_state:-"system"}"

    if [[ -n "$1" ]]; then

      rvm_ruby_string="$1"

      __rvm_select

      __rvm_use

    fi

  else

    rvm_ruby_string="$rvm_state"

    __rvm_select

    __rvm_use

    unset rvm_state

  fi

  return 0
}

# Output an inspection of selected 'binary' scripts, based on CLI selection.
__rvm_inspect()
{
  for binary in $rvm_ruby_args ; do

    actual_file="$(unset -f gem ; command -v gem )"

    "$rvm_path/scripts/log" "info" "$actual_file:"

    if [[ ${rvm_shebang_flag:-0} -eq 1 ]] ; then
      \head -n 1    < "$actual_file"
    fi

    if [[ ${rvm_env_flag:-0} -eq 1 ]] ; then
      \awk '/ENV/'  < "$actual_file"
    fi

    if [[ ${rvm_path_flag:-0} -eq 1 ]] ; then
      \awk '/PATH/' < "$actual_file"
    fi

    if [[ ${rvm_head_flag:-0} -eq 1 ]] ; then
      \head -n 5    < "$actual_file"
    fi

    if [[ ${rvm_tail_flag:-0} -eq 1 ]] ; then
      \tail -n 5    < "$actual_file"
    fi

    if [[ ${rvm_all_flag:-0} -eq 1 ]] ; then
      \cat $actual_file
    fi

  done

  return 0
}

# Attempt to override the Darwin build settings for rubies
# This should only be used in extreme edge cases that
# will not work via the default way.
__rvm_make_flags()
{
  # This is only an issue with Darwin :/
  if [[ "Darwin" = "$(uname)" ]] ; then
    # \ls /usr/lib/gcc/x86_64-apple-darwin10

    # Set the build & host type
    if [[ "Power Macintosh" = "$(/usr/sbin/sysctl -n hw.machine)" ]] ; then

      : # Do nothing ?

    elif [[ "$(/usr/sbin/sysctl -n hw.cpu64bit_capable)" = 1 \
      || "$(/usr/sbin/sysctl -n hw.optional.x86_64)" = 1 ]] ; then

      #   64 bit capable

      if [[ "-arch x86_64" = "${rvm_archflags:-""}" ]] ; then

        rvm_configure_flags="${rvm_configure_flags} \
          --build=x86_64-apple-darwin$(uname -r) \
          --host=x86_64-apple-darwin$(uname -r)"

      elif [[ "-arch i386" = "${rvm_archflags:-""}" ]] ; then

        rvm_configure_flags="${rvm_configure_flags} \
          --build=i386-apple-darwin$(uname -r) \
          --host=i386-apple-darwin$(uname -r)"

      else

        rvm_archflags="-arch x86_64"

        rvm_configure_flags="${rvm_configure_flags} \
          --build=x86_64-apple-darwin$(uname -r) \
          --host=x86_64-apple-darwin$(uname -r)"

      fi

    fi

    if [[ -n "${rvm_archflags:-""}" ]] ; then

      ARCHFLAGS="$rvm_archflags" ; export ARCHFLAGS

      # Use the latest sdk available.
      if [[ -z "${rvm_sdk:-""}" ]] ; then

        rvm_sdk="$(/usr/bin/basename -a /Developer/SDKs/* \
          | awk '/^M/' | \sort | \tail -n 1)"

      fi

      CFLAGS="${CFLAGS:-"-isysroot /Developer/SDKs/$rvm_sdk $rvm_archflags"}"

      export CFLAGS

      LDFLAGS="${LDFLAGS:-"-Wl,-syslibroot /Developer/SDKs/$rvm_sdk $rvm_archflags"}"

      export LDFLAGS

      # CXXFLAGS="-mmacosx-version-min="$(sw_vers -productVersion \
      # | awk -F'.' '{print $1"."$2}')" -isysroot /Developer/SDKs/$rvm_sdk "
      # export CXXFLAGS

    fi
  fi

  return 0
}

__rvm_mono_env()
{
  DYLD_LIBRARY_PATH="${rvm_usr_path:-"$rvm_path/usr"}/lib:$DYLD_LIBRARY_PATH"
  C_INCLUDE_PATH="${rvm_usr_path:-"$rvm_path/usr"}/include:$C_INCLUDE_PATH"
  ACLOCAL_PATH="${rvm_usr_path:-"$rvm_path/usr"}/share/aclocal"
  ACLOCAL_FLAGS="-I $ACLOCAL_PATH"
  PKG_CONFIG_PATH="${rvm_usr_path:-"$rvm_path/usr"}/lib/pkgconfig:$PKG_CONFIG_PATH"

  export  DYLD_LIBRARY_PATH C_INCLUDE_PATH ACLOCAL_PATH ACLOCAL_FLAGS PKG_CONFIG_PATH

  PATH="${rvm_usr_path:-"$rvm_path/usr"}/bin:$PATH"

  builtin hash -r

  return 0
}

__rvm_become()
{
  local string="$1"

  [[ -n "$string" ]] && rvm_ruby_string="$string"

  { __rvm_ruby_string && __rvm_select && __rvm_use; } > /dev/null 2>&1

  return 0
}

__rvm_ensure_has_environment_files()
{
  local environment_id file_name directory identifier variable value variables

  environment_id="$(__rvm_environment_identifier)"

  file_name="${rvm_path}/environments/$environment_id"

  if [[ ! -s "$file_name" ]] ; then

    \mkdir -p "$rvm_path/environments"

    printf "export PATH=\"${rvm_ruby_gem_home}/bin:${rvm_ruby_global_gems_path}/bin:${rvm_ruby_home}/bin:${rvm_bin_path:-"$rvm_path/bin"}:\$PATH\"\n" \
      > "$file_name"

    for variable in rvm_path RUBY_VERSION GEM_HOME GEM_PATH BUNDLE_PATH \
      MY_RUBY_HOME IRBRC rvm_ruby_string rvm_gemset_name MAGLEV_HOME ; do

      eval "export $variable"
      eval "value=\${${variable}:-""}"

      if [[ -n "$value" ]] ; then

        printf "${variable}='$value'\nexport ${variable}\n" \
          >> "$file_name"

      else

        printf "unset ${variable}\n" \
          >> "$file_name"

      fi

    done
  fi

  # Next, ensure we have default wrapper files. Also, prevent it from recursing.
  if [[ ${rvm_create_default_wrappers:-0} -eq 1 \
    || ! -f "$rvm_path/wrappers/$environment_id/ruby" ]] ; then

    # We need to generate wrappers for both the default gemset and the global gemset.
    for identifier in "$environment_id" "${environment_id//@*/}@global" ; do

      rvm_create_default_wrappers=1

      directory="$rvm_path/wrappers/$identifier"

      if [[ ! -L "$directory" && ! -d "$directory" ]]; then
        \mkdir -p "$directory"

        "$rvm_path/scripts/wrapper" "$identifier" &> /dev/null
      fi

    done

    rvm_create_default_wrappers=0
  fi

  return 0
}

# Strip whitespace and normalize it all.
__rvm_strip()
{
  sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[[:space:]]\{1,\}/ /g'
  return $?
}

__rvm_using_gemset_globalcache()
{
  "$rvm_path/scripts/db" "$rvm_path/config/user" \
    "use_gemset_globalcache" | \grep -q '^true$'
  return $?
}

__rvm_current_gemcache_dir()
{
  if __rvm_using_gemset_globalcache; then
    echo "$rvm_gems_cache_path"
  else
    echo "${rvm_ruby_gem_home:-"$GEM_HOME"}/cache"
  fi
  return 0
}

__rvm_Answer_to_the_Ultimate_Question_of_Life_the_Universe_and_Everything()
{
  for index in {1..750} ; do sleep 0.25 ; echo -n '.' ; done ; printf "%d" 0x2A
  echo
  return 0
}

__rvm_ultimate_question()
{
  printf "
  I do not know the Ultimate Question,
  however I can help you build a more
  powerful Ruby which can compute the
  Ultimate Question.

  "
  return 0
}

__rvm_load_env_file()
{
  local string="$1"
  if [[ -f "$rvm_path/environments/$string" ]]; then
    # Restore the path to it's state minus rvm
    __rvm_remove_rvm_from_path

    # source the environment file
    \. "$rvm_path/environments/$string"

    # clear the PATH cache
    builtin hash -r
  elif [[ -n "$string" ]] ; then
    rvm "$string"
  else
    : # TODO: This should have some error handling in the context.
  fi
  return 0
}

__rvm_md5_for()
{
  if command -v md5 > /dev/null; then
    echo "$1" | md5
  elif command -v md5sum > /dev/null ; then
    echo "$1" | md5sum | awk '{print $1}'
  else
    "$rvm_path/scripts/log" "error" \
      "Neither md5 nor md5sum were found in the PATH"
    return 1
  fi

  return 0
}

__rvm_rvmrc_key()
{
  __rvm_md5_for "$1"
  return $?
}

__rvm_reset_rvmrc_trust()
{
  touch "$rvm_path/config/rvmrcs"
  "$rvm_path/scripts/db" "$rvm_path/config/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "delete" >/dev/null 2>&1
  return $?
}

__rvm_trust_rvmrc()
{
  touch "$rvm_path/config/rvmrcs"
  __rvm_reset_rvmrc_trust "$1"
  "$rvm_path/scripts/db" "$rvm_path/config/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "1" >/dev/null 2>&1
  return $?
}

__rvm_untrust_rvmrc()
{
  touch "$rvm_path/config/rvmrcs"
  __rvm_reset_rvmrc_trust "$1"
  "$rvm_path/scripts/db" "$rvm_path/config/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "0" >/dev/null 2>&1
  return $?
}

__rvm_rvmrc_stored_trust()
{
  touch "$rvm_path/config/rvmrcs"
  "$rvm_path/scripts/db" "$rvm_path/config/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")"
  return $?
}

__rvm_rvmrc_tools()
{
  local rvmrc_action="$1"
  [[ $# -gt 0 ]] && shift
  local rvmrc_path="$(builtin cd "${1:-$PWD}" >/dev/null 2>&1; pwd)/.rvmrc"
  case "$rvmrc_action" in
    reset)
      __rvm_reset_rvmrc_trust "$rvmrc_path"
      echo "Reset trust for $rvmrc_path"
    ;;
    trust)
      __rvm_trust_rvmrc "$rvmrc_path"
      echo "Marked $rvmrc_path as trusted"
    ;;
    untrust)
      __rvm_untrust_rvmrc "$rvmrc_path"
      echo "Marked $rvmrc_path as untrusted"
    ;;
    trusted)
      local trusted_value="$(__rvm_rvmrc_stored_trust "$rvmrc_path")"
      if [[ "$trusted_value" = "1" ]]; then
        echo "The rvmrc at '$rvmrc_path' is currently trusted."
      elif [[ "$trusted_value" = "0" ]]; then
        echo "The rvmrc at '$rvmrc_path' is currently untrusted."
      else
        echo "The trustiworthiness of '$rvmrc_path' is currently unknown."
      fi
    ;;
    load)
      rvm_rvmrc_cwd="" rvm_trust_rvmrcs=1  \
        __rvm_project_rvmrc "$(dirname "$rvmrc_path")"
    ;;
    *)
      echo "Usage: rvm rvmrc {trust,untrust,trusted,load,reset}"
      return 1
    ;;
  esac
  return $?
}

__rvm_check_rvmrc_trustworthiness()
{
  # Trust when they have the flag... of doom!
  [[ -z "$1" || "$rvm_trust_rvmrcs" = "1" ]] && return 0
  value="$(__rvm_rvmrc_stored_trust "$1")"
  if [[ -z "$value" ]] ; then
    __rvm_ask_to_trust "$1"
  else
    [[ "$value" = "1" ]]
  fi
  return $?
}

__rvm_ask_to_trust()
{

  local trusted value

  [[ -n "$rvm_promptless" ]] && return 2

  printf "
  ============================================================
  RVM has encountered a not yet trusted .rvmrc file in the
  current working directory which contains the following code:
  ============================================================

$(cat $1)

  ============================================================
  Trusting an .rvmrc file means that whenever you cd into the
  directory RVM will excecute this .rvmrc script in your shell

  Do you wish to trust this .rvmrc from now on?
  ============================================================
  (y for yes, n for no)"

  # TODO: Eliminate infinite loop possibility.
  while [[ -z "$trusted" ]] ; do

    printf " > "

    read -r response

    value="$(echo "$response" | tr '[[:upper:]]' '[[:lower:]]' | __rvm_strip)"

    if [[ "$response" = "y"* ]]; then
      trusted=1

    elif [[ "$response" = "n"* ]]; then
      trusted=0
    fi
  done

  if [[ ${trusted:-0} -gt 0 ]] ; then

    __rvm_trust_rvmrc "$1"

    return 0

  else
    __rvm_untrust_rvmrc "$1"
    return 1
  fi
}

# Checks the rvmrc for the given directory. Note that if
# argument is passed, it will be used instead of pwd.
__rvm_project_rvmrc()
{
  local cwd

  # Get the first argument or the pwd.
  cwd="${1:-"$PWD"}"

  while : ; do

    if [[ -z "$cwd" || "$HOME" = "$cwd" || "/" = "$cwd" ]] ; then

      if [[ -n "${rvm_rvmrc_cwd:-""}" ]] ; then

        if [[ ${rvm_project_rvmrc_default:-0} -eq 1 ]]; then

          __rvm_load_env_file "default"

        elif [[ -n "${rvm_previous_environment:-""}" ]] ; then

          __rvm_load_env_file "$rvm_previous_environment"

        fi

        unset rvm_rvmrc_cwd rvm_previous_environment

      fi
      break
    else

      if [[ -f "$cwd/.rvmrc" ]] ; then

        if [[ "${rvm_rvmrc_cwd:-""}" != "$cwd" ]] ; then

          __rvm_check_rvmrc_trustworthiness "$cwd/.rvmrc"

          local rvm_trustworthiness_result="$?"

          if  [[ "$rvm_trustworthiness_result" = 0 ]]; then

            rvm_previous_environment="$(__rvm_environment_identifier)"

            rvm_rvmrc_cwd="$cwd"

            source "$cwd/.rvmrc"

            return 0
          else
            return "$rvm_trustworthiness_result"
          fi
        fi
        break

      else
        cwd="$(dirname "$cwd")"
      fi
    fi
  done

  return $?
}

__rvm_record_install()
{

  local recorded_ruby_name rvm_install_record_file rvm_install_command

  [[ -z "$1" ]] && return

  recorded_ruby_name="$("$rvm_path/scripts/tools" strings "$1")"

  rvm_install_record_file="$rvm_path/config/installs"

  rvm_install_command=$(printf "$recorded_ruby_name $rvm_install_arguments\n")

  \touch "$rvm_install_record_file"

  \rm -f "$rvm_install_record_file.tmp"

  \grep -v "^$recorded_ruby_name " < "$rvm_install_record_file" \
    > "$rvm_install_record_file.tmp"

  echo "$rvm_install_command" >> "$rvm_install_record_file.tmp"

  \rm -f "$rvm_install_record_file"

  \mv "$rvm_install_record_file.tmp" "$rvm_install_record_file"

  return 0
}

__rvm_remove_install_record()
{
  local recorded_ruby_name rvm_install_record_file

  recorded_ruby_name="$("$rvm_path/scripts/tools" strings "$1")"

  rvm_install_record_file="$rvm_path/config/installs"

  if [[ -s "$rvm_install_record_file" ]]; then

    \mv "$rvm_install_record_file" "$rvm_install_record_file.tmp"

    \grep -v "^$recorded_ruby_name " < "$rvm_install_record_file.tmp" \
      > "$rvm_install_record_file"

    \rm -f "$rvm_install_record_file.tmp"
  fi

  return 0
}

__rvm_recorded_install_command()
{
  local recorded_ruby_name recorded_ruby_match

  recorded_ruby_name="$("$rvm_path/scripts/tools" strings "$1" \
    | awk -F"${rvm_gemset_separator:-"@"}" '{print $1}')"

  [[ -z "$recorded_ruby_name" ]] && return 1

  recorded_ruby_match="^$recorded_ruby_name "

  if [[ -s "$rvm_path/config/installs" ]] \
    && \grep -q "$recorded_ruby_match" "$rvm_path/config/installs" ; then

    \grep "$recorded_ruby_match" < "$rvm_path/config/installs" | head -n1

  else
    return 1
  fi
  return $?
}

__rvm_environment_identifier()
{
  local path string

  path="${GEM_HOME:-""}"

  string="${path//*gems\//}"
  string="${string//\/*/}"

  printf "${string:-system}"

  return $?
}

__rvm_expand_ruby_string()
{
  local string current_ruby

  string="$1"

  if [[ -z "$string" ]] ; then

    "$rvm_path/scripts/list" strings | tr ' ' "\n"

    return $?

  fi

  case "$string" in

    all)
      "$rvm_path/scripts/list" strings | tr ' ' "\n"
      ;;

    all-gemsets)
      "$rvm_path/scripts/list" gemsets strings
      ;;

    default-with-rvmrc|rvmrc)
      "$rvm_path/scripts/tools" path-identifier "$PWD"
      ;;

    all-rubies|rubies)
      "$rvm_path/scripts/list" rubies strings
      ;;

    current-ruby|gemsets)
      current_ruby="$(__rvm_environment_identifier \
        | awk -F"${rvm_gemset_separator:-"@"}" '{print $string}')"

      rvm_silence_logging=1 "$rvm_path/scripts/gemsets" list \
        | sed "s/^/$current_ruby${rvm_gemset_separator:-"@"}/"
      ;;

    current)
      __rvm_environment_identifier
      ;;

    aliases)
      awk -F= '{print $string}' < "$rvm_path/config/alias"
      ;;

    *)
      echo "$string" | tr "," "\n" | __rvm_strip
      ;;

  esac

  return $?
}

# My concern here is that this will slow things down quite a bit.
# This is originally from
# http://github.com/teleological/rvm/commit/21d6083db3fffc5fa92b9ea8814f3f28f7e48c7f#commitcomment-178001
# Is there a zsh setting to counter the issue instead of this?
__rvm_export_if_set()
{
  local parameter value

  for parameter in $* ; do
    eval "value=\${$parameter:-\"\"}"

    if [[ -n "$value" ]] ; then
      export $parameter
    fi
  done

  return 0
}
