module Heroku::Helpers

Public Class Methods

disable_error_capture() click to toggle source
# File lib/heroku/helpers.rb, line 298
def self.disable_error_capture
  included_into.each do |base|
    base.send(:alias_method, :error, :error_without_failure)
  end
  extended_into.each do |base|
    class << base
      alias_method :error, :error_without_failure
    end
  end
end
enable_error_capture() click to toggle source
# File lib/heroku/helpers.rb, line 285
def self.enable_error_capture
  included_into.each do |base|
    base.send(:alias_method, :error_without_failure, :error)
    base.send(:alias_method, :error, :error_with_failure)
  end
  extended_into.each do |base|
    class << base
      alias_method :error_without_failure, :error
      alias_method :error, :error_with_failure
    end
  end
end
extended(base) click to toggle source
# File lib/heroku/helpers.rb, line 281
def self.extended(base)
  extended_into << base
end
extended_into() click to toggle source
# File lib/heroku/helpers.rb, line 273
def self.extended_into
  @@extended_into ||= []
end
included(base) click to toggle source
# File lib/heroku/helpers.rb, line 277
def self.included(base)
  included_into << base
end
included_into() click to toggle source
# File lib/heroku/helpers.rb, line 269
def self.included_into
  @@included_into ||= []
end

Public Instance Methods

action(message) { || ... } click to toggle source

DISPLAY HELPERS

# File lib/heroku/helpers.rb, line 229
def action(message)
  output_with_arrow("#{message}... ", false)
  Heroku::Helpers.enable_error_capture
  yield
  Heroku::Helpers.disable_error_capture
  display "done", false
  display(", #{@status}", false) if @status
  display
end
ask() click to toggle source
# File lib/heroku/helpers.rb, line 85
def ask
  STDIN.gets.strip
end
confirm(message="Are you sure you wish to continue? (y/n)?") click to toggle source
# File lib/heroku/helpers.rb, line 51
def confirm(message="Are you sure you wish to continue? (y/n)?")
  display("#{message} ", false)
  ask.downcase == 'y'
end
confirm_billing() click to toggle source
# File lib/heroku/helpers.rb, line 40
def confirm_billing
  display
  display "This action will cause your account to be billed at the end of the month"
  display "For more information, see http://devcenter.heroku.com/articles/billing"
  display "Are you sure you want to do this? (y/n) ", false
  if ask.downcase == 'y'
    heroku.confirm_billing
    return true
  end
end
confirm_command(app_to_confirm = app, message=nil) click to toggle source
# File lib/heroku/helpers.rb, line 56
def confirm_command(app_to_confirm = app, message=nil)
  raise(Heroku::Command::CommandFailed, "No app specified.\nRun this command from app folder or set it adding --app <app name>") unless app_to_confirm

  if respond_to?(:extract_option) && confirmed_app = extract_option('--confirm', false)
    unless confirmed_app == app_to_confirm
      raise(Heroku::Command::CommandFailed, "Confirmed app #{confirmed_app} did not match the selected app #{app_to_confirm}.")
    end
    return true
  else
    display
    message ||= "WARNING: Potentially Destructive Action\nThis command will affect the app: #{app_to_confirm}"
    message << "\nTo proceed, type \"#{app_to_confirm}\" or re-run this command with --confirm #{app_to_confirm}"
    output_with_bang(message)
    display
    display "> ", false
    if ask.downcase != app_to_confirm
      output_with_bang "Input did not match #{app_to_confirm}. Aborted."
      false
    else
      true
    end
  end
end
create_git_remote(remote, url) click to toggle source
# File lib/heroku/helpers.rb, line 154
def create_git_remote(remote, url)
  return if git('remote').split("\n").include?(remote)
  return unless File.exists?(".git")
  git "remote add #{remote} #{url}"
  display "Git remote #{remote} added"
end
deprecate(version) click to toggle source
# File lib/heroku/helpers.rb, line 30
def deprecate(version)
  display "!!! DEPRECATION WARNING: This command will be removed in version #{version}"
  display
end
display(msg="", new_line=true) click to toggle source
# File lib/heroku/helpers.rb, line 17
def display(msg="", new_line=true)
  if new_line
    puts(msg)
  else
    print(msg)
    STDOUT.flush
  end
end
display_header(message="", new_line=true) click to toggle source
# File lib/heroku/helpers.rb, line 310
def display_header(message="", new_line=true)
  return if message.to_s.strip == ""
  display("=== " + message.to_s.split("\n").join("\n=== "), new_line)
