aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Library/Homebrew/cmd/gist-logs.rb19
-rw-r--r--Library/Homebrew/utils.rb76
2 files changed, 76 insertions, 19 deletions
diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb
index acc9a10ea..5954c031e 100644
--- a/Library/Homebrew/cmd/gist-logs.rb
+++ b/Library/Homebrew/cmd/gist-logs.rb
@@ -37,12 +37,12 @@ module Homebrew
if ARGV.include?("--new-issue") || ARGV.switch?("n")
auth = :AUTH_TOKEN
- unless GitHub.api_credentials
+ if GitHub.api_credentials_type == :none
puts "You can create a personal access token: https://github.com/settings/tokens"
puts "and then set HOMEBREW_GITHUB_API_TOKEN as authentication method."
puts
- auth = :AUTH_BASIC
+ auth = :AUTH_USER_LOGIN
end
url = new_issue(f.tap, "#{f.name} failed to build on #{MacOS.full_version}", url, auth)
@@ -118,9 +118,21 @@ module Homebrew
headers = GitHub.api_headers
headers["Content-Type"] = "application/json"
+ basic_auth_credentials = nil
+ if auth != :AUTH_USER_LOGIN
+ token, username = GitHub.api_credentials
+ case GitHub.api_credentials_type
+ when :keychain
+ basic_auth_credentials = [username, token]
+ when :environment
+ headers["Authorization"] = "token #{token}"
+ end
+ end
+
request = Net::HTTP::Post.new(path, headers)
+ request.basic_auth(*basic_auth_credentials) if basic_auth_credentials
- login(request) if auth == :AUTH_BASIC
+ login(request) if auth == :AUTH_USER_LOGIN
request.body = Utils::JSON.dump(data)
request
@@ -133,6 +145,7 @@ module Homebrew
when Net::HTTPCreated
Utils::JSON.load get_body(response)
else
+ GitHub.api_credentials_error_message(response)
raise "HTTP #{response.code} #{response.message} (expected 201)"
end
end
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 1fbb5afac..98ebcc9c8 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -484,7 +484,7 @@ module GitHub
class RateLimitExceededError < Error
def initialize(reset, error)
super <<-EOS.undent
- GitHub #{error}
+ GitHub API Error: #{error}
Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token:
#{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
@@ -506,9 +506,12 @@ module GitHub
EOS
else
message << <<-EOS.undent
- The GitHub credentials in the OS X keychain are invalid.
+ The GitHub credentials in the OS X keychain may be invalid.
Clear them with:
printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
+ Or create a personal access token:
+ #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
+ and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
EOS
end
super message
@@ -536,32 +539,71 @@ module GitHub
end
end
- def api_headers
- @api_headers ||= begin
- headers = {
- "User-Agent" => HOMEBREW_USER_AGENT,
- "Accept" => "application/vnd.github.v3+json"
- }
- token, username = api_credentials
- if token && !token.empty?
- if username && !username.empty?
- headers[:http_basic_authentication] = [username, token]
- else
- headers["Authorization"] = "token #{token}"
+ def api_credentials_type
+ token, username = api_credentials
+ if token && !token.empty?
+ if username && !username.empty?
+ :keychain
+ else
+ :environment
+ end
+ else
+ :none
+ end
+ end
+
+ def api_credentials_error_message(response_headers)
+ @api_credentials_error_message_printed ||= begin
+ unauthorized = (response_headers["status"] == "401 Unauthorized")
+ scopes = response_headers["x-accepted-oauth-scopes"].to_s.split(", ")
+ if !unauthorized && scopes.empty?
+ credentials_scopes = response_headers["x-oauth-scopes"].to_s.split(", ")
+
+ case GitHub.api_credentials_type
+ when :keychain
+ onoe <<-EOS.undent
+ Your OS X keychain GitHub credentials do not have sufficient scope!
+ Scopes they have: #{credentials_scopes}
+ Create a personal access token: https://github.com/settings/tokens
+ and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
+ EOS
+ when :environment
+ onoe <<-EOS.undent
+ Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope!
+ Scopes it has: #{credentials_scopes}
+ Create a new personal access token: https://github.com/settings/tokens
+ and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
+ EOS
end
end
- headers
+ true
end
end
+ def api_headers
+ {
+ "User-Agent" => HOMEBREW_USER_AGENT,
+ "Accept" => "application/vnd.github.v3+json"
+ }
+ end
+
def open(url, &_block)
# This is a no-op if the user is opting out of using the GitHub API.
return if ENV["HOMEBREW_NO_GITHUB_API"]
require "net/https"
+ headers = api_headers
+ token, username = api_credentials
+ case api_credentials_type
+ when :keychain
+ headers[:http_basic_authentication] = [username, token]
+ when :environment
+ headers["Authorization"] = "token #{token}"
+ end
+
begin
- Kernel.open(url, api_headers) { |f| yield Utils::JSON.load(f.read) }
+ Kernel.open(url, headers) { |f| yield Utils::JSON.load(f.read) }
rescue OpenURI::HTTPError => e
handle_api_error(e)
rescue EOFError, SocketError, OpenSSL::SSL::SSLError => e
@@ -578,6 +620,8 @@ module GitHub
raise RateLimitExceededError.new(reset, error)
end
+ GitHub.api_credentials_error_message(e.io.meta)
+
case e.io.status.first
when "401", "403"
raise AuthenticationFailedError.new(e.message)