diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-19 07:19:10 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-19 07:19:10 +0000 |
commit | eddc0685f224a6de2f5a6bdaab7f87562192ba7f (patch) | |
tree | 54f3427a70f2cc21e9dbbb6c3ad9ed500ea96865 | |
parent | 1b2be1f8ca5286a75d9401f96eaec89317353e3e (diff) |
* lib/rubygems/commands/query_command.rb: Refactored to improve
maintainability.
* test/rubygems/test_gem_commands_query_command.rb: Note default gems
in gem list details.
* lib/rubygems/uninstaller.rb: Detect all gems for uninstallation.
This allows duplicate installs of default gems to be removed.
* lib/rubygems/specification.rb: Allow use of ::each_spec.
* lib/rubygems/test_case.rb: Added install_default_gems.
* test/rubygems/test_gem_commands_uninstall_command.rb: Moved test
down to the uninstaller tests.
* test/rubygems/test_gem_uninstaller.rb: Test for uninstallation of
default gems and duplicate default gems.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38461 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | lib/rubygems/commands/query_command.rb | 184 | ||||
-rw-r--r-- | lib/rubygems/specification.rb | 1 | ||||
-rw-r--r-- | lib/rubygems/test_case.rb | 15 | ||||
-rw-r--r-- | lib/rubygems/uninstaller.rb | 16 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_query_command.rb | 44 | ||||
-rw-r--r-- | test/rubygems/test_gem_commands_uninstall_command.rb | 18 | ||||
-rw-r--r-- | test/rubygems/test_gem_uninstaller.rb | 61 |
8 files changed, 236 insertions, 119 deletions
@@ -1,3 +1,19 @@ +Wed Dec 19 16:18:22 2012 Eric Hodel <drbrain@segment7.net> + + * lib/rubygems/commands/query_command.rb: Refactored to improve + maintainability. + * test/rubygems/test_gem_commands_query_command.rb: Note default gems + in gem list details. + + * lib/rubygems/uninstaller.rb: Detect all gems for uninstallation. + This allows duplicate installs of default gems to be removed. + * lib/rubygems/specification.rb: Allow use of ::each_spec. + * lib/rubygems/test_case.rb: Added install_default_gems. + * test/rubygems/test_gem_commands_uninstall_command.rb: Moved test + down to the uninstaller tests. + * test/rubygems/test_gem_uninstaller.rb: Test for uninstallation of + default gems and duplicate default gems. + Wed Dec 19 15:23:50 2012 Eric Hodel <drbrain@segment7.net> * doc/syntax/methods.rdoc: Add () around keyword arguments example for diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb index 020bc297b4..0ae7924564 100644 --- a/lib/rubygems/commands/query_command.rb +++ b/lib/rubygems/commands/query_command.rb @@ -162,12 +162,18 @@ class Gem::Commands::QueryCommand < Gem::Command n.downcase end + output_versions output, versions + + say output.join(options[:details] ? "\n\n" : "\n") + end + + def output_versions output, versions versions.each do |gem_name, matching_tuples| matching_tuples = matching_tuples.sort_by { |n,_| n.version }.reverse platforms = Hash.new { |h,version| h[version] = [] } - matching_tuples.map do |n,_| + matching_tuples.each do |n, _| platforms[n.version] << n.platform if n.platform end @@ -182,97 +188,125 @@ class Gem::Commands::QueryCommand < Gem::Command end end - entry = gem_name.dup - - if options[:versions] then - list = if platforms.empty? or options[:details] then - matching_tuples.map { |n,_| n.version }.uniq - else - platforms.sort.reverse.map do |version, pls| - if pls == [Gem::Platform::RUBY] then - version - else - ruby = pls.delete Gem::Platform::RUBY - platform_list = [ruby, *pls.sort].compact - "#{version} #{platform_list.join ' '}" - end - end - end.join ', ' - - entry << " (#{list})" - end - - if options[:details] then - detail_tuple = matching_tuples.first + output << make_entry(matching_tuples, platforms) + end + end - spec = detail_tuple.last + def entry_details entry, spec, specs, platforms + return unless options[:details] - unless spec.kind_of? Gem::Specification - spec = spec.fetch_spec detail_tuple.first - end + entry << "\n" - entry << "\n" + spec_platforms entry, platforms + spec_authors entry, spec + spec_homepage entry, spec + spec_license entry, spec + spec_loaded_from entry, spec, specs + spec_summary entry, spec + end - non_ruby = platforms.any? do |_, pls| - pls.any? { |pl| pl != Gem::Platform::RUBY } - end + def entry_versions entry, name_tuples, platforms + return unless options[:versions] - if non_ruby then - if platforms.length == 1 then - title = platforms.values.length == 1 ? 'Platform' : 'Platforms' - entry << " #{title}: #{platforms.values.sort.join ', '}\n" + list = + if platforms.empty? or options[:details] then + name_tuples.map { |n| n.version }.uniq + else + platforms.sort.reverse.map do |version, pls| + if pls == [Gem::Platform::RUBY] then + version else - entry << " Platforms:\n" - platforms.sort_by do |version,| - version - end.each do |version, pls| - label = " #{version}: " - data = format_text pls.sort.join(', '), 68, label.length - data[0, label.length] = label - entry << data << "\n" - end + ruby = pls.delete Gem::Platform::RUBY + platform_list = [ruby, *pls.sort].compact + "#{version} #{platform_list.join ' '}" end end + end - authors = "Author#{spec.authors.length > 1 ? 's' : ''}: " - authors << spec.authors.join(', ') - entry << format_text(authors, 68, 4) + entry << " (#{list.join ', '})" + end - if spec.rubyforge_project and not spec.rubyforge_project.empty? then - rubyforge = "Rubyforge: http://rubyforge.org/projects/#{spec.rubyforge_project}" - entry << "\n" << format_text(rubyforge, 68, 4) - end + def make_entry entry_tuples, platforms + detail_tuple = entry_tuples.first + name_tuple, latest_spec = detail_tuple - if spec.homepage and not spec.homepage.empty? then - entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4) - end + latest_spec = latest_spec.fetch_spec name_tuple unless + Gem::Specification === latest_spec - if spec.license and not spec.license.empty? then - licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: " - licenses << spec.licenses.join(', ') - entry << "\n" << format_text(licenses, 68, 4) - end + name_tuples, specs = entry_tuples.flatten.partition do |item| + Gem::NameTuple === item + end - if spec.loaded_from then - if matching_tuples.length == 1 then - loaded_from = File.dirname File.dirname(spec.loaded_from) - entry << "\n" << " Installed at: #{loaded_from}" - else - label = 'Installed at' - matching_tuples.each do |n,s| - loaded_from = File.dirname File.dirname(s.loaded_from) - entry << "\n" << " #{label} (#{n.version}): #{loaded_from}" - label = ' ' * label.length - end - end - end + entry = [latest_spec.name] + + entry_versions entry, name_tuples, platforms + entry_details entry, latest_spec, specs, platforms + + entry.join + end + + def spec_authors entry, spec + authors = "Author#{spec.authors.length > 1 ? 's' : ''}: " + authors << spec.authors.join(', ') + entry << format_text(authors, 68, 4) + end + + def spec_homepage entry, spec + return if spec.homepage.nil? or spec.homepage.empty? + + entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4) + end + + def spec_license entry, spec + return if spec.license.nil? or spec.license.empty? - entry << "\n\n" << format_text(spec.summary, 68, 4) + licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: " + licenses << spec.licenses.join(', ') + entry << "\n" << format_text(licenses, 68, 4) + end + + def spec_loaded_from entry, spec, specs + return unless spec.loaded_from + + if specs.length == 1 then + default = spec.default_gem? ? ' (default)' : nil + entry << "\n" << " Installed at#{default}: #{spec.base_dir}" + else + label = 'Installed at' + specs.each do |s| + version = s.version.to_s + version << ', default' if s.default_gem? + entry << "\n" << " #{label} (#{version}): #{s.base_dir}" + label = ' ' * label.length end - output << entry end + end - say output.join(options[:details] ? "\n\n" : "\n") + def spec_platforms entry, platforms + non_ruby = platforms.any? do |_, pls| + pls.any? { |pl| pl != Gem::Platform::RUBY } + end + + return unless non_ruby + + if platforms.length == 1 then + title = platforms.values.length == 1 ? 'Platform' : 'Platforms' + entry << " #{title}: #{platforms.values.sort.join ', '}\n" + else + entry << " Platforms:\n" + platforms.sort_by do |version,| + version + end.each do |version, pls| + label = " #{version}: " + data = format_text pls.sort.join(', '), 68, label.length + data[0, label.length] = label + entry << data << "\n" + end + end + end + + def spec_summary entry, spec + entry << "\n\n" << format_text(spec.summary, 68, 4) end end diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 0b349bccc7..2c8b73a76b 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -622,7 +622,6 @@ class Gem::Specification File.join(Gem.default_dir, "specifications", "default") end - private def each_spec(search_dirs) # :nodoc: search_dirs.each { |dir| Dir[File.join(dir, "*.gemspec")].each { |path| diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index a652cecf2a..a04c733ccf 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -466,6 +466,19 @@ class Gem::TestCase < MiniTest::Unit::TestCase end ## + # Installs the provided default specs including writing the spec file + + def install_default_gems(*specs) + install_default_specs(*specs) + + specs.each do |spec| + open spec.loaded_from, 'w' do |io| + io.write spec.to_ruby_for_cache + end + end + end + + ## # Install the provided default specs def install_default_specs(*specs) @@ -572,7 +585,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase block = proc do |s| # Since Hash#each is unordered in 1.8, sort # the keys and iterate that way so the tests are - # deteriminstic on all implementations. + # deterministic on all implementations. deps.keys.sort.each do |n| s.add_dependency n, (deps[n] || '>= 0') end diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 475211dfe3..d672b9dec1 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -72,7 +72,19 @@ class Gem::Uninstaller # directory, and the cached .gem file. def uninstall - list = Gem::Specification.find_all_by_name(@gem, @version) + dependency = Gem::Dependency.new @gem, @version + + list = [] + + dirs = + Gem::Specification.dirs + + [Gem::Specification.default_specifications_dir] + + Gem::Specification.each_spec dirs do |spec| + next unless dependency.matches_spec? spec + + list << spec + end default_specs, list = list.partition do |spec| spec.default_gem? @@ -80,7 +92,7 @@ class Gem::Uninstaller list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir or - (@user_install and spec.base_dir == Gem.user_dir) + (@user_install and spec.base_dir == Gem.user_dir) end if list.empty? then diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb index 8ff62b4217..09e6efcd07 100644 --- a/test/rubygems/test_gem_commands_query_command.rb +++ b/test/rubygems/test_gem_commands_query_command.rb @@ -106,7 +106,6 @@ pl (1 i386-linux) @a2.summary = 'This is a lot of text. ' * 4 @a2.authors = ['Abraham Lincoln', 'Hirohito'] @a2.homepage = 'http://a.example.com/' - @a2.rubyforge_project = 'rubygems' util_clear_gems util_setup_spec_fetcher @a1, @a2, @pl1 @@ -123,7 +122,6 @@ pl (1 i386-linux) a (2) Authors: Abraham Lincoln, Hirohito - Rubyforge: http://rubyforge.org/projects/rubygems Homepage: http://a.example.com/ This is a lot of text. This is a lot of text. This is a lot of text. @@ -147,7 +145,6 @@ pl (1) @a2.summary = 'This is a lot of text. ' * 4 @a2.authors = ['Abraham Lincoln', 'Hirohito'] @a2.homepage = 'http://a.example.com/' - @a2.rubyforge_project = 'rubygems' @a2.platform = 'universal-darwin' util_clear_gems @@ -168,7 +165,6 @@ a (2, 1) 1: x86-linux 2: universal-darwin Authors: Abraham Lincoln, Hirohito - Rubyforge: http://rubyforge.org/projects/rubygems Homepage: http://a.example.com/ This is a lot of text. This is a lot of text. This is a lot of text. @@ -355,7 +351,6 @@ pl (1 i386-linux) @a2.summary = 'This is a lot of text. ' * 4 @a2.authors = ['Abraham Lincoln', 'Hirohito'] @a2.homepage = 'http://a.example.com/' - @a2.rubyforge_project = 'rubygems' @a2.platform = 'universal-darwin' util_clear_gems @@ -380,7 +375,6 @@ a (2, 1) 1: x86-linux 2: universal-darwin Authors: Abraham Lincoln, Hirohito - Rubyforge: http://rubyforge.org/projects/rubygems Homepage: http://a.example.com/ Installed at - - @@ -400,5 +394,43 @@ pl \(1\) assert_match expected, @ui.output end + def test_execute_default_details + default_gem_dir = Gem::Specification.default_specifications_dir + @a1.loaded_from = + File.join default_gem_dir, @a1.spec_name + + @cmd.handle_options %w[-l -d] + + use_ui @ui do + @cmd.execute + end + + str = @ui.output + + expected = <<-EOF + +*** LOCAL GEMS *** + +a (3.a, 2, 1) + Author: A User + Homepage: http://example.com + Installed at (3.a): #{@gemhome} + (2): #{@gemhome} + (1, default): #{@a1.base_dir} + + this is a summary + +pl \(1\) + Platform: i386-linux + Author: A User + Homepage: http://example.com + Installed at: #{@gemhome} + + this is a summary + EOF + + assert_equal expected, @ui.output + end + end diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb index 964ce85cc3..844c7b4b97 100644 --- a/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/test/rubygems/test_gem_commands_uninstall_command.rb @@ -175,23 +175,5 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase assert Gem::Specification.find_all_by_name('x').length == 0 end - def test_execute_default_gem - default_gem_spec = new_default_spec("default", "2.0.0.0", - nil, "default/gem.rb") - install_default_specs(default_gem_spec) - - ui = Gem::MockGemUi.new - - @cmd.options[:args] = %w[default] - @cmd.options[:executables] = true - - use_ui ui do - e = assert_raises Gem::InstallError do - @cmd.execute - end - assert_equal "gem \"default\" cannot be uninstalled because it is a default gem", - e.message - end - end end diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index f6fe4a9a4f..948318a5e3 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -172,6 +172,38 @@ class TestGemUninstaller < Gem::InstallerTestCase assert_same uninstaller, @post_uninstall_hook_arg end + def test_uninstall_default_gem + spec = new_default_spec 'default', '2' + + install_default_gems spec + + uninstaller = Gem::Uninstaller.new spec.name, :executables => true + + e = assert_raises Gem::InstallError do + uninstaller.uninstall + end + + assert_equal 'gem "default" cannot be uninstalled ' + + 'because it is a default gem', + e.message + end + + def test_uninstall_default_gem_with_same_version + default_spec = new_default_spec 'default', '2' + install_default_gems default_spec + + spec = new_spec 'default', '2' + install_gem spec + + Gem::Specification.reset + + uninstaller = Gem::Uninstaller.new spec.name, :executables => true + + uninstaller.uninstall + + refute_path_exists spec.gem_dir + end + def test_uninstall_nonexistent uninstaller = Gem::Uninstaller.new 'bogus', :executables => true @@ -265,8 +297,8 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_uninstall_prompts_about_broken_deps - util_gem 'r', '1', 'q' => '= 1' - util_gem 'q', '1' + quick_gem 'r', '1' do |s| s.add_dependency 'q', '= 1' end + quick_gem 'q', '1' un = Gem::Uninstaller.new('q') ui = Gem::MockGemUi.new("y\n") @@ -287,10 +319,10 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_uninstall_only_lists_unsatified_deps - util_gem 'r', '1', 'q' => '~> 1.0' - util_gem 'x', '1', 'q' => '= 1.0' - util_gem 'q', '1.0' - util_gem 'q', '1.1' + quick_gem 'r', '1' do |s| s.add_dependency 'q', '~> 1.0' end + quick_gem 'x', '1' do |s| s.add_dependency 'q', '= 1.0' end + quick_gem 'q', '1.0' + quick_gem 'q', '1.1' un = Gem::Uninstaller.new('q', :version => "1.0") ui = Gem::MockGemUi.new("y\n") @@ -311,9 +343,9 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_uninstall_doesnt_prompt_when_other_gem_satifies_requirement - util_gem 'r', '1', 'q' => '~> 1.0' - util_gem 'q', '1.0' - util_gem 'q', '1.1' + quick_gem 'r', '1' do |s| s.add_dependency 'q', '~> 1.0' end + quick_gem 'q', '1.0' + quick_gem 'q', '1.1' un = Gem::Uninstaller.new('q', :version => "1.0") ui = Gem::MockGemUi.new("y\n") @@ -328,11 +360,8 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_uninstall_doesnt_prompt_when_removing_a_dev_dep - util_gem('r', '1') do |s| - s.add_development_dependency "q", "= 1.0" - end - - util_gem 'q', '1.0' + quick_gem 'r', '1' do |s| s.add_development_dependency 'q', '= 1.0' end + quick_gem 'q', '1.0' un = Gem::Uninstaller.new('q', :version => "1.0") ui = Gem::MockGemUi.new("y\n") @@ -348,11 +377,11 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_uninstall_prompt_includes_dep_type - util_gem 'r', '1' do |s| + quick_gem 'r', '1' do |s| s.add_development_dependency 'q', '= 1' end - util_gem 'q', '1' + quick_gem 'q', '1' un = Gem::Uninstaller.new('q', :check_dev => true) ui = Gem::MockGemUi.new("y\n") |