end
display_object(object) click to toggle source
# File lib/heroku/helpers.rb, line 315
def display_object(object)
  case object
  when Array
    # list of objects
    object.each do |item|
      display_object(item)
    end
  when Hash
    # if all values are arrays, it is a list with headers
    # otherwise it is a single header with pairs of data
    if object.values.all? {|value| value.is_a?(Array)}
      object.keys.sort_by {|key| key.to_s}.each do |key|
        display_header(key)
        display_object(object[key])
        hputs
      end
    end
  else
    hputs(object.to_s)
  end
end
display_row(row, lengths) click to toggle source
# File lib/heroku/helpers.rb, line 178
def display_row(row, lengths)
  row.zip(lengths).each do |column, length|
    format = column.is_a?(Fixnum) ? "%#{length}s  " : "%-#{length}s  "
    display format % column, false
  end
  display
end
display_table(objects, columns, headers) click to toggle source
# File lib/heroku/helpers.rb, line 165
def display_table(objects, columns, headers)
  lengths = []
  columns.each_with_index do |column, index|
    header = headers[index]
    lengths << longest([header].concat(objects.map { |o| o[column].to_s }))
  end
  display_row headers, lengths
  display_row lengths.map { |length| "-" * length }, lengths
  objects.each do |row|
    display_row columns.map { |column| row[column] }, lengths
  end
end
error(msg) click to toggle source
# File lib/heroku/helpers.rb, line 35
def error(msg)
  STDERR.puts(format_with_bang(msg))
  exit(1)
end
error_with_failure(message) click to toggle source
# File lib/heroku/helpers.rb, line 263
def error_with_failure(message)
  display "failed"
  STDERR.puts(format_with_bang(message))
  exit(1)
end
fail(message) click to toggle source
# File lib/heroku/helpers.rb, line 223
def fail(message)
  raise Heroku::Command::CommandFailed, message
end
format_bytes(amount) click to toggle source
# File lib/heroku/helpers.rb, line 141
def format_bytes(amount)
  amount = amount.to_i
  return '(empty)' if amount == 0
  return amount if amount < @@kb
  return "#{(amount / @@kb).round}k" if amount < @@mb
  return "#{(amount / @@mb).round}M" if amount < @@gb
  return "#{(amount / @@gb).round}G"
end
format_date(date) click to toggle source
# File lib/heroku/helpers.rb, line 80
def format_date(date)
  date = Time.parse(date) if date.is_a?(String)
  date.strftime("%Y-%m-%d %H:%M %Z")
end
format_with_bang(message) click to toggle source
# File lib/heroku/helpers.rb, line 253
def format_with_bang(message)
  return '' if message.to_s.strip == ""
  " !    " + message.split("\n").join("\n !    ")
end
get_terminal_environment() click to toggle source
# File lib/heroku/helpers.rb, line 217
def get_terminal_environment
  { "TERM" => ENV["TERM"], "COLUMNS" => %xtput cols`, "LINES" => %xtput lines` }
rescue
  { "TERM" => ENV["TERM"] }
