diff options
Diffstat (limited to 'lib/rubygems/commands')
-rw-r--r-- | lib/rubygems/commands/cert_command.rb | 37 | ||||
-rw-r--r-- | lib/rubygems/commands/cleanup_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/help_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/owner_command.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/commands/pristine_command.rb | 21 | ||||
-rw-r--r-- | lib/rubygems/commands/push_command.rb | 3 | ||||
-rw-r--r-- | lib/rubygems/commands/query_command.rb | 27 | ||||
-rw-r--r-- | lib/rubygems/commands/setup_command.rb | 193 | ||||
-rw-r--r-- | lib/rubygems/commands/signin_command.rb | 33 | ||||
-rw-r--r-- | lib/rubygems/commands/signout_command.rb | 33 | ||||
-rw-r--r-- | lib/rubygems/commands/uninstall_command.rb | 7 | ||||
-rw-r--r-- | lib/rubygems/commands/unpack_command.rb | 20 | ||||
-rw-r--r-- | lib/rubygems/commands/update_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/which_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/yank_command.rb | 15 |
15 files changed, 279 insertions, 122 deletions
diff --git a/lib/rubygems/commands/cert_command.rb b/lib/rubygems/commands/cert_command.rb index 7adf5b01b1..5542262a50 100644 --- a/lib/rubygems/commands/cert_command.rb +++ b/lib/rubygems/commands/cert_command.rb @@ -84,6 +84,11 @@ class Gem::Commands::CertCommand < Gem::Command options[:sign] << cert_file end + + add_option('-d', '--days NUMBER_OF_DAYS', + 'Days before the certificate expires') do |days, options| + options[:expiration_length_days] = days.to_i + end end def add_certificate certificate # :nodoc: @@ -105,16 +110,20 @@ class Gem::Commands::CertCommand < Gem::Command list_certificates_matching filter end - options[:build].each do |name| - build name + options[:build].each do |email| + build email end sign_certificates unless options[:sign].empty? end - def build name + def build email + if !valid_email?(email) + raise Gem::CommandLineError, "Invalid email address #{email}" + end + key, key_path = build_key - cert_path = build_cert name, key + cert_path = build_cert email, key say "Certificate: #{cert_path}" @@ -124,8 +133,16 @@ class Gem::Commands::CertCommand < Gem::Command end end - def build_cert name, key # :nodoc: - cert = Gem::Security.create_cert_email name, key + def build_cert email, key # :nodoc: + expiration_length_days = options[:expiration_length_days] + age = + if expiration_length_days.nil? || expiration_length_days == 0 + Gem::Security::ONE_YEAR + else + Gem::Security::ONE_DAY * expiration_length_days + end + + cert = Gem::Security.create_cert_email email, key, age Gem::Security.write cert, "gem-public_cert.pem" end @@ -273,5 +290,13 @@ For further reading on signing gems see `ri Gem::Security`. end end + private + + def valid_email? email + # It's simple, but is all we need + email =~ /\A.+@.+\z/ + end + + end if defined?(OpenSSL::SSL) diff --git a/lib/rubygems/commands/cleanup_command.rb b/lib/rubygems/commands/cleanup_command.rb index 83ee6b5c7c..db1bf3a794 100644 --- a/lib/rubygems/commands/cleanup_command.rb +++ b/lib/rubygems/commands/cleanup_command.rb @@ -66,7 +66,7 @@ If no gems are named all gems in GEM_HOME are cleaned. clean_gems end - say "Clean Up Complete" + say "Clean up complete" verbose do skipped = @default_gems.map { |spec| spec.full_name } diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb index de3f175fad..7d02022369 100644 --- a/lib/rubygems/commands/help_command.rb +++ b/lib/rubygems/commands/help_command.rb @@ -367,7 +367,7 @@ platform. elsif possibilities.size > 1 then alert_warning "Ambiguous command #{command_name} (#{possibilities.join(', ')})" else - alert_warning "Unknown command #{command_name}. Try: gem help commands" + alert_warning "Unknown command #{command_name}. Try: gem help commands" end end diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb index 4b99434e87..8e2271657a 100644 --- a/lib/rubygems/commands/owner_command.rb +++ b/lib/rubygems/commands/owner_command.rb @@ -40,7 +40,9 @@ permission to. options[:remove] << value end - add_option '-h', '--host HOST', 'Use another gemcutter-compatible host' do |value, options| + add_option '-h', '--host HOST', + 'Use another gemcutter-compatible host', + ' (e.g. https://rubygems.org)' do |value, options| options[:host] = value end end diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb index 6cab572b86..408672158f 100644 --- a/lib/rubygems/commands/pristine_command.rb +++ b/lib/rubygems/commands/pristine_command.rb @@ -125,14 +125,14 @@ extensions will be restored. next end - unless spec.extensions.empty? or options[:extensions] then + unless spec.extensions.empty? or options[:extensions] or options[:only_executables] then say "Skipped #{spec.full_name}, it needs to compile an extension" next end gem = spec.cache_file - unless File.exist? gem then + unless File.exist? gem or options[:only_executables] then require 'rubygems/remote_fetcher' say "Cached gem for #{spec.full_name} not found, attempting to fetch..." @@ -157,16 +157,19 @@ extensions will be restored. install_defaults.to_s['--env-shebang'] end - installer = Gem::Installer.at(gem, - :wrappers => true, - :force => true, - :install_dir => spec.base_dir, - :env_shebang => env_shebang, - :build_args => spec.build_args) - + installer_options = { + :wrappers => true, + :force => true, + :install_dir => spec.base_dir, + :env_shebang => env_shebang, + :build_args => spec.build_args, + } + if options[:only_executables] then + installer = Gem::Installer.for_spec(spec, installer_options) installer.generate_bin else + installer = Gem::Installer.at(gem, installer_options) installer.install end diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb index 6adeff6b30..d294cbc8df 100644 --- a/lib/rubygems/commands/push_command.rb +++ b/lib/rubygems/commands/push_command.rb @@ -33,7 +33,8 @@ command. For further discussion see the help for the yank command. add_key_option add_option('--host HOST', - 'Push to another gemcutter-compatible host') do |value, options| + 'Push to another gemcutter-compatible host', + ' (e.g. https://rubygems.org)') do |value, options| options[:host] = value end diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb index 44144203e0..4624e5a1e9 100644 --- a/lib/rubygems/commands/query_command.rb +++ b/lib/rubygems/commands/query_command.rb @@ -255,22 +255,21 @@ is too hard to use. name_tuples.map { |n| n.version }.uniq else platforms.sort.reverse.map do |version, pls| - if pls == [Gem::Platform::RUBY] then - if options[:domain] == :remote || specs.all? { |spec| spec.is_a? Gem::Source } - version - else - spec = specs.select { |s| s.version == version } - if spec.first.default_gem? - "default: #{version}" - else - version - end + out = version.to_s + + if options[:domain] == :local + default = specs.any? do |s| + !s.is_a?(Gem::Source) && s.version == version && s.default_gem? end - else - ruby = pls.delete Gem::Platform::RUBY - platform_list = [ruby, *pls.sort].compact - "#{version} #{platform_list.join ' '}" + out = "default: #{out}" if default + end + + if pls != [Gem::Platform::RUBY] then + platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact + out = platform_list.unshift(out).join(' ') end + + out end end diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index 2c29786224..f322ca9df5 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -15,10 +15,11 @@ class Gem::Commands::SetupCommand < Gem::Command super 'setup', 'Install RubyGems', :format_executable => true, :document => %w[ri], :site_or_vendor => 'sitelibdir', - :destdir => '', :prefix => '', :previous_version => '' + :destdir => '', :prefix => '', :previous_version => '', + :regenerate_binstubs => true add_option '--previous-version=VERSION', - 'Previous version of rubygems', + 'Previous version of RubyGems', 'Used for changelog processing' do |version, options| options[:previous_version] = version end @@ -42,7 +43,7 @@ class Gem::Commands::SetupCommand < Gem::Command add_option '--[no-]format-executable', 'Makes `gem` match ruby', - 'If ruby is ruby18, gem will be gem18' do |value, options| + 'If Ruby is ruby18, gem will be gem18' do |value, options| options[:format_executable] = value end @@ -79,6 +80,15 @@ class Gem::Commands::SetupCommand < Gem::Command options[:document].uniq! end + add_option '--[no-]regenerate-binstubs', + 'Regenerate gem binstubs' do |value, options| + if value then + options[:regenerate_binstubs] = true + else + options.delete(:regenerate_binstubs) + end + end + @verbose = nil end @@ -92,7 +102,7 @@ class Gem::Commands::SetupCommand < Gem::Command end def defaults_str # :nodoc: - "--format-executable --document ri" + "--format-executable --document ri --regenerate-binstubs" end def description # :nodoc: @@ -142,8 +152,12 @@ By default, this RubyGems will install gem as: remove_old_lib_files lib_dir + install_default_bundler_gem + say "RubyGems #{Gem::VERSION} installed" + regenerate_binstubs + uninstall_old_gemcutter documentation_success = install_rdoc @@ -190,7 +204,7 @@ By default, this RubyGems will install gem as: if options[:document].include? 'ri' then say "Ruby Interactive (ri) documentation was installed. ri is kind of like man " - say "pages for ruby libraries. You may access it like this:" + say "pages for Ruby libraries. You may access it like this:" say " ri Classname" say " ri Classname.class_method" say " ri Classname#instance_method" @@ -202,59 +216,64 @@ By default, this RubyGems will install gem as: end end - def install_executables(bin_dir) - say "Installing gem executable" if @verbose + def install_executables(bin_dir) @bin_file_names = [] - Dir.chdir 'bin' do - bin_files = Dir['*'] + executables = { 'gem' => 'bin' } + executables['bundler'] = 'bundler/exe' if Gem::USE_BUNDLER_FOR_GEMDEPS + executables.each do |tool, path| + say "Installing #{tool} executable" if @verbose - bin_files.delete 'update_rubygems' + Dir.chdir path do + bin_files = Dir['*'] - bin_files.each do |bin_file| - bin_file_formatted = if options[:format_executable] then - Gem.default_exec_format % bin_file - else - bin_file - end + bin_files -= %w[update_rubygems bundler bundle_ruby] - dest_file = File.join bin_dir, bin_file_formatted - bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}" + bin_files.each do |bin_file| + bin_file_formatted = if options[:format_executable] then + Gem.default_exec_format % bin_file + else + bin_file + end - begin - bin = File.readlines bin_file - bin[0] = "#!#{Gem.ruby}\n" + dest_file = File.join bin_dir, bin_file_formatted + bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}" - File.open bin_tmp_file, 'w' do |fp| - fp.puts bin.join - end - - install bin_tmp_file, dest_file, :mode => 0755 - @bin_file_names << dest_file - ensure - rm bin_tmp_file - end - - next unless Gem.win_platform? + begin + bin = File.readlines bin_file + bin[0] = "#!#{Gem.ruby}\n" - begin - bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat" + File.open bin_tmp_file, 'w' do |fp| + fp.puts bin.join + end - File.open bin_cmd_file, 'w' do |file| - file.puts <<-TEXT -@ECHO OFF -IF NOT "%~f0" == "~f0" GOTO :WinNT -@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9 -GOTO :EOF -:WinNT -@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %* -TEXT + install bin_tmp_file, dest_file, :mode => 0755 + @bin_file_names << dest_file + ensure + rm bin_tmp_file end - install bin_cmd_file, "#{dest_file}.bat", :mode => 0755 - ensure - rm bin_cmd_file + next unless Gem.win_platform? + + begin + bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat" + + File.open bin_cmd_file, 'w' do |file| + file.puts <<-TEXT + @ECHO OFF + IF NOT "%~f0" == "~f0" GOTO :WinNT + @"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9 + GOTO :EOF + :WinNT + @"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %* + TEXT + end + + install bin_cmd_file, "#{dest_file}.bat", :mode => 0755 + ensure + rm bin_cmd_file + end end end end @@ -269,18 +288,22 @@ TEXT end def install_lib(lib_dir) - say "Installing RubyGems" if @verbose + libs = { 'RubyGems' => 'lib' } + libs['Bundler'] = 'bundler/lib' if Gem::USE_BUNDLER_FOR_GEMDEPS + libs.each do |tool, path| + say "Installing #{tool}" if @verbose - lib_files = rb_files_in 'lib' - pem_files = pem_files_in 'lib' + lib_files = rb_files_in path + pem_files = pem_files_in path - Dir.chdir 'lib' do - lib_files.each do |lib_file| - install_file lib_file, lib_dir - end + Dir.chdir path do + lib_files.each do |lib_file| + install_file lib_file, lib_dir + end - pem_files.each do |pem_file| - install_file pem_file, lib_dir + pem_files.each do |pem_file| + install_file pem_file, lib_dir + end end end end @@ -326,6 +349,29 @@ TEXT return false end + def install_default_bundler_gem + return unless Gem::USE_BUNDLER_FOR_GEMDEPS + + bundler_spec = Gem::Specification.load("bundler/bundler.gemspec") + bundler_spec.files = Dir["bundler/{*.md,{lib,exe,man}/**/*}"] + bundler_spec.executables -= %w[bundler bundle_ruby] + Dir.entries(Gem::Specification.default_specifications_dir). + select {|gs| gs.start_with?("bundler-") }. + each {|gs| File.delete(File.join(Gem::Specification.default_specifications_dir, gs)) } + + default_spec_path = File.join(Gem::Specification.default_specifications_dir, "#{bundler_spec.full_name}.gemspec") + Gem.write_binary(default_spec_path, bundler_spec.to_ruby) + + bundler_spec = Gem::Specification.load(default_spec_path) + + Dir.entries(bundler_spec.gems_dir). + select {|default_gem| default_gem.start_with?("bundler-") }. + each {|default_gem| rm_r File.join(bundler_spec.gems_dir, default_gem) } + + mkdir_p bundler_spec.bin_dir + bundler_spec.executables.each {|e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_spec.bin_dir, e) } + end + def make_destination_dirs(install_destdir) lib_dir, bin_dir = Gem.default_rubygems_dirs @@ -397,7 +443,7 @@ TEXT old_bin_path = File.join bin_dir, old_bin_file next unless File.exist? old_bin_path - deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead." + deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead." File.open old_bin_path, 'w' do |fp| fp.write <<-EOF @@ -416,23 +462,26 @@ abort "#{deprecation_message}" end def remove_old_lib_files lib_dir - rubygems_dir = File.join lib_dir, 'rubygems' - lib_files = rb_files_in 'lib/rubygems' + lib_dirs = { File.join(lib_dir, 'rubygems') => 'lib/rubygems' } + lib_dirs[File.join(lib_dir, 'bundler')] = 'bundler/lib/bundler' if Gem::USE_BUNDLER_FOR_GEMDEPS + lib_dirs.each do |old_lib_dir, new_lib_dir| + lib_files = rb_files_in(new_lib_dir) - old_lib_files = rb_files_in rubygems_dir + old_lib_files = rb_files_in(old_lib_dir) - to_remove = old_lib_files - lib_files + to_remove = old_lib_files - lib_files - to_remove.delete_if do |file| - file.start_with? 'defaults' - end + to_remove.delete_if do |file| + file.start_with? 'defaults' + end - Dir.chdir rubygems_dir do - to_remove.each do |file| - FileUtils.rm_f file + Dir.chdir old_lib_dir do + to_remove.each do |file| + FileUtils.rm_f file - warn "unable to remove old file #{file} please remove it by hand" if - File.exist? file + warn "unable to remove old file #{file} please remove it by hand" if + File.exist? file + end end end end @@ -480,5 +529,11 @@ abort "#{deprecation_message}" rescue Gem::InstallError end -end + def regenerate_binstubs + require "rubygems/commands/pristine_command" + say "Regenerating binstubs" + command = Gem::Commands::PristineCommand.new + command.invoke(*%w[--all --only-executables --silent]) + end +end diff --git a/lib/rubygems/commands/signin_command.rb b/lib/rubygems/commands/signin_command.rb new file mode 100644 index 0000000000..6556db5a89 --- /dev/null +++ b/lib/rubygems/commands/signin_command.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +require 'rubygems/command' +require 'rubygems/gemcutter_utilities' + +class Gem::Commands::SigninCommand < Gem::Command + include Gem::GemcutterUtilities + + def initialize + super 'signin', 'Sign in to any gemcutter-compatible host. '\ + 'It defaults to https://rubygems.org' + + add_option('--host HOST', 'Push to another gemcutter-compatible host') do |value, options| + options[:host] = value + end + + end + + def description # :nodoc: + 'The signin command executes host sign in for a push server (the default is'\ + ' https://rubygems.org). The host can be provided with the host flag or can'\ + ' be inferred from the provided gem. Host resolution matches the resolution'\ + ' strategy for the push command.' + end + + def usage # :nodoc: + program_name + end + + def execute + sign_in options[:host] + end + +end diff --git a/lib/rubygems/commands/signout_command.rb b/lib/rubygems/commands/signout_command.rb new file mode 100644 index 0000000000..2452e8cae1 --- /dev/null +++ b/lib/rubygems/commands/signout_command.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +require 'rubygems/command' + +class Gem::Commands::SignoutCommand < Gem::Command + + def initialize + super 'signout', 'Sign out from all the current sessions.' + end + + def description # :nodoc: + 'The `signout` command is used to sign out from all current sessions,'\ + ' allowing you to sign in using a different set of credentials.' + end + + def usage # :nodoc: + program_name + end + + def execute + credentials_path = Gem.configuration.credentials_path + + if !File.exist?(credentials_path) then + alert_error 'You are not currently signed in.' + elsif !File.writable?(credentials_path) then + alert_error "File '#{Gem.configuration.credentials_path}' is read-only."\ + ' Please make sure it is writable.' + else + Gem.configuration.unset_api_key! + say 'You have successfully signed out from all sessions.' + end + end + +end diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb index fe97790194..20b3a7a1e4 100644 --- a/lib/rubygems/commands/uninstall_command.rb +++ b/lib/rubygems/commands/uninstall_command.rb @@ -30,7 +30,7 @@ class Gem::Commands::UninstallCommand < Gem::Command options[:ignore] = value end - add_option('-D', '--[no-]-check-development', + add_option('-D', '--[no-]check-development', 'Check development dependencies while uninstalling', '(default: false)') do |value, options| options[:check_dev] = value @@ -143,7 +143,9 @@ that is a dependency of an existing gem. You can use the deplist = Gem::DependencyList.new get_all_gem_names.uniq.each do |name| - Gem::Specification.find_all_by_name(name).each do |spec| + gem_specs = Gem::Specification.find_all_by_name(name) + say("Gem '#{name}' is not installed") if gem_specs.empty? + gem_specs.each do |spec| deplist.add spec end end @@ -162,4 +164,3 @@ that is a dependency of an existing gem. You can use the end end - diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb index ffa429de6f..eb7f550673 100644 --- a/lib/rubygems/commands/unpack_command.rb +++ b/lib/rubygems/commands/unpack_command.rb @@ -2,11 +2,20 @@ require 'rubygems/command' require 'rubygems/installer' require 'rubygems/version_option' +require 'rubygems/security_option' require 'rubygems/remote_fetcher' +# forward-declare + +module Gem::Security # :nodoc: + class Policy # :nodoc: + end +end + class Gem::Commands::UnpackCommand < Gem::Command include Gem::VersionOption + include Gem::SecurityOption def initialize require 'fileutils' @@ -24,6 +33,7 @@ class Gem::Commands::UnpackCommand < Gem::Command options[:spec] = true end + add_security_option add_version_option end @@ -63,6 +73,8 @@ command help for an example. # at the same time.) def execute + security_policy = options[:security_policy] + get_all_gem_names.each do |name| dependency = Gem::Dependency.new name, options[:version] path = get_path dependency @@ -73,7 +85,7 @@ command help for an example. end if @options[:spec] then - spec, metadata = get_metadata path + spec, metadata = get_metadata path, security_policy if metadata.nil? then alert_error "--spec is unsupported on '#{name}' (old format gem)" @@ -89,7 +101,7 @@ command help for an example. basename = File.basename path, '.gem' target_dir = File.expand_path basename, options[:target] - package = Gem::Package.new path + package = Gem::Package.new path, security_policy package.extract_files target_dir say "Unpacked gem: '#{target_dir}'" @@ -158,8 +170,8 @@ command help for an example. #-- # TODO move to Gem::Package as #raw_spec or something - def get_metadata path - format = Gem::Package.new path + def get_metadata path, security_policy = nil + format = Gem::Package.new path, security_policy spec = format.spec metadata = nil diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index f3d70a92a6..93ee60e1ab 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -70,7 +70,7 @@ command to remove old versions. def check_latest_rubygems version # :nodoc: if Gem.rubygems_version == version then - say "Latest version currently installed. Aborting." + say "Latest version already installed. Done." terminate_interaction end diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb index c028d5d49f..704d79fc60 100644 --- a/lib/rubygems/commands/which_command.rb +++ b/lib/rubygems/commands/which_command.rb @@ -56,7 +56,7 @@ requiring to see why it does not behave as you expect. paths = find_paths arg, dirs if paths.empty? then - alert_error "Can't find ruby library file or shared library #{arg}" + alert_error "Can't find Ruby library file or shared library #{arg}" found &&= false else diff --git a/lib/rubygems/commands/yank_command.rb b/lib/rubygems/commands/yank_command.rb index 0d6575b272..ebf24e5c77 100644 --- a/lib/rubygems/commands/yank_command.rb +++ b/lib/rubygems/commands/yank_command.rb @@ -11,19 +11,11 @@ class Gem::Commands::YankCommand < Gem::Command def description # :nodoc: <<-EOF -The yank command removes a gem you pushed to a server from the server's -index. - -Note that if you push a gem to rubygems.org the yank command does not -prevent other people from downloading the gem via the download link. +The yank command permanently removes a gem you pushed to a server. Once you have pushed a gem several downloads will happen automatically -via the webhooks. If you accidentally pushed passwords or other sensitive +via the webhooks. If you accidentally pushed passwords or other sensitive data you will need to change them immediately and yank your gem. - -If you are yanking a gem due to intellectual property reasons contact -http://help.rubygems.org for permanent removal. Be sure to mention this -as the reason for the removal request. EOF end @@ -42,7 +34,8 @@ as the reason for the removal request. add_platform_option("remove") add_option('--host HOST', - 'Yank from another gemcutter-compatible host') do |value, options| + 'Yank from another gemcutter-compatible host', + ' (e.g. https://rubygems.org)') do |value, options| options[:host] = value end |