123456789_123456789_123456789_123456789_123456789_

Class: Gem::Command

Overview

Base class for all ::Gem commands. When creating a new gem command, define #initialize, #execute, #arguments, #defaults_str, #description and #usage (as appropriate). See the above mentioned methods for details.

A very good example to look at is Commands::ContentsCommand

Constant Summary

  • HELP = Internal use only
    # File 'lib/rubygems/command.rb', line 627
    <<-HELP.freeze
    RubyGems is a package manager for Ruby.
    
    Usage:
      gem -h/--help
      gem -v/--version
      gem command [arguments...] [options...]
    
    Examples:
      gem install rake
      gem list --local
      gem build package.gemspec
      gem push package-0.0.1.gem
      gem help install
    
    Further help:
      gem help commands            list all 'gem' commands
      gem help examples            show some examples of usage
      gem help gem_dependencies    gem dependencies file guide
      gem help platforms           gem platforms guide
      gem help <COMMAND>           show help on COMMAND
                                     (e.g. 'gem help install')
      gem server                   present a web page at
                                   http://localhost:8808/
                                   with info about installed gems
    Further information:
      https://guides.rubygems.org
    HELP

Class Attribute Summary

Class Method Summary

Instance Attribute Summary

DefaultUserInteraction - Included

Instance Method Summary

UserInteraction - Included

#alert

Displays an alert statement.

#alert_error

Displays an error statement to the error output location.

#alert_warning

Displays a warning statement to the warning output location.

#ask

Asks a question and returns the answer.

#ask_for_password

Asks for a password with a prompt

#ask_yes_no

Asks a yes or no question.

#choose_from_list

Asks the user to answer question with an answer from the given list.

#say

Displays the given statement on the standard output (or equivalent).

#terminate_interaction

Terminates the RubyGems process with the given exit_code

#verbose

Calls say with msg or the results of the block if really_verbose is true.

DefaultUserInteraction - Included

Text - Included

#clean_text

Remove any non-printable characters and make the text suitable for printing.

#format_text

Wraps text to #wrap characters and optionally indents by indent characters.

#levenshtein_distance

This code is based directly on the Text gem implementation Returns a value representing the “cost” of transforming str1 into str2.

#truncate_text, #min3

Constructor Details

.new(command, summary = nil, defaults = {}) ⇒ Command

Initializes a generic gem command named #command. #summary is a short description displayed in gem help commands. #defaults are the default options. Defaults should be mirrored in #defaults_str, unless there are none.

When defining a new command subclass, use add_option to add command-line switches.

Unhandled arguments (gem names, files, etc.) are left in options[:args].

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 121

def initialize(command, summary=nil, defaults={})
  @command = command
  @summary = summary
  @program_name = "gem #{command}"
  @defaults = defaults
  @options = defaults.dup
  @option_groups = Hash.new {|h,k| h[k] = [] }
  @deprecated_options = { command => {} }
  @parser = nil
  @when_invoked = nil
end

Class Attribute Details

.build_args (rw)

Arguments used when building gems

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 54

def self.build_args
  @build_args ||= []
end

.build_args=(value) (rw)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 58

def self.build_args=(value)
  @build_args = value
end

.extra_args (rw)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 70

def self.extra_args
  @extra_args ||= []
end

.extra_args=(value) (rw)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 74

def self.extra_args=(value)
  case value
  when Array
    @extra_args = value
  when String
    @extra_args = value.split(' ')
  end
end

Class Method Details

.add_common_option(*args, &handler)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 66

def self.add_common_option(*args, &handler)
  Gem::Command.common_options << [args, handler]
end

.add_specific_extra_args(cmd, args)

Add a list of extra arguments for the given command. args may be an array or a string to be split on white space.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 95

def self.add_specific_extra_args(cmd,args)
  args = args.split(/\s+/) if args.kind_of? String
  specific_extra_args_hash[cmd] = args
end

.common_options

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 62

def self.common_options
  @common_options ||= []
end

.specific_extra_args(cmd)

Return an array of extra arguments for the command. The extra arguments come from the gem configuration file read at program startup.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 87

def self.specific_extra_args(cmd)
  specific_extra_args_hash[cmd]
end

.specific_extra_args_hash

Accessor for the specific extra args hash (self initializing).

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 103

def self.specific_extra_args_hash
  @specific_extra_args_hash ||= Hash.new do |h,k|
    h[k] = Array.new
  end
end

Instance Attribute Details

#command (readonly)

The name of the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 29

attr_reader :command

#defaults (rw)

The default options for the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 39

attr_accessor :defaults

#deprecated?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 469

def deprecated?
  false
end

#options (readonly)

The options for the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 34

attr_reader :options

#program_name (rw)

The name of the command for command-line invocation.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 44

attr_accessor :program_name

#summary (rw)

A short description of the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 49

attr_accessor :summary

Instance Method Details

#add_extra_args(args)

Adds extra args from ~/.gemrc

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 451

