Copying gems from previous version of Ruby in rbenv

前端 未结 3 497
难免孤独
难免孤独 2020-12-23 22:46

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

相关标签:
3条回答
  • 2020-12-23 23:01

    You can copy the gems/ and bin/ folders, but this will lead to problems. The files in bin/ have hardcoded paths in them.

    I'd recommend reinstalling them, which would be as easy as this:

    $ rbenv local 1.9.3-p286
    $ gem list | cut -d" " -f1 > my-gems
    $ rbenv local 1.9.3-p327
    $ gem install $(cat my-gems)
    
    0 讨论(0)
  • 2020-12-23 23:15

    For posterity, I wrote rbenv-copy-gems.sh to help me do this. It doesn't meet the criteria of this question (it installs from the Internet, not locally), but it's been useful for me as I upgrade or install new version of Ruby via rbenv install.

    Current version pasted below for reference, but I keep the gist up to date as I make improvements.

    #!/bin/bash
    # copy is a misnomer; it's actually LIST + INSTALL
    # --from 2.2.1 [--to other-version-else-whatever-is-currently-set]
    #
    # TODO: install only most-recent version that's installed in FROM
    # TODO: use gem names only from FROM, install latest available version (might be more recent than in FROM)
    # TODO: pass arguments to gem command (e.g. --no-document)
    
    CURRENT_VERSION=`rbenv version | cut -d' ' -f1`
    GEM_LIST_ARGS="--local"
    
    while [[ $# -gt 0 ]]; do
      option="$1"
    
      case $option in
        --from)
        FROM="$2"
        shift
        ;;
        --to)
        TO="$2"
        shift
        ;;
      esac
      shift # past argument or value
    done
    
    if [ -z "${FROM}" ]; then
      FROM="${CURRENT_VERSION}"
    fi
    
    if [ -z "${TO}" ]; then
      TO="${CURRENT_VERSION}"
    fi
    
    echo ">>> Install gems from v${FROM} to v${TO}"
    
    # Get gems and versions, reformat to GEMNAME:version[,version[...]]
    gems=(`RBENV_VERSION=${FROM} gem list ${GEM_LIST_ARGS} | sed -e 's/[\(\)]//g' -e 's/, /,/g' -e 's/ /:/'`)
    
    for geminfo in "${gems[@]}"; do
      gem=`echo $geminfo | cut -d: -f1`
      versions=(`echo $geminfo | sed -e 's/^.*://' -e 's/,/ /g'`)
      for version in "${versions[@]}"; do
        installed=`RBENV_VERSION=${TO} gem query -i $gem -v $version`
        if [ "${installed}" == "false" ]; then
          echo ">>> Installing ${gem} ${version}:"
          RBENV_VERSION=${TO} gem install $gem -v $version
        else
          echo ">>> ${gem} ${version} already installed"
        fi
        echo ""
      done
    done
    
    0 讨论(0)
  • 2020-12-23 23:17

    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.

    0 讨论(0)
提交回复
热议问题