diff options
Diffstat (limited to 'jni/ruby/lib/rubygems/commands/update_command.rb')
-rw-r--r-- | jni/ruby/lib/rubygems/commands/update_command.rb | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/jni/ruby/lib/rubygems/commands/update_command.rb b/jni/ruby/lib/rubygems/commands/update_command.rb new file mode 100644 index 0000000..001dd77 --- /dev/null +++ b/jni/ruby/lib/rubygems/commands/update_command.rb @@ -0,0 +1,277 @@ +require 'rubygems/command' +require 'rubygems/command_manager' +require 'rubygems/dependency_installer' +require 'rubygems/install_update_options' +require 'rubygems/local_remote_options' +require 'rubygems/spec_fetcher' +require 'rubygems/version_option' +require 'rubygems/install_message' # must come before rdoc for messaging +require 'rubygems/rdoc' + +class Gem::Commands::UpdateCommand < Gem::Command + + include Gem::InstallUpdateOptions + include Gem::LocalRemoteOptions + include Gem::VersionOption + + attr_reader :installer # :nodoc: + + attr_reader :updated # :nodoc: + + def initialize + super 'update', 'Update installed gems to the latest version', + :document => %w[rdoc ri], + :force => false + + add_install_update_options + + OptionParser.accept Gem::Version do |value| + Gem::Version.new value + + value + end + + add_option('--system [VERSION]', Gem::Version, + 'Update the RubyGems system software') do |value, options| + value = true unless value + + options[:system] = value + end + + add_local_remote_options + add_platform_option + add_prerelease_option "as update targets" + + @updated = [] + @installer = nil + end + + def arguments # :nodoc: + "REGEXP regexp to search for in gem name" + end + + def defaults_str # :nodoc: + "--document --no-force --install-dir #{Gem.dir}" + end + + def description # :nodoc: + <<-EOF +The update command will update your gems to the latest version. + +The update command does not remove the previous version. Use the cleanup +command to remove old versions. + EOF + end + + def usage # :nodoc: + "#{program_name} REGEXP [REGEXP ...]" + end + + def check_latest_rubygems version # :nodoc: + if Gem.rubygems_version == version then + say "Latest version currently installed. Aborting." + terminate_interaction + end + + options[:user_install] = false + end + + def check_update_arguments # :nodoc: + unless options[:args].empty? then + alert_error "Gem names are not allowed with the --system option" + terminate_interaction 1 + end + end + + def execute + if options[:system] then + update_rubygems + return + end + + say "Updating installed gems" + + hig = highest_installed_gems + + gems_to_update = which_to_update hig, options[:args].uniq + + updated = update_gems gems_to_update + + updated_names = updated.map { |spec| spec.name } + not_updated_names = options[:args].uniq - updated_names + + if updated.empty? then + say "Nothing to update" + else + say "Gems updated: #{updated_names.join(' ')}" + say "Gems already up-to-date: #{not_updated_names.join(' ')}" unless not_updated_names.empty? + end + end + + def fetch_remote_gems spec # :nodoc: + dependency = Gem::Dependency.new spec.name, "> #{spec.version}" + dependency.prerelease = options[:prerelease] + + fetcher = Gem::SpecFetcher.fetcher + + spec_tuples, errors = fetcher.search_for_dependency dependency + + error = errors.find { |e| e.respond_to? :exception } + + raise error if error + + spec_tuples + end + + def highest_installed_gems # :nodoc: + hig = {} # highest installed gems + + Gem::Specification.each do |spec| + if hig[spec.name].nil? or hig[spec.name].version < spec.version then + hig[spec.name] = spec + end + end + + hig + end + + def highest_remote_version spec # :nodoc: + spec_tuples = fetch_remote_gems spec + + matching_gems = spec_tuples.select do |g,_| + g.name == spec.name and g.match_platform? + end + + highest_remote_gem = matching_gems.max_by { |g,_| g.version } + + highest_remote_gem ||= [Gem::NameTuple.null] + + highest_remote_gem.first.version + end + + def install_rubygems version # :nodoc: + args = update_rubygems_arguments + + update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}" + + Dir.chdir update_dir do + say "Installing RubyGems #{version}" + + # Make sure old rubygems isn't loaded + old = ENV["RUBYOPT"] + ENV.delete("RUBYOPT") if old + installed = system Gem.ruby, 'setup.rb', *args + say "RubyGems system software updated" if installed + ENV["RUBYOPT"] = old if old + end + end + + def rubygems_target_version + version = options[:system] + update_latest = version == true + + if update_latest then + version = Gem::Version.new Gem::VERSION + requirement = Gem::Requirement.new ">= #{Gem::VERSION}" + else + version = Gem::Version.new version + requirement = Gem::Requirement.new version + end + + rubygems_update = Gem::Specification.new + rubygems_update.name = 'rubygems-update' + rubygems_update.version = version + + hig = { + 'rubygems-update' => rubygems_update + } + + gems_to_update = which_to_update hig, options[:args], :system + _, up_ver = gems_to_update.first + + target = if update_latest then + up_ver + else + version + end + + return target, requirement + end + + def update_gem name, version = Gem::Requirement.default + return if @updated.any? { |spec| spec.name == name } + + update_options = options.dup + update_options[:prerelease] = version.prerelease? + + @installer = Gem::DependencyInstaller.new update_options + + say "Updating #{name}" + begin + @installer.install name, Gem::Requirement.new(version) + rescue Gem::InstallError, Gem::DependencyError => e + alert_error "Error installing #{name}:\n\t#{e.message}" + end + + @installer.installed_gems.each do |spec| + @updated << spec + end + end + + def update_gems gems_to_update + gems_to_update.uniq.sort.each do |(name, version)| + update_gem name, version + end + + @updated + end + + ## + # Update RubyGems software to the latest version. + + def update_rubygems + check_update_arguments + + version, requirement = rubygems_target_version + + check_latest_rubygems version + + update_gem 'rubygems-update', version + + installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement + version = installed_gems.last.version + + install_rubygems version + end + + def update_rubygems_arguments # :nodoc: + args = [] + args << '--prefix' << Gem.prefix if Gem.prefix + # TODO use --document for >= 1.9 , --no-rdoc --no-ri < 1.9 + args << '--no-rdoc' unless options[:document].include? 'rdoc' + args << '--no-ri' unless options[:document].include? 'ri' + args << '--no-format-executable' if options[:no_format_executable] + args << '--previous-version' << Gem::VERSION if + options[:system] == true or + Gem::Version.new(options[:system]) >= Gem::Version.new(2) + args + end + + def which_to_update highest_installed_gems, gem_names, system = false + result = [] + + highest_installed_gems.each do |l_name, l_spec| + next if not gem_names.empty? and + gem_names.none? { |name| name == l_spec.name } + + highest_remote_ver = highest_remote_version l_spec + + if system or (l_spec.version < highest_remote_ver) then + result << [l_spec.name, [l_spec.version, highest_remote_ver].max] + end + end + + result + end + +end |