def add_extra_args(args)
  result = []

  s_extra = Gem::Command.specific_extra_args(@command)
  extra = Gem::Command.extra_args + s_extra

  until extra.empty? do
    ex = []
    ex << extra.shift
    ex << extra.shift if extra.first.to_s =~ /^[^-]/ # rubocop:disable Performance/StartWith
    result << ex if handles?(ex)
  end

  result.flatten!
  result.concat(args)
  result
end

#add_option(*opts, &handler)

Add a command-line option and handler to the command.

See OptionParser#make_switch for an explanation of opts.

handler will be called with two values, the value of the argument and the options hash.

If the first argument of add_option is a Symbol, it’s used to group options in output. See gem help list for an example.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 355

def add_option(*opts, &handler) # :yields: value, options
  group_name = Symbol === opts.first ? opts.shift : :options

  raise "Do not pass an empty string in opts" if opts.include?("")

  @option_groups[group_name] << [opts, handler]
end

#add_parser_description (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 479

def add_parser_description # :nodoc:
  return unless description

  formatted = description.split("\n\n").map do |chunk|
    wrap chunk, 80 - 4
  end.join "\n"

  @parser.separator nil
  @parser.separator "  Description:"
  formatted.split("\n").each do |line|
    @parser.separator "    #{line.rstrip}"
  end
end

#add_parser_options (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 493

def add_parser_options # :nodoc:
  @parser.separator nil

  regular_options = @option_groups.delete :options

  configure_options "", regular_options

  @option_groups.sort_by {|n,_| n.to_s }.each do |group_name, option_list|
    @parser.separator nil
    configure_options group_name, option_list
  end
end

#add_parser_run_info(title, content) (private)

Adds a section with title and content to the parser help view. Used for adding command arguments and default arguments.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 510

def add_parser_run_info(title, content)
  return if content.empty?

  @parser.separator nil
  @parser.separator "  #{title}:"
  content.split(/\n/).each do |line|
    @parser.separator "    #{line}"
  end
end

#add_parser_summary (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 520

def add_parser_summary # :nodoc:
  return unless @summary

  @parser.separator nil
  @parser.separator "  Summary:"
  wrap(@summary, 80 - 4).split("\n").each do |line|
    @parser.separator "    #{line.strip}"
  end
end

#arguments

Override to provide details of the arguments a command takes. It should return a left-justified string, one argument per line.

For example:

def usage
  "#{program_name} FILE [FILE ...]"
end

def arguments
  "FILE          name of file to find"
end
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 255

def arguments
  ""
end

#begins?(long, short) ⇒ Boolean

True if long begins with the characters from short.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 136

def begins?(long, short)
  return false if short.nil?
  long[0, short.length] == short
end

#check_deprecated_options(options)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 394

def check_deprecated_options(options)
  options.each do |option|
    if option_is_deprecated?(option)
      deprecation = @deprecated_options[command][option]
      version_to_expire = deprecation["rg_version_to_expire"]

      deprecate_option_msg = if version_to_expire
                               "The \"#{option}\" option has been deprecated and will be removed in Rubygems #{version_to_expire}."
                             else
                               "The \"#{option}\" option has been deprecated and will be removed in future versions of Rubygems."
                             end

      extra_msg = deprecation["extra_msg"]

      deprecate_option_msg += " #{extra_msg}" if extra_msg

      alert_warning(deprecate_option_msg)
    end
  end
end

#configure_options(header, option_list) (private)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 556

def configure_options(header, option_list)
  return if option_list.nil? or option_list.empty?

  header = header.to_s.empty? ? '' : "#{header} "
  @parser.separator "  #{header}Options:"

  option_list.each do |args, handler|
    @parser.on(*args) do |value|
      handler.call(value, @options)
    end
  end

  @parser.separator ''
end

#create_option_parser (private)

Creates an option parser and fills it in with the help info for the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 542

def create_option_parser
  @parser = Gem::OptionParser.new

  add_parser_options

  @parser.separator nil
  configure_options "Common", Gem::Command.common_options

  add_parser_run_info "Arguments", arguments
  add_parser_summary
  add_parser_description
  add_parser_run_info "Defaults", defaults_str
end

#defaults_str

