#!/bin/bash rvm_author="Wayne E. Seguin" rvm_version="0.0.1" rvm_updated="2009.08.23" # # License: See LICENSE # # # Functions # function usage { cat <<-Usage Usage: $0 Action [Implementation] [Options] Action: install - Install a ruby version, default is from source use - Switch to using a specific ruby versio (new login shell) path - Set path for current ruby info - Show information for current ruby gemdir - Switch to gem directory for installation (new login shell) gemdup - Clone source implementation version gems to currently used version setup - Place rvm to in default path (~/.bin/ && .profile) * usage - Show this usage information Implementation: * ruby - MRI/YARV Ruby (The Standard) jruby - jRuby ree - Ruby Enterprise Edition rubinius - Rubinius (NI) leopard - Leopard's system Ruby ( Mac OS X only ) default - Resets to the default system ruby Options: -v|--version - Ruby Package Version, defaults to 'latest' -l|--level - Patch level for the specified Ruby version -p|--prefix - Package and source directory prefix, with trailing slash! Default is a users home directory and /usr/local/ for root -m|--manager - Package Manager to use, one of: {port,aptitude,apt-get,emerge,yum,pacman} -d|--debug - Toggle debug mode on Notes: * Defaults are denoted with a * prefix. TODO: (in order) * Rubinius (not in first revisions) * Shell detection instead of simply assuming bash (not in first revisions) Usage } # Logging functions based on level function log { echo -e "\n $* \e[0m\n" ; } function debug { log "\e[4;34m $*" ; } function info { log "\e[0;32m $*" ; } function warn { log "\e[0;33m $*" ; } function error { log "\e[0;31m $*" ; } function fail { log "\e[0;31m $*" ; } function ruby-gi { gem install -q --no-rdoc --no-ri $* ; } function ruby-info { full_version=$(ruby -v) ruby_implementation=$(echo "$full_version" | awk '{print $1}') ruby_version=$(echo "$full_version" | awk '{print $2}') ruby_patchlevel=$(echo "$full_version" | sed 's/^.*(//' | sed 's/).*$//') ruby_date=$(echo "$full_version" | sed 's/^.*(\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*$/\1/') ruby_platform=$(echo "$full_version" | sed 's/^.*\[//' | sed 's/\].*$//') cat <<-Info ruby: implementation: "$ruby_implementation" version: "$ruby_version" date: "$ruby_date" platform: "$ruby_platform" patchlevel: "$ruby_patchlevel" gem_home: "${GEM_HOME-not set}" ruby_home: "${ruby_home-not set}" full_version: "$full_version" Info } function ruby-install-source { case "${version-$1}" in 1.9|1.9.1) major="1.9" ; minor="1" ; patchlevel="${2-243}" ;; 1.8|1.8.6) major="1.8" ; minor="6" ; patchlevel="${2-369}" ;; 1.8.7) major="1.8" ; minor="7" ; patchlevel="${2-174}" ;; *) fail "Ruby version '$version' is unknown." esac package_name="ruby-$major.$minor-p$patchlevel" url="ftp://ftp.ruby-lang.org/pub/ruby/$major/$package_name.tar.gz" pushd $source_path if [ -d $package_name ] ; then cd $package_name else if [ ! -f "$package_name.tar.gz" ] ; then $curl $url ; fi tar xzf $package_name.tar.gz && cd $package_name/ fi ./configure --prefix=$install_path/$package_name --enable-shared && make && make install chmod +x $install_path/$package_name/bin/* popd } function ruby-install { case "$implementation" in leopard) # no-op system_type=`uname` if [ "$system_type" = "Darwin" ] ; then echo "Leopard ruby is not installable via rvm." else fail "leopard ruby is the default ruby installed on Mac OS X (Darwin), you are on: $system_type" fi ;; ree) version=${version-1.8.6} patchlevel=${patchlevel-20090610} package_name="ruby-enterprise-$version-$patchlevel" url="http://rubyforge.org/frs/download.php/58677/$package_name.tar.gz" pushd $source_path if [ -d $package_name ] ; then cd $package_name else if [ ! -f "$package_name.tar.gz" ] ; then $curl $url ; fi tar xzf $package_name.tar.gz && cd $package_name/ fi cd ruby-enterprise-$version-$patchlevel && ./installer -a $install_path/ruby-enterprise-$version-$patchlevel --dont-install-useful-gems popd chmod +x $install_path/$package_name/bin/* ;; jruby) version=${version-1.3.1} # 1.2.0, 1.3.1 patchlevel="" # No patchlevel for jRuby package_name="$implementation-bin-$version" package_dir="$implementation-$version" url="http://dist.codehaus.org/$implementation/$version/$package_name.zip" pushd $source_path if [ -d $package_name ] ; then cd $package_name else if [ ! -f "$package_name.zip" ] ; then $curl $url ; fi jar xf $package_name.zip && cd $package_name/ fi mkdir -p $install_path/$package_dir/bin/ for binary in jruby jgem jirb ; do ln -sf $source_path/$package_dir/bin/$binary $source_path/$package_dir/bin/${binary#j} done rsync -ag $source_path/$package_dir/ $install_path/$package_dir/ cd $source_path/$package_dir/tool/nailgun && make popd chmod +x $install_path/$package_dir/bin/* ruby-gi jruby-openssl ;; ruby) version=${version-1.8.6} ruby-install-source $version ${patchlevel-$3} ;; *) fail "Ruby implementation '$implementation' is not known." esac ruby-gi rake MY_RUBY_HOME=ruby_home export ruby_home GEM_HOME PATH MY_RUBY_HOME } function ruby-use { case "$implementation" in default) rm -f ~/.rvm/current unset ruby_home unset GEM_HOME ;; leopard) ruby_home="/System/Library/Frameworks/Ruby.framework/Versions/Current/usr" GEM_HOME="$HOME/.gem/ruby/1.8" ;; jruby) version="${version-1.3.1}" if [ "$version" = "1.2.0" -o "$version" = "1.3.1" ] ; then ruby_home="$install_path/jruby-$version" GEM_HOME="$HOME/.gem/jruby/1.8" alias ruby_ng="jruby --ng" alias ruby_ng_server="jruby --ng-server" else fail "Unknown jRuby version: $version" fi ;; ree) version=${version-1.8.6} if [ "$version" = "1.8.6" ] ; then patchlevel="${3-20090610}" ruby_home="$install_path/ruby-enterprise-$version-$patchlevel" GEM_HOME="$HOME/.gem/ruby-enterprise/1.8" else fail "Unknown Ruby Enterprise Edition version: $version" fi ;; ruby) if [ "$version" = "1.8.6" ] ; then patchlevel="${patchlevel-369}" ruby_home="$install_path/ruby-1.8.6-p$patchlevel" GEM_HOME="$HOME/.gem/ruby/1.8" elif [ "$version" = "1.8.7" ] ; then patchlevel="${patchlevel-174}" ruby_home="$install_path/ruby-1.8.7-p$patchlevel" GEM_HOME="$HOME/.gem/ruby/1.8" elif [ "$version" = "1.9.1" -o "$version" = "1.9" ] ; then patchlevel="${patchlevel-243}" ruby_home="$install_path/ruby-1.9.1-p$patchlevel" GEM_HOME="$HOME/.gem/ruby/1.9.1" else fail "Unknown ruby version: $version" fi ;; *) fail "Ruby implementation '$implementation' is not known." esac if [ ! "$implementation" = "default" ] ; then MY_RUBY_HOME=$ruby_home RUBY_VERSION="$($ruby_home/bin/ruby -v | sed 's/^\(.*\) (.*$/\1/')" export GEM_HOME ruby_home MY_RUBY_HOME RUBY_VERSION if [ ! -d $ruby_home ] ; then warn "$implementation $version is not installed, installing." ruby-install $implementation $version $patchlevel fi # Setup ~/.rvm/current echo "PATH=$ruby_home/bin:$GEM_HOME/bin:\$PATH ; export PATH" > ~/.rvm/current for variable in RUBY_VERSION GEM_HOME MY_RUBY_HOME ruby_home ; do eval "export $variable" eval value=\$${variable} echo "${variable}='$value' ; export ${variable}" >> ~/.rvm/current done else PATH=$original_path ; export PATH fi info "Switching to $implementation $version $patchlevel ..." exec bash --login } function ruby-gem-dir { case "$implementation" in leopard) GEM_HOME="$HOME/.gem/ruby/1.8" ;; jruby) GEM_HOME="$HOME/.gem/jruby/1.8" ;; ree) GEM_HOME="$HOME/.gem/ruby-enterprise/1.8" ;; ruby) if [ "$version" = "1.8.6" ] ; then GEM_HOME="$HOME/.gem/ruby/1.8" elif [ "$version" = "1.8.7" ] ; then GEM_HOME="$HOME/.gem/ruby/1.8" elif [ "$version" = "1.9.1" -o "$version" = "1.9" ] ; then GEM_HOME="$HOME/.gem/ruby/1.9.1" else fail "Unknown ruby version: $version" fi ;; *) fail "Ruby implementation '$implementation' is not known." esac cd $GEM_HOME } # clones from source implementation/version to current function ruby-gem-dup { source_implementation=${1-ruby} source_version=${2-1.8.6} # TODO: use ruby-gem-dir for this once it has stabilized case "$source_implementation" in leopard) gemdir="$HOME/.gem/ruby/1.8" ;; jruby) gemdir="$HOME/.gem/jruby/1.8" ;; ree) gemdir="$HOME/.gem/ruby-enterprise/1.8" ;; ruby) if [ "$source_version" = "1.8.6" ] ; then gemdir="$HOME/.gem/ruby/1.8" elif [ "$source_version" = "1.8.7" ] ; then gemdir="$HOME/.gem/ruby/1.8" elif [ "$source_version" = "1.9.1" -o "$version" = "1.9" ] ; then gemdir="$HOME/.gem/ruby/1.9.1" fi ;; esac if [ ! -z "$gemdir" ] ; then for gem_name_version in `ls $gemdir/gems` ; do gem_name=${gem_name_version%-*} gem_version=${gem_name_version##*-} if [ -d $GEM_HOME/gems/$gem_name_version ] ; then echo "$gem_name_version already installed." else ruby-gi $gemdir/cache/$gem_name-$gem_version.gem fi done else fail "Unknown $implementation version: $version" fi } function rvm-setup { rm -f ~/.bin/rvm bindir=$(dirname `which rvm`) gemsdir="$(dirname $bindir)/gems" cd $gemsdir/`ls -t ~/.gem/ruby/1.8/gems | grep rvm | head -n 1` bash/rvm-setup info "~/.bin/rvm is symlinked to the gem's rvm script and ~/.bin is in your path.\n" \ "You may now use rvm via the command line the next time you open a terminal shell." } function rvm-version { info "rvm $rvm_version" } function rvm { while [ $# -gt 0 ] ; do arg="$1" ; shift case "$arg" in install|use|path|info|gemdir|gemdup|setup|version) action=$arg ;; ruby|jruby|ree|leopard|default) implementation="$arg" ;; -v|--version) version="$1" ; shift ;; -l|--level) patchlevel="$1" ; shift ;; -p|--prefix) install_path="$1" ; shift ;; -m|--manager) manager="$1" ; shift ;; -d|--debug) debug=true ;; *) usage esac done curl="curl -O -L -s " implementation=${implementation-'ruby'} username=`whoami` if [ "$username" = "root" ] ; then prefix_path=${prefix-/usr/local/} else prefix_path=${prefix-$HOME/.} fi # TODO: Sanitize user input, ensure that there is a / a the end... source_path="${prefix_path}rvm/src" install_path="${prefix_path}rvm" mkdir -p $source_path $install_path original_path=`cat $install_path/.original_path` if [ -z "$original_path" ] ; then echo $PATH > $install_path/.original_path original_path=$PATH fi case "$action" in install) if [ "$implementation" = "all" ] ; then for implementation in ruby jruby ree ; do if [ "$implementation" = "ruby" ] ; then for versions in 1.8.6 1.8.7 1.9.1 ; do ruby-install done else ruby-install fi done else ruby-install $implementation $version $patchlevel fi ;; use) ruby-use $implementation $version $patchlevel ;; gemdir) ruby-gem-dir $implementation $version $patchlevel ;; gemdup) ruby-gem-dup $implementation $version $patchlevel ;; path) ruby-path $implementation $version $patchlevel ;; info) ruby-info $implementation $version $patchlevel ;; version) rvm-version ;; setup) rvm-setup ;; *) usage ; fail "unknown action '$action'" esac }