aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/patch.rb
blob: a4616eee609c2cc049a15c17be08e8aaecb22cc4 (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
require 'resource'
require 'stringio'

class Patch
  def self.create(strip, io=nil, &block)
    case strip ||= :p1
    when :DATA, IO, StringIO
      IOPatch.new(strip, :p1)
    when String
      IOPatch.new(StringIO.new(strip), :p1)
    when Symbol
      case io
      when :DATA, IO, StringIO
        IOPatch.new(io, strip)
      when String
        IOPatch.new(StringIO.new(io), strip)
      else
        ExternalPatch.new(strip, &block)
      end
    else
      raise ArgumentError, "unexpected value #{strip.inspect} for strip"
    end
  end

  attr_reader :whence

  def external?
    whence == :resource
  end
end

class IOPatch < Patch
  attr_writer :owner
  attr_reader :strip

  def initialize(io, strip)
    @io     = io
    @strip  = strip
    @whence = :io
  end

  def apply
    @io = DATA if @io == :DATA
    data = @io.read
    data.gsub!("HOMEBREW_PREFIX", HOMEBREW_PREFIX)
    IO.popen("/usr/bin/patch -g 0 -f -#{strip}", "w") { |p| p.write(data) }
    raise ErrorDuringExecution, "Applying DATA patch failed" unless $?.success?
  ensure
    # IO and StringIO cannot be marshaled, so remove the reference
    # in case we are indirectly referenced by an exception later.
    @io = nil
  end
end

class ExternalPatch < Patch
  attr_reader :resource, :strip

  def initialize(strip, &block)
    @strip    = strip
    @resource = Resource.new(&block)
    @whence   = :resource
  end

  def url
    resource.url
  end

  def owner= owner
    resource.owner   = owner
    resource.name    = "patch-#{resource.checksum}"
    resource.version = owner.version
  end

  def apply
    dir = Pathname.pwd
    resource.unpack do
      # Assumption: the only file in the staging directory is the patch
      patchfile = Pathname.pwd.children.first
      safe_system "/usr/bin/patch", "-g", "0", "-f", "-d", dir, "-#{strip}", "-i", patchfile
    end
  end
end