class Razor::CLI::Command

Public Class Methods

arg_type(arg_name, cmd_schema) click to toggle source
# File lib/razor/cli/command.rb, line 81
def self.arg_type(arg_name, cmd_schema)
  # Short-circuit to allow this as a work-around for backwards compatibility.
  return nil if arg_name == 'json'
  return nil unless cmd_schema.is_a?(Hash)
  return cmd_schema[arg_name]['type'] if cmd_schema.has_key?(arg_name)
  return nil
end
convert_arg(arg_name, value, existing_value, cmd_schema) click to toggle source

`cmd_name`: The name of the command being executed. `arg_name`: The name of the argument being formatted. `value`: The original value provided by the user. `existing_value`: The value already assigned to this variable

by previous calls to this method. The new `value` will be
concatenated to an array or hash if an array/hash is
accepted by the command for the given argument.
# File lib/razor/cli/command.rb, line 96
def self.convert_arg(arg_name, value, existing_value, cmd_schema)
  value = nil if value == "null"

  argument_type = arg_type(arg_name, cmd_schema)

  # This might be helpful, since there's no other method for debug-level logging on the client.
  puts _("Formatting argument %{argument_name} with value %{value} as %{argument_type}\n") %
           {argument_name: arg_name, value: value, argument_type: argument_type} if @dump_response

  case argument_type
    when "array"
      existing_value ||= []
      begin
        existing_value + Array(MultiJson::load(value))
      rescue MultiJson::LoadError => _
        existing_value + Array(value)
      end
    when "object"
      existing_value ||= {}
      begin
        if value =~ /\A(.+?)=(.+)?\z/
          # `--arg name=value`
          existing_value.merge($1 => $2)
        else
          MultiJson::load(value).tap do |value|
            value.is_a?(Hash) or raise ArgumentError, _("Invalid object for argument '%{argument_name}'") % {argument_name: arg_name}
            existing_value.merge(value)
          end
        end
      rescue MultiJson::LoadError => error
        raise ArgumentError, _("Invalid object for argument '%{argument_name}': %{error}") %
            {argument_name: arg_name, error: error.message}
      end
    when "boolean"
      raise ArgumentError, _("Invalid boolean for argument '%{argument_name}': %{value}") %
          {argument_name: arg_name, value: value} unless ["true", "false", nil].include?(value)
      value != "false"
    when "number"
      begin
        Integer(value)
      rescue ArgumentError
        raise ArgumentError, _("Invalid integer for argument '%{argument_name}': %{value}") % {argument_name: arg_name, value: value}
      end
    when "null"
      raise ArgumentError, _("Expected nothing for argument '%{argument_name}', but was: '%{value}'") %
          {argument_name: arg_name, value: value} unless value.nil?
      nil
    when "string", nil # `nil` for 'might be an alias, send as-is'
      value
    else
      raise Razor::CLI::Error, _("Unexpected datatype '%{argument_type}' for argument %{argument_name}") % {argument_type: argument_type, argument_name: arg_name}
  end
end
new(parse, navigate, command, segments, cmd_url) click to toggle source
# File lib/razor/cli/command.rb, line 2
def initialize(parse, navigate, command, segments, cmd_url)
  @dump_response = parse && parse.dump_response?
  @show_command_help = parse && parse.show_command_help?
  @navigate = navigate
  @command = command
  @cmd_schema = command ? command['schema'] : nil
  @cmd_url = cmd_url
  @segments = segments
end
resolve_alias(arg_name, cmd_schema) click to toggle source
# File lib/razor/cli/command.rb, line 150
def self.resolve_alias(arg_name, cmd_schema)
  return arg_name if cmd_schema[arg_name]
  cmd_schema.find do |other_attr, metadata|
    if metadata && metadata.has_key?('aliases')
      return other_attr if metadata['aliases'].find {|aliaz| aliaz == arg_name}
    end
  end
  # No results; return the same name to generate a reasonable error message.
  arg_name
end

Public Instance Methods

extract_command() click to toggle source
# File lib/razor/cli/command.rb, line 28
def extract_command
  body = {}
  pos_index = 0
  until @segments.empty?
    argument = @segments.shift
    if argument =~ /\A--([a-z][a-z_-]+)(=(.+))?\Z/ or
        argument =~ /\A-([a-z])(=(.+))?\Z/
      # `--arg=value`/`--arg value`
      # `-a=value`/`-a value`
      arg_name, value = [$1, $3]
      value = @segments.shift if value.nil? && @segments[0] !~ /^-[-]?[a-z]/
      arg_name = self.class.resolve_alias(arg_name, @cmd_schema)
      body[arg_name] = self.class.convert_arg(arg_name, value, body[arg_name], @cmd_schema)
    elsif argument =~ /\A-([a-z][a-z_-]+)(=(.+))?\Z/ and
          @cmd_schema[self.class.resolve_alias($1, @cmd_schema)]
      # Short form, should be long; offer suggestion
      raise ArgumentError, _("Unexpected argument %{argument} (did you mean %{suggestion}?)") % {argument: argument, suggestion: "--#{$1}"}
    elsif argument =~ /\A--([a-z])(=(.+))?\Z/ and
          @cmd_schema[self.class.resolve_alias($1, @cmd_schema)]
      # Long form, should be short; offer suggestion
      raise ArgumentError, _("Unexpected argument %{argument} (did you mean %{suggestion}?)") % {argument: argument, suggestion: "-#{$1}"}
    else
      # This may be a positional argument.
      arg_name = positional_argument(@cmd_schema, pos_index)
      if arg_name
        body[arg_name] = self.class.convert_arg(arg_name, argument, body[arg_name], @cmd_schema)
        pos_index += 1
      else
        raise ArgumentError, _("Unexpected argument %{argument}") % {argument: argument}
      end
    end
  end

  begin
    body = MultiJson::load(File::read(body["json"])) if body["json"]
  rescue MultiJson::LoadError
    raise Razor::CLI::Error, _("File %{path} is not valid JSON") % {path: body['json']}
  rescue Errno::ENOENT
    raise Razor::CLI::Error, _("File %{path} not found") % {path: body['json']}
  rescue Errno::EACCES
    raise Razor::CLI::Error,
          _("Permission to read file %{path} denied") % {path: body['json']}
  end
  body
end
positional_argument(cmd_schema, pos_index) click to toggle source
# File lib/razor/cli/command.rb, line 74
def positional_argument(cmd_schema, pos_index)
  # Find a matching position and return its argument name.
  cmd_schema && cmd_schema.select do |_, schema|
    schema['position'] == pos_index
  end.keys.first
end
run() click to toggle source
# File lib/razor/cli/command.rb, line 12
def run
  body = extract_command
  if @show_command_help
    @command
  else
    if body.empty?
      raise Razor::CLI::Error,
            _("No arguments for command (did you forget --json ?)")
    end
    result = @navigate.json_post(@cmd_url, body)
    # Get actual object from the id.
    result = result.merge(@navigate.json_get(URI.parse(result['id']))) if result['id']
    result
  end
end