svenfuchs
11/8/2009 - 12:55 PM

hubcut

#!/usr/bin/env ruby

# This script copies all .gem files for all versions of a gem from gems.github.com to gemcutter.org.
# For all versions of a gem, it does a gem fetch, repackages the gem with the non-namespaced name,
# and does a gem push.  You must have permission to push the gem, so your gemcutter key must be
# set in ~/.gemrc

require 'rubygems'
require 'yaml'
require 'fileutils'

def usage
  puts "Usage: hubcut <github_account-gemname>
  e.g. hubcut pivotal-desert"
  exit 1
end

def shell(command)
  puts `#{command}`
  exit(1) unless $?.success?
end

usage unless ARGV[0]

scoped_name = ARGV[0]
account_name, gem_name = scoped_name.split('-', 2)
puts "Account: #{account_name} Gem: #{gem_name}"

usage unless gem_name

puts "Getting gem versions..."
list = `gem list -ra #{scoped_name} --source=http://gems.github.com/`
if list =~ %r{\((.+)\)}
  versions = $1.split(', ')
end

versions.each do |version|
  puts "\nFetching gem version #{version}..."
  shell "gem fetch #{scoped_name} --version #{version} --source=http://gems.github.com/"
  old_gemfile_name = "#{scoped_name}-#{version}.gem"
  new_gemfile_name = "#{gem_name}-#{version}.gem"

  puts "Unpacking..."
  shell "gem unpack #{old_gemfile_name}"
  unpacked_gem = "#{scoped_name}-#{version}"

  puts "Creating new gemspec..."
  gemspec = `gem spec #{old_gemfile_name}`
  spec = YAML.load(StringIO.new(gemspec))
  spec.name = gem_name
  FileUtils.cd(unpacked_gem) do
    gemspec_file = "#{gem_name}.gemspec"
    File.open(gemspec_file, 'w') do |f|
      YAML.dump(spec, f)
    end
    
    puts "Building gem..."
    shell "gem build #{gemspec_file}"

    FileUtils.mv(new_gemfile_name, "../#{new_gemfile_name}", :force => true)
  end
  
  puts "Pushing #{new_gemfile_name} to gemcutter.org..."
  shell "gem push #{new_gemfile_name}"
end