class Maguro::Bitbucket
Constants
- API_BASE
- BITBUCKET
Attributes
app_name[R]
builder[R]
organization[R]
password[RW]
username[RW]
Public Class Methods
new(builder, app_name, organization)
click to toggle source
# File lib/maguro/bitbucket.rb, line 17 def initialize(builder, app_name, organization) @builder = builder @app_name = app_name @organization = organization self.username = nil self.password = nil end
Public Instance Methods
create_repo()
click to toggle source
# File lib/maguro/bitbucket.rb, line 39 def create_repo options = { scm: 'git', name: app_name, is_private: true, fork_policy: 'no_public_forks', language: 'ruby' } path = "#{API_BASE}/repositories/#{organization}/#{app_name}" response = bitbucket_api(path, Net::HTTP::Post, options) if response.code == "200" # Success puts "Successfully created repository for #{app_name}" else raise "Could not create Git repository for project #{app_name}" end end
delete_repo()
click to toggle source
# File lib/maguro/bitbucket.rb, line 59 def delete_repo path = "#{API_BASE}/repositories/#{organization}/#{app_name}" success_code = 204 response = bitbucket_api(path, Net::HTTP::Delete, {}, success_code) raise "Could not delete repository." if response.code != success_code.to_s puts "Successfully deleted repository: '#{app_name}'" end
get_repo()
click to toggle source
# File lib/maguro/bitbucket.rb, line 67 def get_repo path = "#{API_BASE}/repositories/#{organization}/#{app_name}" response = bitbucket_api(path, Net::HTTP::Get) # Do not raise on error, so that this method can be used # to query the existence of a repository return nil if response.code != "200" JSON.parse(response.body) end
git_url()
click to toggle source
# File lib/maguro/bitbucket.rb, line 25 def git_url if @git_url.nil? path = "#{API_BASE}/repositories/#{organization}/#{app_name}" response = bitbucket_api(path, Net::HTTP::Get) if response.code == "200" @git_url = JSON.parse(response.body)["links"]["clone"].find{|i| i["name"] == "https"}["href"] else raise "Could not retrieve Git url for project #{app_name}" end end @git_url end
Private Instance Methods
bitbucket_api(path, method, options = {}, expected_http_code = 200)
click to toggle source
# File lib/maguro/bitbucket.rb, line 80 def bitbucket_api(path, method, options = {}, expected_http_code = 200) puts "Making request to API at: #{path} via #{method} with options: #{options}" # TODO: Doug: do we want to enable this? # First, try to read the username and password from the OS X Keychain, # as stored by git credential-oskeychain # if username.nil? || password.nil? # output = %x[printf protocol=https\\\\nhost=#{BITBUCKET}\\\\n\\\\n | git credential-osxkeychain get] # m = output.match("password=(.*)\n") # self.password = m[1] if !m.nil? # m = output.match("username=(.*)\n") # self.username = m[1] if !m.nil? # end # Try to retrieve username and password directly from the OS X Keychain did_get_password_from_keychain = false if username.nil? || password.nil? credentials = Keychain.retrieve_account(BITBUCKET) if !credentials.nil? self.username = credentials[:username] self.password = credentials[:password] did_get_password_from_keychain = true end end tries = 0 response = nil should_store_in_keychain = false loop do tries += 1 if username.nil? || password.nil? # Prompt the user for password puts "" self.username = builder.ask "What is your BitBucket username?" puts "" # password = $stdin.noecho do # ask "BitBucket password?" # end self.password = builder.ask "What is your BitBucket password?", :echo => false puts "" puts "" if did_get_password_from_keychain || (builder.yes? "Do you want to store this BitBucket login info into the Keychain? (y/n)") should_store_in_keychain = true end puts "" end url = URI.parse(path) http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == 'https') request = method.new(url.path) if !options.empty? request["content-type"] = "application/json" request.body = options.to_json end request.basic_auth username, password response = http.request(request) response_code = response.code.to_i # Most REST calls return HTTP 200 on success. # Some calls return another status code on success, # E.g. DELETE returns 204 if response_code == expected_http_code # Success Keychain.add_account(BITBUCKET, username, password) if should_store_in_keychain return response end puts "Response code: #{response_code} message: #{response.message}" if !response.body.empty? message = JSON.parse(response.body)["error"]["message"] detail = JSON.parse(response.body)["error"]["detail"] puts "Error message: #{message}" puts "Error detail: #{detail}" if !detail.nil? end break if tries >= 3 # Try no more than three times break if response_code != 401 # Only retry when the username/password is incorrect # Clear password, so the next iteration of the loop will prompt the user if response_code == 401 self.username = nil self.password = nil if did_get_password_from_keychain # If we got credentials from the Keychain, and authentication fails, # clear the credentials from the keychain Keychain.delete_account(BITBUCKET) end end end # The request was unsuccessful response end