Override to display the default values of the command options. (similar to #arguments, but displays the default values).

For example:

def defaults_str
  --no-gems-first --no-all
end
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 269

def defaults_str
  ""
end

#deprecate_option(name, version: nil, extra_msg: nil)

Mark a command-line option as deprecated, and optionally specify a deprecation horizon.

Note that with the current implementation, every version of the option needs to be explicitly deprecated, so to deprecate an option defined as

add_option('-t', '--[no-]test', 'Set test mode') do |value, options|
  # ... stuff ...
end

you would need to explicitly add a call to deprecate_option for every version of the option you want to deprecate, like

deprecate_option('-t')
deprecate_option('--test')
deprecate_option('--no-test')
[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 390

def deprecate_option(name, version: nil, extra_msg: nil)
  @deprecated_options[command].merge!({ name => { "rg_version_to_expire" => version, "extra_msg" => extra_msg } })
end

#description

Override to display a longer description of what this command does.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 276

def description
  nil
end

#execute

Override to provide command handling.

#options will be filled in with your parsed options, unparsed options will be left in options[:args].

See also: #get_all_gem_names, #get_one_gem_name, #get_one_optional_argument

Raises:

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 150

def execute
  raise Gem::Exception, "generic command has no actions"
end

#get_all_gem_names

Get all gem names from the command line.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 186

def get_all_gem_names
  args = options[:args]

  if args.nil? or args.empty?
    raise Gem::CommandLineError,
          "Please specify at least one gem name (e.g. gem build GEMNAME)"
  end

  args.select {|arg| arg !~ /^-/ }
end

#get_all_gem_names_and_versions

Get all [gem, version] from the command line.

An argument in the form gem:ver is pull apart into the gen name and version, respectively.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 202

def get_all_gem_names_and_versions
  get_all_gem_names.map do |name|
    if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name
      [$1, $2]
    else
      [name]
    end
  end
end

#get_one_gem_name

Get a single gem name from the command line. Fail if there is no gem name or if there is more than one gem name given.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 216

def get_one_gem_name
  args = options[:args]

  if args.nil? or args.empty?
    raise Gem::CommandLineError,
          "Please specify a gem name on the command line (e.g. gem build GEMNAME)"
  end

  if args.size > 1
    raise Gem::CommandLineError,
          "Too many gem names (#{args.join(', ')}); please specify only one"
  end

  args.first
end

#get_one_optional_argument

Get a single optional argument from the command line. If more than one argument is given, return only the first. Return nil if none are given.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 236

def get_one_optional_argument
  args = options[:args] || []
  args.first
end

#handle_options(args)

Handle the given list of arguments by parsing them and recording the results.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 440

def handle_options(args)
  args = add_extra_args(args)
  check_deprecated_options(args)
  @options = Marshal.load Marshal.dump @defaults # deep copy
  parser.parse!(args)
  @options[:args] = args
end

#handles?(args) ⇒ Boolean

True if the command handles the given argument list.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 427

def handles?(args)
  begin
    parser.parse!(args.dup)
    return true
  rescue
    return false
  end
end

#invoke(*args)

Invoke the command with the given list of arguments.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 300

def invoke(*args)
  invoke_with_build_args args, nil
end

#invoke_with_build_args(args, build_args)

Invoke the command with the given list of normal arguments and additional build arguments.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 308

def invoke_with_build_args(args, build_args)
  handle_options args

  options[:build_args] = build_args

  if options[:silent]
    old_ui = self.ui
    self.ui = ui = Gem::SilentUI.new
  end

  if options[:help]
    show_help
  elsif @when_invoked
    @when_invoked.call options
  else
    execute
  end
ensure
  if ui
    self.ui = old_ui
    ui.close
  end
end

#merge_options(new_options)

Merge a set of command options with the set of default options (without modifying the default option hash).

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 419

def merge_options(new_options)
  @options = @defaults.clone
  new_options.each {|k,v| @options[k] = v }
end

#option_is_deprecated?(option) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 475

def option_is_deprecated?(option)
  @deprecated_options[command].has_key?(option)
end

#parser (private)

Create on demand parser.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 533

def parser
  create_option_parser if @parser.nil?
  @parser
end

#remove_option(name)

Remove previously defined command-line argument name.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 366

def remove_option(name)
  @option_groups.each do |_, option_list|
    option_list.reject! {|args, _| args.any? {|x| x.is_a?(String) && x =~ /^#{name}/ } }
  end
end

#show_help

Display the help message for the command.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 292

def show_help
  parser.program_name = usage
  say parser
end

#show_lookup_failure(gem_name, version, errors, suppress_suggestions = false, required_by = nil)

Display to the user that a gem couldn’t be found and reasons why –

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 158

def show_lookup_failure(gem_name, version, errors, suppress_suggestions = false, required_by = nil)
  gem = "'#{gem_name}' (#{version})"
  msg = String.new "Could not find a valid gem #{gem}"

  if errors and !errors.empty?
    msg << ", here is why:\n"
    errors.each {|x| msg << "          #{x.wordy}\n" }
  else
    if required_by and gem != required_by
      msg << " (required by #{required_by}) in any repository"
    else
      msg << " in any repository"
    end
  end

  alert_error msg

  unless suppress_suggestions
    suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name(gem_name, :latest, 10)
    unless suggestions.empty?
      alert_error "Possible alternatives: #{suggestions.join(", ")}"
    end
  end
end

#usage

Override to display the usage for an individual gem command.

The text “[options]” is automatically appended to the usage text.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 285

def usage
  program_name
end

#when_invoked(&block)

Call the given block when invoked.

Normal command invocations just executes the #execute method of the command. Specifying an invocation block allows the test methods to override the normal action of a command to determine that it has been invoked correctly.

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 340

def when_invoked(&block)
  @when_invoked = block
end

#wrap(text, width) (private)

Wraps text to width

[ GitHub ]

  
# File 'lib/rubygems/command.rb', line 574

def wrap(text, width) # :doc:
  text.gsub(/(.{1,#{width}})( +|$\n?)|(.{1,#{width}})/, "\\1\\3\n")
end