end
git(args) click to toggle source
# File lib/heroku/helpers.rb, line 114
def git(args)
  return "" unless has_git?
  flattened_args = [args].flatten.compact.join(" ")
  %x{ git #{flattened_args} 2>&1 }.strip
end
has_git?() click to toggle source
# File lib/heroku/helpers.rb, line 109
def has_git?
  %x{ git --version }
  $?.success?
end
home_directory() click to toggle source
# File lib/heroku/helpers.rb, line 5
def home_directory
  running_on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
end
hprint(string='') click to toggle source
# File lib/heroku/helpers.rb, line 341
def hprint(string='')
  Kernel.print(string)
  STDOUT.flush
end
hputs(string='') click to toggle source
# File lib/heroku/helpers.rb, line 337
def hputs(string='')
  Kernel.puts(string)
end
json_decode(json) click to toggle source
# File lib/heroku/helpers.rb, line 192
def json_decode(json)
  Heroku::OkJson.decode(json)
rescue Heroku::OkJson::Error
  nil
end
json_encode(object) click to toggle source
# File lib/heroku/helpers.rb, line 186
def json_encode(object)
  Heroku::OkJson.encode(object)
rescue Heroku::OkJson::Error
  nil
end
longest(items) click to toggle source
# File lib/heroku/helpers.rb, line 161
def longest(items)
  items.map { |i| i.to_s.length }.sort.last
end
output(message="", new_line=true) click to toggle source
# File lib/heroku/helpers.rb, line 243
def output(message="", new_line=true)
  return if message.to_s.strip == ""
  display("      " + message.split("\n").join("\n      "), new_line)
end
output_with_arrow(message="", new_line=true) click to toggle source
# File lib/heroku/helpers.rb, line 248
def output_with_arrow(message="", new_line=true)
  return if message.to_s.strip == ""
  display("----> " + message.split("\n").join("\n      "), new_line)
end
output_with_bang(message="", new_line=true) click to toggle source
# File lib/heroku/helpers.rb, line 258
def output_with_bang(message="", new_line=true)
  return if message.to_s.strip == ""
  display(format_with_bang(message), new_line)
end
quantify(string, num) click to toggle source
# File lib/heroku/helpers.rb, line 150
def quantify(string, num)
  "%d %s" % [ num, num.to_i == 1 ? string : "#{string}s" ]
end
redisplay(line, line_break = false) click to toggle source
# File lib/heroku/helpers.rb, line 26
def redisplay(line, line_break = false)
  display("\r\e[0K#{line}", line_break)
end
retry_on_exception(*exceptions) { || ... } click to toggle source
# File lib/heroku/helpers.rb, line 97
def retry_on_exception(*exceptions)
  retry_count = 0
  begin
    yield
  rescue *exceptions => ex
    raise ex if retry_count >= 3
    sleep 3
    retry_count += 1
    retry
  end
end
run_command(command, args=[]) click to toggle source
# File lib/heroku/helpers.rb, line 93
def run_command(command, args=[])
  Heroku::Command.run(command, args)
end
running_on_a_mac?() click to toggle source
# File lib/heroku/helpers.rb, line 13
def running_on_a_mac?
  RUBY_PLATFORM =~ %r-darwin\d/
end
running_on_windows?() click to toggle source
# File lib/heroku/helpers.rb, line 9
def running_on_windows?
  RUBY_PLATFORM =~ %rmswin32|mingw32/
end
set_buffer(enable) click to toggle source
# File lib/heroku/helpers.rb, line 198
def set_buffer(enable)
  with_tty do
    if enable
      %xstty icanon echo`
    else
      %xstty -icanon -echo`
    end
  end
end
shell(cmd) click to toggle source
# File lib/heroku/helpers.rb, line 89
def shell(cmd)
  FileUtils.cd(Dir.pwd) {|d| return %x#{cmd}`}
end
status(message) click to toggle source
# File lib/heroku/helpers.rb, line 239
def status(message)
  @status = message
end
string_distance(first, last) click to toggle source
# File lib/heroku/helpers.rb, line 346
def string_distance(first, last)
  distances = [] # 0x0s
  0.upto(first.length) do |index|
    distances << [index] + [0] * last.length
  end
  distances[0] = 0.upto(last.length).to_a
  1.upto(last.length) do |last_index|
    1.upto(first.length) do |first_index|
      first_char = first[first_index - 1, 1]
      last_char = last[last_index - 1, 1]
      if first_char == last_char
        distances[first_index][last_index] = distances[first_index - 1][last_index - 1] # noop
      else
        distances[first_index][last_index] = [
          distances[first_index - 1][last_index],     # deletion
          distances[first_index][last_index - 1],     # insertion
          distances[first_index - 1][last_index - 1]  # substitution
        ].min + 1 # cost
        if first_index > 1 && last_index > 1
          first_previous_char = first[first_index - 2, 1]
          last_previous_char = last[last_index - 2, 1]
          if first_char == last_previous_char && first_previous_char == last_char
            distances[first_index][last_index] = [
              distances[first_index][last_index],
              distances[first_index - 2][last_index - 2] + 1 # transposition
            ].min
          end
        end
      end
    end
  end
  distances[first.length][last.length]
end
time_ago(elapsed) click to toggle source
# File lib/heroku/helpers.rb, line 120
def time_ago(elapsed)
  if elapsed < 60
    "#{elapsed.floor}s ago"
  elsif elapsed < (60 * 60)
    "#{(elapsed / 60).floor}m ago"
  else
    "#{(elapsed / 60 / 60).floor}h ago"
  end
end
truncate(text, length) click to toggle source
# File lib/heroku/helpers.rb, line 130
def truncate(text, length)
  if text.size > length
    text[0, length - 2] + '..'
  else
    text
  end
end
with_tty() { || ... } click to toggle source
# File lib/heroku/helpers.rb, line 208
def with_tty(&block)
  return unless $stdin.isatty
  begin
    yield
  rescue
    # fails on windows
  end
end