Search code examples
rubyrbenv

Copying gems from previous version of Ruby in rbenv


I installed Ruby 1.9.3-p286 with rbenv. Now, after installing a newer version (p327), obviously, it doesn't know anything about the GEMs installed with the previous version.

Is it possible to copy Gems from that version to the newer one, so that it won't be needed to download them all again?


Solution

  • I've been looking at this specifically from the perspective of upgrading and reinstalling without downloading. It's not trivial, and I recommend you do some cleanup of your gems to minimize the amount of processing/installation that needs to be done (e.g., I had five versions of ZenTest installed; I did 'gem cleanup ZenTest' before doing this). Be careful with 'gem cleanup', though, as it removes all but the LAST version: if you need to support an older version of Rails, manually clean up the versions you don't need.

    I called this script 'migrate-gems.sh':

    #! /bin/bash
    
    if [ ${#} -ne 2 ]; then
      echo >&2 Usage: $(basename ${0}) old-version new-version
      exit 1
    fi
    
    home_path=$(cd ~; pwd -P)
    old_version=${1}
    new_version=${2}
    
    rbenv shell ${old_version}
    
    declare -a old_gem_paths old_gems
    old_gem_paths=($(gem env gempath | sed -e 's/:/ /'))
    
    rbenv shell ${new_version}
    
    for ogp in "${old_gem_paths[@]}"; do
      case "${ogp}" in
        ${home_path}/.gem/ruby*|*/.gem/ruby*)
          # Skip ~/.gem/ruby.
          continue
          ;;
      esac
    
      for old_gem in $(ls -1 ${ogp}/cache/*.gem); do
        gem install --local --ignore-dependencies ${ogp}/cache/${old_gem}
      done
    done
    

    There are three pieces that make this work:

    1. gem env gempath contains the paths (:-separated) where gems are installed. Because gems are shared in ~/.gem/ruby, I skip this one.
    2. gem install accepts --local, which forces no network connections.
    3. gem install accepts --ignore-dependencies, which disables dependency checking.

    I had a fairly large list of gems to move over today and I didn't want to download from rubygems.org (plus, I needed older versions), so I whipped this up fairly quickly.