Copying gems from previous version of Ruby in rbenv

限于喜欢 提交于 2019-11-29 21:49:16
Austin Ziegler

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.

you can copy gems/ and bin/ folders but this will lead to troubles.
files in bin/ has hardcoded paths in them.

i would recommend instead to reinstall them with easy like this:

$ rbenv local 1.9.3-p286
$ gem list | cut -d" " -f1 > my-gems
$ rbenv local 1.9.3-p327
$ gem in $(cat my-gems)

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!