From bbaebbf5290adcbbfe30bbd925c2bf85ce190f52 Mon Sep 17 00:00:00 2001 From: Jared Beck Date: Thu, 8 Jul 2021 11:27:50 -0400 Subject: [PATCH] [rubygems/rubygems] Fix contradictory message about deletion of default gem [Fixes #4733] https://github.com/rubygems/rubygems/commit/fce7f3eb7d --- lib/rubygems/uninstaller.rb | 41 +++++++++++++++++++++++---- test/rubygems/test_gem_uninstaller.rb | 11 +++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 3bc202863c..87a5ef770f 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -70,6 +70,9 @@ class Gem::Uninstaller # only add user directory if install_dir is not set @user_install = false @user_install = options[:user_install] unless options[:install_dir] + + # Optimization: populated during #uninstall + @default_specs_matching_uninstall_params = [] end ## @@ -98,10 +101,8 @@ class Gem::Uninstaller default_specs, list = list.partition do |spec| spec.default_gem? end - - default_specs.each do |default_spec| - say "Gem #{default_spec.full_name} cannot be uninstalled because it is a default gem" - end + warn_cannot_uninstall_default_gems(default_specs - list) + @default_specs_matching_uninstall_params = default_specs list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir or @@ -273,7 +274,7 @@ class Gem::Uninstaller end safe_delete { FileUtils.rm_r gemspec } - say "Successfully uninstalled #{spec.full_name}" + announce_deletion_of(spec) Gem::Specification.reset end @@ -376,4 +377,34 @@ class Gem::Uninstaller raise e end + + private + + def announce_deletion_of(spec) + name = spec.full_name + say "Successfully uninstalled #{name}" + if default_spec_matches?(spec) + say( + "There was both a regular copy and a default copy of #{name}. The " \ + "regular copy was successfully uninstalled, but the default copy " \ + "was left around because default gems can't be removed." + ) + end + end + + # @return true if the specs of any default gems are `==` to the given `spec`. + def default_spec_matches?(spec) + !default_specs_that_match(spec).empty? + end + + # @return [Array] specs of default gems that are `==` to the given `spec`. + def default_specs_that_match(spec) + @default_specs_matching_uninstall_params.select {|default_spec| spec == default_spec } + end + + def warn_cannot_uninstall_default_gems(specs) + specs.each do |spec| + say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem" + end + end end diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index a002c0c7c8..9e18972864 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -295,8 +295,15 @@ class TestGemUninstaller < Gem::InstallerTestCase uninstaller = Gem::Uninstaller.new spec.name, :executables => true - uninstaller.uninstall - + ui = Gem::MockGemUi.new "1\ny\n" + use_ui ui do + uninstaller.uninstall + end + expected = "Successfully uninstalled default-2\n" \ + "There was both a regular copy and a default copy of default-2. The " \ + "regular copy was successfully uninstalled, but the default copy " \ + "was left around because default gems can't be removed.\n" + assert_equal expected, ui.output assert_path_not_exist spec.gem_dir end