aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/cmd/gist-logs.rb
blob: 53b4962e023d65cf94dc13ebc92f34251a85be18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
require 'formula'
require 'cmd/config'
require 'net/http'
require 'net/https'
require 'stringio'

module Homebrew
  def gistify_logs f
    if ARGV.include? '--new-issue'
      unless HOMEBREW_GITHUB_API_TOKEN
        puts 'You need to create an API token: https://github.com/settings/applications'
        puts 'and then set HOMEBREW_GITHUB_API_TOKEN to use --new-issue option.'
        exit 1
      end
    end

    files = load_logs(f.name)

    s = StringIO.new
    Homebrew.dump_verbose_config(s)
    files["config.out"] = { :content => s.string }
    files["doctor.out"] = { :content => `brew doctor 2>&1` }

    url = create_gist(files)

    if ARGV.include? '--new-issue'
      url = new_issue(f.tap, "#{f.name} failed to build on #{MACOS_FULL_VERSION}", url)
    end

    ensure puts url if url
  end

  def load_logs name
    logs = {}
    dir = HOMEBREW_LOGS/name
    dir.children.sort.each do |file|
      contents = file.size? ? file.read : "empty log"
      logs[file.basename.to_s] = { :content => contents }
    end if dir.exist?
    raise 'No logs.' if logs.empty?
    logs
  end

  def create_gist files
    post("/gists", "public" => true, "files" => files)["html_url"]
  end

  def new_issue repo, title, body
    post("/repos/#{repo}/issues", "title" => title, "body" => body)["html_url"]
  end

  def http
    @http ||= begin
      uri = URI.parse('https://api.github.com')
      p = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : nil
      if p.class == URI::HTTP or p.class == URI::HTTPS
        @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

  def make_request(path, data)
    headers = {
      "User-Agent"   => HOMEBREW_USER_AGENT,
      "Accept"       => "application/vnd.github.v3+json",
      "Content-Type" => "application/json",
    }

    if HOMEBREW_GITHUB_API_TOKEN
      headers["Authorization"] = "token #{HOMEBREW_GITHUB_API_TOKEN}"
    end

    request = Net::HTTP::Post.new(path, headers)
    request.body = Utils::JSON.dump(data)
    request
  end

  def post(path, data)
    request = make_request(path, data)

    case response = http.request(request)
    when Net::HTTPCreated
      Utils::JSON.load get_body(response)
    else
      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
    if ARGV.formulae.length != 1
      puts "usage: brew gist-logs [--new-issue] <formula>"
      Homebrew.failed = true
      return
    end

    gistify_logs(ARGV.formulae[0])
  end
end