class Rabbit::GemPusher

Public Class Methods

new(gem_path, user) click to toggle source
# File lib/rabbit/gem-pusher.rb, line 29
def initialize(gem_path, user)
  @gem_path = gem_path
  @user = user
end

Public Instance Methods

push() click to toggle source
# File lib/rabbit/gem-pusher.rb, line 34
def push
  credentials_path = File.expand_path("~/.gem/credentials")
  credentials_path_exist = File.exist?(credentials_path)
  if credentials_path_exist
    credentials = YAMLLoader.load(File.read(credentials_path))
  else
    credentials = {}
  end
  unless credentials.key?(@user.to_sym)
    credentials[@user.to_sym] = retrieve_api_key
    FileUtils.mkdir_p(File.dirname(credentials_path))
    File.open(credentials_path, "w") do |credentials_file|
      credentials_file.print(credentials.to_yaml)
    end
    unless credentials_path_exist
      File.chmod(0600, credentials_path)
    end
  end
  ruby("-S", "gem", "push", @gem_path,
       "--key", @user)
end

Private Instance Methods

mfa_error?(error) click to toggle source
# File lib/rabbit/gem-pusher.rb, line 83
def mfa_error?(error)
  return false unless error.message.start_with?("401 ")
  body = error.io.read
  body.start_with?("You have enabled multifactor authentication")
end
retrieve_api_key() click to toggle source
# File lib/rabbit/gem-pusher.rb, line 57
def retrieve_api_key
  prompt = _("Enter password on RubyGems.org [%{user}]: ") % {:user => @user}
  reader = PasswordReader.new(prompt)
  password = reader.read
  begin
    URI.open("https://rubygems.org/api/v1/api_key.yaml",
             :http_basic_authentication => [@user, password]) do |response|
      YAMLLoader.load(response.read)[:rubygems_api_key]
    end
  rescue OpenURI::HTTPError => error
    if mfa_error?(error)
      prompt = _("Enter OTP on RubyGems.org [%{user}]: ") % {:user => @user}
      # TODO: We don't need to hide input.
      reader = PasswordReader.new(prompt)
      otp = reader.read
      URI.open("https://rubygems.org/api/v1/api_key.yaml",
               :http_basic_authentication => [@user, password],
               "OTP" => otp) do |response|
        YAMLLoader.load(response.read)[:rubygems_api_key]
      end
    else
      raise
    end
  end
end