aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/patch.rb
diff options
context:
space:
mode:
authorJack Nagel2014-03-13 19:51:23 -0500
committerJack Nagel2014-03-13 21:35:41 -0500
commitbc6e4a189491f0e3f911b879efec3e570029dd8e (patch)
tree3a37c4f0a4575d6f1986f5b182e904f59f3255ff /Library/Homebrew/patch.rb
parentf36e676bc9e93c4c10d14b3e10e9e2f72bfb25db (diff)
downloadbrew-bc6e4a189491f0e3f911b879efec3e570029dd8e.tar.bz2
New patch implementation and DSL
This commit introduces a new patch implementation that supports checksums and caching. Patches are declared in blocks: patch do url ... sha1 ... end A strip level of -p1 is assumed. It can be overridden using a symbol argument: patch :p0 do url ... sha1 ... end Patches can be declared in stable, devel, and head blocks. This form is preferred over using conditionals. stable do # ... patch do url ... sha1 ... end end Embedded (__END__) patches are declared like so: patch :DATA patch :p0, :DATA Patches can also be embedded by passing a string. This makes it possible to provide multiple embedded patches while making only some of them conditional. patch :p0, "..."
Diffstat (limited to 'Library/Homebrew/patch.rb')
-rw-r--r--Library/Homebrew/patch.rb82
1 files changed, 82 insertions, 0 deletions
diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb
new file mode 100644
index 000000000..a4616eee6
--- /dev/null
+++ b/Library/Homebrew/patch.rb
@@ -0,0 +1,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