diff options
Diffstat (limited to 'lib/rubygems/commands/update_command.rb')
| -rw-r--r-- | lib/rubygems/commands/update_command.rb | 245 |
1 files changed, 146 insertions, 99 deletions
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index f3d70a92a6..d9740d814a 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -1,16 +1,16 @@ # frozen_string_literal: true -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 +require_relative "../command" +require_relative "../command_manager" +require_relative "../dependency_installer" +require_relative "../install_update_options" +require_relative "../local_remote_options" +require_relative "../spec_fetcher" +require_relative "../version_option" +require_relative "../install_message" # must come before rdoc for messaging +require_relative "../rdoc" +class Gem::Commands::UpdateCommand < Gem::Command include Gem::InstallUpdateOptions include Gem::LocalRemoteOptions include Gem::VersionOption @@ -20,23 +20,27 @@ class Gem::Commands::UpdateCommand < Gem::Command attr_reader :updated # :nodoc: def initialize - super 'update', 'Update installed gems to the latest version', - :document => %w[rdoc ri], - :force => false + options = { + force: false, + } + + options.merge!(install_update_options) + + super "update", "Update installed gems to the latest version", options add_install_update_options - OptionParser.accept Gem::Version do |value| + Gem::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 + add_option("--system [VERSION]", Gem::Version, + "Update the RubyGems system software") do |value, opts| + value ||= true - options[:system] = value + opts[:system] = value end add_local_remote_options @@ -52,7 +56,8 @@ class Gem::Commands::UpdateCommand < Gem::Command end def defaults_str # :nodoc: - "--document --no-force --install-dir #{Gem.dir}" + "--no-force --install-dir #{Gem.dir}\n" + + install_update_defaults_str end def description # :nodoc: @@ -68,49 +73,68 @@ command to remove old versions. "#{program_name} GEMNAME [GEMNAME ...]" end - def check_latest_rubygems version # :nodoc: - if Gem.rubygems_version == version then - say "Latest version currently installed. Aborting." + def check_latest_rubygems(version) # :nodoc: + if Gem.rubygems_version == version + say "Latest version already installed. Done." terminate_interaction end + end - options[:user_install] = false + def check_oldest_rubygems(version) # :nodoc: + if oldest_supported_version > version + alert_error "rubygems #{version} is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is #{oldest_supported_version}" + terminate_interaction 1 + end end def check_update_arguments # :nodoc: - unless options[:args].empty? then + unless options[:args].empty? alert_error "Gem names are not allowed with the --system option" terminate_interaction 1 end end def execute - - if options[:system] then + if options[:system] update_rubygems return end - say "Updating installed gems" + gems_to_update = which_to_update( + highest_installed_gems, + options[:args].uniq + ) + + if options[:explain] + say "Gems to update:" - hig = highest_installed_gems + gems_to_update.each do |name_tuple| + say " #{name_tuple.full_name}" + end + + return + end - gems_to_update = which_to_update hig, options[:args].uniq + say "Updating installed gems" updated = update_gems gems_to_update - updated_names = updated.map { |spec| spec.name } + installed_names = highest_installed_gems.keys + updated_names = updated.map(&:name) not_updated_names = options[:args].uniq - updated_names + not_installed_names = not_updated_names - installed_names + up_to_date_names = not_updated_names - not_installed_names - if updated.empty? then + if updated.empty? 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? + say "Gems updated: #{updated_names.join(" ")}" end + say "Gems already up-to-date: #{up_to_date_names.join(" ")}" unless up_to_date_names.empty? + say "Gems not currently installed: #{not_installed_names.join(" ")}" unless not_installed_names.empty? end - def fetch_remote_gems spec # :nodoc: + def fetch_remote_gems(spec) # :nodoc: dependency = Gem::Dependency.new spec.name, "> #{spec.version}" dependency.prerelease = options[:prerelease] @@ -118,7 +142,7 @@ command to remove old versions. spec_tuples, errors = fetcher.search_for_dependency dependency - error = errors.find { |e| e.respond_to? :exception } + error = errors.find {|e| e.respond_to? :exception } raise error if error @@ -128,8 +152,11 @@ command to remove old versions. def highest_installed_gems # :nodoc: hig = {} # highest installed gems + # Get only gem specifications installed as --user-install + Gem::Specification.dirs = Gem.user_dir if options[:user_install] + Gem::Specification.each do |spec| - if hig[spec.name].nil? or hig[spec.name].version < spec.version then + if hig[spec.name].nil? || hig[spec.name].version < spec.version hig[spec.name] = spec end end @@ -137,34 +164,50 @@ command to remove old versions. hig end - def highest_remote_version spec # :nodoc: + def highest_remote_name_tuple(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 = spec_tuples.max + return unless highest_remote_gem - highest_remote_gem.first.version + highest_remote_gem.first end - def install_rubygems version # :nodoc: + def install_rubygems(spec) # :nodoc: args = update_rubygems_arguments + version = spec.version - update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}" + update_dir = File.join spec.base_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 + say "Installing RubyGems #{version}" unless options[:silent] + + installed = preparing_gem_layout_for(version) do + system Gem.ruby, "--disable-gems", "setup.rb", *args + end + + unless options[:silent] + say "RubyGems system software updated" if installed + end + end + end + + def preparing_gem_layout_for(version) + if Gem::Version.new(version) >= Gem::Version.new("3.2.a") + yield + else + require "tmpdir" + Dir.mktmpdir("gem_update") do |tmpdir| + FileUtils.mv Gem.plugindir, tmpdir + + status = yield + + unless status + FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugindir + end + + status + end end end @@ -172,43 +215,35 @@ command to remove old versions. version = options[:system] update_latest = version == true - if update_latest then - version = Gem::Version.new Gem::VERSION - requirement = Gem::Requirement.new ">= #{Gem::VERSION}" - else + unless update_latest version = Gem::Version.new version requirement = Gem::Requirement.new version + + return version, requirement end + version = Gem::Version.new Gem::VERSION + requirement = Gem::Requirement.new ">= #{Gem::VERSION}" + rubygems_update = Gem::Specification.new - rubygems_update.name = 'rubygems-update' + 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 + highest_remote_tup = highest_remote_name_tuple(rubygems_update) + target = highest_remote_tup ? highest_remote_tup.version : version - return target, requirement + [target, requirement] end - def update_gem name, version = Gem::Requirement.default - return if @updated.any? { |spec| spec.name == name } + 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}" + say "Updating #{name}" unless options[:system] begin @installer.install name, Gem::Requirement.new(version) rescue Gem::InstallError, Gem::DependencyError => e @@ -220,9 +255,9 @@ command to remove old versions. end end - def update_gems gems_to_update - gems_to_update.uniq.sort.each do |(name, version)| - update_gem name, version + def update_gems(gems_to_update) + gems_to_update.uniq.sort.each do |name_tuple| + update_gem name_tuple.name, name_tuple.version end @updated @@ -232,48 +267,60 @@ command to remove old versions. # Update RubyGems software to the latest version. def update_rubygems + if Gem.disable_system_update_message + alert_error Gem.disable_system_update_message + terminate_interaction 1 + end + check_update_arguments version, requirement = rubygems_target_version check_latest_rubygems version - update_gem 'rubygems-update', version + check_oldest_rubygems version - installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement - version = installed_gems.first.version + installed_gems = Gem::Specification.find_all_by_name "rubygems-update", requirement + installed_gems = update_gem("rubygems-update", requirement) if installed_gems.empty? || installed_gems.first.version != version + return if installed_gems.empty? - install_rubygems version + install_rubygems installed_gems.first 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 << "--silent" if options[:silent] + args << "--prefix" << Gem.prefix if Gem.prefix + args << "--no-document" unless options[:document].include?("rdoc") || options[:document].include?("ri") + args << "--no-format-executable" if options[:no_format_executable] + args << "--previous-version" << Gem::VERSION args end - def which_to_update highest_installed_gems, gem_names, system = false + def which_to_update(highest_installed_gems, gem_names) 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_installed_gems.each do |_l_name, l_spec| + next if !gem_names.empty? && + gem_names.none? {|name| name == l_spec.name } - highest_remote_ver = highest_remote_version l_spec + highest_remote_tup = highest_remote_name_tuple l_spec + next unless highest_remote_tup - if system or (l_spec.version < highest_remote_ver) then - result << [l_spec.name, [l_spec.version, highest_remote_ver].max] - end + result << highest_remote_tup end result end + private + + # + # Oldest version we support downgrading to. This is the version that + # originally ships with the oldest supported patch version of ruby. + # + def oldest_supported_version + @oldest_supported_version ||= + Gem::Version.new("3.3.3") + end end |
