#! /usr/bin/env ruby
#
# (c) Erik Hvatum 2009
#
require 'rubygems'
require 'optparse'
require 'open4'
#* Parse command line options
options = {}
optparser = OptionParser.new
optparser.banner = "Usage: #{$0} [options]"
options[:dryrun] = false
optparser.on('-d', '--dry', 'Dry run; print the calls to gem that would be executed') do
options[:dryrun] = true
end
options[:gemexec] = 'gem'
optparser.on('-g', '--gem EXECUTABLE', 'Specify gem executable name; ie, gem19 or /usr/local/bin/gem19') do |gem|
options[:gemexec] = gem
end
optparser.on('-h', '--help', 'Display help information') do
puts optparser
exit
end
options[:verbose] = false
optparser.on('-v', '--verbose', 'Output more information') do
options[:verbose] = true
end
begin
optparser.parse! ARGV
rescue OptionParser::ParseError => e
abort e
end
if ARGV.size > 0
abort "invalid option: #{ARGV[0]}"
end
#* Make list of outdated gems to remove
GemInfo = Struct.new(:nameAndVersion, :name, :version, :path)
gemsToUninstall = []
gemCleanDryCmd = "#{options[:gemexec]} cleanup -d"
if options[:verbose]
puts "To determine which gems are outdated and should be removed, executing shell command: #{gemCleanDryCmd}"
end
pid, stdin, stdout, stderr = Open4::popen4(gemCleanDryCmd)
ignored, status = Process::waitpid2(pid)
if status != 0
abort "Error: #{gemCleanDryCmd} returned #{status} instead of zero, with stdout output\n#{stdout.read.strip}\nand stderr output\n#{stderr.read.strip}"
end
l = stdout.readline()
unless l =~ /^\s*Cleaning up installed gems\.\.\.\s*$/i
abort "Error: First line of #{gemCleanDryCmd} stdout is not \"Cleaning up installed gems...\""
end
while 1
l = stdout.readline()
if l == nil
abort "Error: Premature end of output from #{gemCleanDryCmd}"
end
if l =~ /^\s*Clean Up Complete\s*$/i
break
end
if l =~ /^\s*Dry Run Mode: Would uninstall (\S+)\s*$/i
if options[:verbose]
puts "Found obsolete gem to uninstall: #{$1}"
end
gemsToUninstall << GemInfo.new($1)
else
abort "Error: Failed to parse output from #{gemCleanDryCmd}: #{l}"
end
end
for gem in gemsToUninstall
if gem.nameAndVersion =~ /^(.*)-((?:\d+\.?)+)$/
gem.name, gem.version = $1, $2
else
abort "Error: Failed to parse gem name: #{gem.nameAndVersion}"
end
end
#* Get paths of identified gems
for gem in gemsToUninstall
cmd = "#{options[:gemexec]} list -d -l #{gem.name}"
if options[:verbose]
puts cmd
end
pid, stdin, stdout, stderr = Open4::popen4(cmd)
ignored, status = Process::waitpid2(pid)
if status != 0
abort "Error: #{cmd} returned #{status} instead of zero, with stdout output\n#{stdout.read.strip}\nand stderr output\n#{stderr.read.strip}"
end
o = stdout.read()
unless o =~ /Installed at /
abort "Error: failed to parse output of #{cmd}"
end
while $' =~ /\s*\(((?:\d+\.?)+)\): (.*)$/
if $1 == gem.version
gem.path = $2
break
end
end
end
#* Perform removal
for gem in gemsToUninstall
cmd = "#{options[:gemexec]} uninstall -I --no-executables
--install-dir #{gem.path} --version \"=#{gem.version}\" #{gem.name}"
if options[:dryrun] || options[:verbose]
puts cmd
end
unless options[:dryrun]
system(cmd)
end
end
July 2009 August 2009 September 2009 October 2009 November 2009 December 2009 January 2010 September 2010 December 2010 January 2011 February 2011 April 2011 June 2011 August 2011 February 2012 June 2012 July 2012 August 2012 October 2012 November 2012 January 2014 April 2014 June 2014 August 2014 September 2014 October 2014 January 2015 March 2015 April 2015 June 2015 November 2015 December 2015 January 2016 June 2016 August 2016 January 2017 March 2017 April 2018 April 2019 June 2019 January 2020
Subscribe to Posts [Atom]
Post a Comment