command_aliases()
click to toggle source
def self.command_aliases
@@command_aliases ||= {}
end
commands()
click to toggle source
def self.commands
@@commands ||= {}
end
current_args()
click to toggle source
def self.current_args
@current_args
end
current_command()
click to toggle source
def self.current_command
@current_command
end
current_options()
click to toggle source
def self.current_options
@current_options
end
files()
click to toggle source
def self.files
@@files ||= Hash.new {|hash,key| hash[key] = File.readlines(key).map {|line| line.strip}}
end
global_option(name, *args)
click to toggle source
def self.global_option(name, *args)
global_options << { :name => name, :args => args }
end
global_options()
click to toggle source
def self.global_options
@global_options ||= []
end
load()
click to toggle source
def self.load
Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do |file|
require file
end
Heroku::Plugin.load!
end
namespaces()
click to toggle source
def self.namespaces
@@namespaces ||= {}
end
parse(cmd)
click to toggle source
def self.parse(cmd)
commands[cmd] || commands[command_aliases[cmd]]
end
parse_error_json(body)
click to toggle source
def self.parse_error_json(body)
json = json_decode(body.to_s) rescue false
json ? json['error'] : nil
end
parse_error_plain(body)
click to toggle source
def self.parse_error_plain(body)
return unless body.respond_to?(:headers) && body.headers[:content_type].to_s.include?("text/plain")
body.to_s
end
parse_error_xml(body)
click to toggle source
def self.parse_error_xml(body)
xml_errors = REXML::Document.new(body).elements.to_a("//errors/error")
msg = xml_errors.map { |a| a.text }.join(" / ")
return msg unless msg.empty?
rescue Exception
end
prepare_run(cmd, args=[])
click to toggle source
def self.prepare_run(cmd, args=[])
command = parse(cmd)
unless command
if %w( -v --version ).include?(cmd)
display Heroku::VERSION
exit
end
output_with_bang("`#{cmd}` is not a heroku command.")
distances = {}
(commands.keys + command_aliases.keys).each do |suggestion|
distance = string_distance(cmd, suggestion)
distances[distance] ||= []
distances[distance] << suggestion
end
if distances.keys.min < 4
suggestions = distances[distances.keys.min].sort
if suggestions.length == 1
output_with_bang("Perhaps you meant `#{suggestions.first}`.")
else
output_with_bang("Perhaps you meant #{suggestions[0...-1].map {|suggestion| "`#{suggestion}`"}.join(', ')} or `#{suggestions.last}`.")
end
end
output_with_bang("See `heroku help` for additional details.")
exit(1)
end
@current_command = cmd
opts = {}
invalid_options = []
parser = OptionParser.new do |parser|
parser.on("--version") do |value|
invalid_options << "--version"
end
global_options.each do |global_option|
parser.on(*global_option[:args]) do |value|
opts[global_option[:name]] = value
end
end
command[:options].each do |name, option|
parser.on("-#{option[:short]}", "--#{option[:long]}", option[:desc]) do |value|
opts[name.gsub("-", "_").to_sym] = value
end
end
end
begin
parser.order!(args) do |nonopt|
invalid_options << nonopt
end
rescue OptionParser::InvalidOption => ex
invalid_options << ex.args.first
retry
end
if opts[:help]
args.unshift cmd unless cmd =~ %r^-.*/
cmd = "help"
command = parse(cmd)
end
args.concat(invalid_options)
@current_args = args
@current_options = opts
[ command[:klass].new(args.dup, opts.dup), command[:method] ]
end
register_command(command)
click to toggle source
def self.register_command(command)
commands[command[:command]] = command
end
register_namespace(namespace)
click to toggle source
def self.register_namespace(namespace)
namespaces[namespace[:name]] = namespace
end
run(cmd, arguments=[])
click to toggle source
def self.run(cmd, arguments=[])
object, method = prepare_run(cmd, arguments.dup)
object.send(method)
rescue RestClient::Unauthorized
puts "Authentication failure"
unless ENV['HEROKU_API_KEY']
run "login"
retry
end
rescue RestClient::PaymentRequired => e
retry if run('account:confirm_billing', arguments.dup)
rescue RestClient::ResourceNotFound => e
error extract_error(e.http_body) {
e.http_body =~ %r^[\w\s]+ not found.?$/ ? e.http_body : "Resource not found"
}
rescue RestClient::Locked => e
app = e.response.headers[:x_confirmation_required]
if confirm_command(app, extract_error(e.response.body))
arguments << '--confirm' << app
retry
end
rescue RestClient::RequestFailed => e
error extract_error(e.http_body)
rescue RestClient::RequestTimeout
error "API request timed out. Please try again, or contact support@heroku.com if this issue persists."
rescue CommandFailed => e
error e.message
rescue OptionParser::ParseError => ex
commands[cmd] ? run("help", [cmd]) : run("help")
end