2015-08-03 13:09:07 +01:00
|
|
|
require "formula"
|
|
|
|
require "cmd/config"
|
|
|
|
require "net/http"
|
|
|
|
require "net/https"
|
|
|
|
require "stringio"
|
2015-10-16 05:41:50 -04:00
|
|
|
require "socket"
|
2014-09-20 14:25:09 +01:00
|
|
|
|
|
|
|
module Homebrew
|
2015-08-03 13:09:07 +01:00
|
|
|
def gistify_logs(f)
|
2015-04-25 22:07:06 -04:00
|
|
|
files = load_logs(f.logs)
|
2015-10-16 05:41:50 -04:00
|
|
|
build_time = f.logs.ctime
|
|
|
|
timestamp = build_time.strftime("%Y-%m-%d_%H-%M-%S")
|
2014-09-20 14:25:09 +01:00
|
|
|
|
|
|
|
s = StringIO.new
|
|
|
|
Homebrew.dump_verbose_config(s)
|
2015-10-16 05:41:50 -04:00
|
|
|
# Dummy summary file, asciibetically first, to control display title of gist
|
|
|
|
files["# #{f.name} - #{timestamp}.txt"] = { :content => brief_build_info(f) }
|
|
|
|
files["00.config.out"] = { :content => s.string }
|
|
|
|
files["00.doctor.out"] = { :content => `brew doctor 2>&1` }
|
2015-02-11 17:29:56 +08:00
|
|
|
unless f.core_formula?
|
|
|
|
tap = <<-EOS.undent
|
|
|
|
Formula: #{f.name}
|
|
|
|
Tap: #{f.tap}
|
|
|
|
Path: #{f.path}
|
|
|
|
EOS
|
2015-10-16 05:41:50 -04:00
|
|
|
files["00.tap.out"] = { :content => tap }
|
2015-02-11 17:29:56 +08:00
|
|
|
end
|
2014-09-20 14:25:09 +01:00
|
|
|
|
2015-10-16 05:41:50 -04:00
|
|
|
# Description formatted to work well as page title when viewing gist
|
|
|
|
if f.core_formula?
|
|
|
|
descr = "#{f.name} on #{OS_VERSION} - Homebrew build logs"
|
|
|
|
else
|
|
|
|
descr = "#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs"
|
|
|
|
end
|
|
|
|
url = create_gist(files, descr)
|
2014-09-20 14:25:09 +01:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
if ARGV.include?("--new-issue") || ARGV.switch?("n")
|
2014-11-10 23:32:02 +01:00
|
|
|
auth = :AUTH_TOKEN
|
|
|
|
|
2016-03-25 18:35:06 +08:00
|
|
|
if GitHub.api_credentials_type == :none
|
2015-08-03 13:09:07 +01:00
|
|
|
puts "You can create a personal access token: https://github.com/settings/tokens"
|
|
|
|
puts "and then set HOMEBREW_GITHUB_API_TOKEN as authentication method."
|
2014-11-10 23:32:02 +01:00
|
|
|
puts
|
|
|
|
|
2016-03-25 18:35:06 +08:00
|
|
|
auth = :AUTH_USER_LOGIN
|
2014-11-10 23:32:02 +01:00
|
|
|
end
|
|
|
|
|
2015-10-16 16:41:14 +08:00
|
|
|
url = new_issue(f.tap, "#{f.name} failed to build on #{MacOS.full_version}", url, auth)
|
2014-09-20 14:25:09 +01:00
|
|
|
end
|
|
|
|
|
2014-11-10 23:32:02 +01:00
|
|
|
puts url if url
|
|
|
|
end
|
|
|
|
|
2015-10-16 05:41:50 -04:00
|
|
|
def brief_build_info(f)
|
|
|
|
build_time_str = f.logs.ctime.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
s = <<-EOS.undent
|
|
|
|
Homebrew build logs for #{f.full_name} on #{OS_VERSION}
|
|
|
|
EOS
|
|
|
|
if ARGV.include?("--with-hostname")
|
|
|
|
hostname = Socket.gethostname
|
|
|
|
s << "Host: #{hostname}\n"
|
|
|
|
end
|
|
|
|
s << "Build date: #{build_time_str}\n"
|
|
|
|
s
|
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
# Hack for ruby < 1.9.3
|
2014-11-10 23:32:02 +01:00
|
|
|
def noecho_gets
|
2015-08-03 13:09:07 +01:00
|
|
|
system "stty -echo"
|
2014-11-10 23:32:02 +01:00
|
|
|
result = $stdin.gets
|
2015-08-03 13:09:07 +01:00
|
|
|
system "stty echo"
|
2014-11-10 23:32:02 +01:00
|
|
|
puts
|
|
|
|
result
|
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def login(request)
|
|
|
|
print "GitHub User: "
|
2014-11-10 23:32:02 +01:00
|
|
|
user = $stdin.gets.chomp
|
2015-08-03 13:09:07 +01:00
|
|
|
print "Password: "
|
2014-11-10 23:32:02 +01:00
|
|
|
password = noecho_gets.chomp
|
|
|
|
puts
|
|
|
|
request.basic_auth(user, password)
|
2014-09-20 14:25:09 +01:00
|
|
|
end
|
|
|
|
|
2015-04-25 22:07:06 -04:00
|
|
|
def load_logs(dir)
|
2014-09-20 14:25:09 +01:00
|
|
|
logs = {}
|
|
|
|
dir.children.sort.each do |file|
|
|
|
|
contents = file.size? ? file.read : "empty log"
|
|
|
|
logs[file.basename.to_s] = { :content => contents }
|
|
|
|
end if dir.exist?
|
2015-08-03 13:09:07 +01:00
|
|
|
raise "No logs." if logs.empty?
|
2014-09-20 14:25:09 +01:00
|
|
|
logs
|
|
|
|
end
|
|
|
|
|
2015-10-16 05:41:50 -04:00
|
|
|
def create_gist(files, descr)
|
|
|
|
post("/gists", { "public" => true, "files" => files, "description" => descr })["html_url"]
|
2014-09-20 14:25:09 +01:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def new_issue(repo, title, body, auth)
|
2014-11-10 23:32:02 +01:00
|
|
|
post("/repos/#{repo}/issues", { "title" => title, "body" => body }, auth)["html_url"]
|
2014-09-20 14:25:09 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def http
|
|
|
|
@http ||= begin
|
2015-08-03 13:09:07 +01:00
|
|
|
uri = URI.parse("https://api.github.com")
|
|
|
|
p = ENV["http_proxy"] ? URI.parse(ENV["http_proxy"]) : nil
|
|
|
|
if p.class == URI::HTTP || p.class == URI::HTTPS
|
2014-09-20 14:25:09 +01:00
|
|
|
@http = Net::HTTP.new(uri.host, uri.port, p.host, p.port, p.user, p.password)
|
|
|
|
else
|
|
|
|
@http = Net::HTTP.new(uri.host, uri.port)
|
|
|
|
end
|
|
|
|
@http.use_ssl = true
|
|
|
|
@http
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-11-10 23:32:02 +01:00
|
|
|
def make_request(path, data, auth)
|
2016-03-08 11:43:39 +00:00
|
|
|
headers = GitHub.api_headers
|
|
|
|
headers["Content-Type"] = "application/json"
|
2014-09-20 14:25:09 +01:00
|
|
|
|
2016-03-25 18:35:06 +08:00
|
|
|
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
|
|
|
|
|
2014-09-20 14:25:09 +01:00
|
|
|
request = Net::HTTP::Post.new(path, headers)
|
2016-03-25 18:35:06 +08:00
|
|
|
request.basic_auth(*basic_auth_credentials) if basic_auth_credentials
|
2014-11-10 23:32:02 +01:00
|
|
|
|
2016-03-25 18:35:06 +08:00
|
|
|
login(request) if auth == :AUTH_USER_LOGIN
|
2014-11-10 23:32:02 +01:00
|
|
|
|
2014-09-20 14:25:09 +01:00
|
|
|
request.body = Utils::JSON.dump(data)
|
|
|
|
request
|
|
|
|
end
|
|
|
|
|
2014-11-10 23:32:02 +01:00
|
|
|
def post(path, data, auth = nil)
|
|
|
|
request = make_request(path, data, auth)
|
2014-09-20 14:25:09 +01:00
|
|
|
|
|
|
|
case response = http.request(request)
|
|
|
|
when Net::HTTPCreated
|
|
|
|
Utils::JSON.load get_body(response)
|
|
|
|
else
|
2016-03-25 18:35:06 +08:00
|
|
|
GitHub.api_credentials_error_message(response)
|
2014-09-20 14:25:09 +01:00
|
|
|
raise "HTTP #{response.code} #{response.message} (expected 201)"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_body(response)
|
|
|
|
if !response.body.respond_to?(:force_encoding)
|
|
|
|
response.body
|
|
|
|
elsif response["Content-Type"].downcase == "application/json; charset=utf-8"
|
|
|
|
response.body.dup.force_encoding(Encoding::UTF_8)
|
|
|
|
else
|
|
|
|
response.body.encode(Encoding::UTF_8, :undef => :replace)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def gist_logs
|
2015-05-17 20:27:43 +08:00
|
|
|
if ARGV.resolved_formulae.length != 1
|
2014-11-10 23:32:02 +01:00
|
|
|
puts "usage: brew gist-logs [--new-issue|-n] <formula>"
|
2014-09-20 14:25:09 +01:00
|
|
|
Homebrew.failed = true
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2015-05-17 20:27:43 +08:00
|
|
|
gistify_logs(ARGV.resolved_formulae[0])
|
2014-09-20 14:25:09 +01:00
|
|
|
end
|
|
|
|
end
|