aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Contributions/examples/brew-pull.rb
blob: 30d04120b984b883873455b00c59da90e354e4b4 (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
# Gets a patch from a GitHub commit or pull request and applies it to Homebrew.
# Optionally, installs it too.

require 'utils.rb'

if ARGV.include? '--install'
  ARGV.delete '--install'
  install = true
end

if ARGV.empty?
  onoe 'This command requires at least one argument containing a URL or pull request number'
end

HOMEBREW_REPOSITORY.cd do
  ARGV.named.each do|arg|
    if arg.to_i > 0
      url = 'https://github.com/mxcl/homebrew/pull/' + arg + '.patch'
    else
      # This regex should work, if it's too precise, feel free to fix it.
      urlmatch = arg.match 'https:\/\/github.com\/\w+\/homebrew\/(pull\/(\d+)|commit\/\w{4,40})'
      if !urlmatch
        ohai 'Ignoring URL:', "Not a GitHub pull request or commit: #{arg}"
        next
      end

      # GitHub provides commits'/pull-requests' raw patches using this URL.
      url = urlmatch[0] + '.patch'
    end

    # The cache directory seems like a good place to put patches.
    HOMEBREW_CACHE.mkpath
    patchpath = (HOMEBREW_CACHE+File.basename(url))
    curl url, '-o', patchpath

    # Store current revision
    revision = `git log -n1 --format=%H`.strip()

    ohai 'Applying patch'
    patch_args = %w[am --signoff]
    # Normally we don't want whitespace errors, but squashing them can break
    # patches so an option is provided to skip this step.
    patch_args << '--whitespace=fix' unless ARGV.include? '--ignore-whitespace'
    patch_args << patchpath

    safe_system 'git', *patch_args

    issue = arg.to_i > 0 ? arg.to_i : urlmatch[2]
    if issue
      ohai "Patch closes issue ##{issue}"
      message = `git log HEAD^.. --format=%B`

      # If this is a pull request, append a close message.
      if !message.include? 'Closes #'
        issueline = "Closes ##{issue}."
        signed = 'Signed-off-by:'
        message = message.gsub signed, issueline + "\n\n" + signed
        safe_system 'git', 'commit', '--amend', '-q', '-m', message
      end
    end

    ohai 'Patch changed:'
    safe_system 'git', 'diff', "#{revision}..", '--stat'

    if install
      `git diff #{revision}.. --name-status`.each_line do |line|
        status, filename = line.split()
        # Don't try and do anything to removed files.
        if (status == 'A' or status == 'M') and filename.include? '/Formula/'
          formula = File.basename(filename, '.rb')
          ohai "Installing #{formula}"
          # Not sure if this is the best way to install?
          safe_system 'brew', 'install', '--force', '--build-bottle', formula
        end
      end
    end
  end
end