Created
November 12, 2008 08:45
-
-
Save sborsje/24113 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'rubygems' | |
require 'rubygems/command' | |
require 'rubygems/commands/query_command' | |
CONFIG_FILE = 'config/gem_installer.yml' | |
def run | |
commands = parse_input_file | |
@gem_install_count = 0 | |
@required_gems = 0 | |
@source_installed = 0 | |
@removed_gems = 0 | |
error_count = 0 | |
commands.each do |command| | |
if command[:command] == "source" | |
error_count += 1 unless do_source(command) | |
elsif command[:command] == "gem" | |
error_count += 1 unless do_gem(command) | |
end | |
end | |
puts "*** Finished installing #{@gem_install_count} out of #{@required_gems} gems" | |
puts "*** Removed #{@removed_gems} gems." if @removed_gems > 0 | |
if error_count > 0 | |
puts "*** ERROR: #{error_count} errors occured!" | |
exit 1 | |
end | |
end | |
def parse_input_file | |
raise("Gem installer config file (#{CONFIG_FILE}) missing!") unless (File.exists?(CONFIG_FILE)) | |
Gem.source_index # update gem sources | |
commands = [] | |
config = YAML::load_file(CONFIG_FILE) | |
config["sources"].each do |source| | |
commands << { :command => 'source', :source => source } | |
end | |
config["gems"].each do |rubygem| | |
x = parse_gem_line(rubygem) | |
commands << x if x | |
end | |
return commands | |
end | |
def parse_gem_line(line) | |
split_line = line.split(" ") | |
name, version, command = split_line[0], split_line[1], nil | |
if split_line[2] == "--" | |
# custom command specified | |
command = split_line[3..split_line.size-1].join(" ") | |
end | |
unless name.empty?# or version.empty? | |
allow_siblings = version.nil? ? nil : (version.match(/\*$/) ? false : true) | |
version.gsub!(/\*$/, "") unless version.nil? | |
{ :command => 'gem', :name => name, :version => version, :allow_siblings => allow_siblings, :custom_command => command } | |
end | |
end | |
def do_source(command) | |
add_source(command[:source]) | |
end | |
def do_gem(command) | |
@required_gems +=1 | |
# uninstall unwanted siblings if required | |
unless command[:allow_siblings] | |
siblings = get_siblings_of(command[:name], command[:version]) | |
(siblings || []).each do |sibling| | |
puts "==> Removing #{sibling[:name]} #{sibling[:version]}..." | |
unless remove_gem(sibling[:name], sibling[:version]) | |
puts "==> Could not uninstall #{sibling[:name]} #{sibling[:version]}. An error was returned." | |
return false | |
else | |
@removed_gems +=1 | |
end | |
end | |
end | |
# install the gem if it's not already installed | |
unless gem_installed?(command[:name], command[:version]) | |
puts "==> Installing #{command[:name]} #{command[:version]}..." | |
@gem_install_count +=1 | |
if command[:custom_command].nil? | |
version_string = "" | |
unless command[:version].nil? or command[:version].empty? | |
version_string = "-v #{command[:version]}" | |
end | |
output, exit_code = exec("gem install #{command[:name]} #{version_string} --no-rdoc --no-ri") | |
else | |
puts "==> Running custom command '#{command[:custom_command]}'..." | |
output, exit_code = exec("#{command[:custom_command]}") | |
end | |
return (exit_code == 0) | |
else | |
puts "==> #{command[:name]} #{command[:version]} is already installed." | |
return true | |
end | |
end | |
def remove_gem(name, version) | |
output, exit_code = exec("gem uninstall #{name} -v '#{version}' -I -x -a") | |
return (exit_code == 0) | |
end | |
def gem_installed?(gem_name, gem_version) | |
Gem::Commands::QueryCommand.new.installed?(gem_name, gem_version) | |
end | |
def source_installed?(source_uri) | |
Gem.sources.include?(source_uri) | |
end | |
def add_source(source_uri) | |
unless source_installed?(source_uri) | |
puts "==> Adding source #{source_uri}..." | |
output, exit_code = exec("gem sources -a #{source_uri} && gem sources --update") | |
return (exit_code == 0) | |
else | |
puts "==> Source #{source_uri} already installed." | |
return true | |
end | |
end | |
def get_siblings_of(gem_name, version) | |
# TODO: get the versions directly from a Rubygems method instead of parsing. | |
gem, exit_code = exec("gem list #{gem_name} | grep #{gem_name}") | |
versions = [] | |
gem.each_line do |line| | |
if line.starts_with?(gem_name + " (") | |
versions = line.sub(gem_name + " (", "").sub(")","").sub(" ", "").split(',') | |
end | |
end | |
out = [] | |
versions.each do |v| | |
v.chomp! | |
out << {:name => gem_name, :version => v} unless v == version | |
end | |
out | |
end | |
def exec(command) | |
output = `#{command}` | |
exit_code = $? | |
return [output, exit_code] | |
end | |
class Gem::Commands::QueryCommand | |
public :installed? | |
end | |
class String | |
def starts_with?(str) | |
str = str.to_str | |
head = self[0, str.length] | |
head == str | |
end | |
end | |
# run the script! | |
run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment