From cc3d041c263ef88d2d301d06eb17031cfabfc971 Mon Sep 17 00:00:00 2001 From: ilovezfs Date: Mon, 25 Jan 2016 08:21:57 -0800 Subject: [PATCH] DSL method "apply" to specify patch files The "apply" DSL method can be called from patch-do blocks to specify the paths within an archive of the desired patch files, which will be applied in the order in which they were supplied to the "apply" calls. If "apply" isn't used, raise an error whenever the extracted directory doesn't contain exactly one file. The "apply" method can be called zero or more times within a patch-do block with the following syntaxes supported: apply "single_apply" apply "multiple_apply_1", "multiple_apply_2" apply [array_of_apply] If apply must be used, a single call using the second syntax above is usually best practice. Each apply leaf should be the relative path to a specific patch file in the extracted directory. For example, if extracting this-v123-patches.tar.gz gives you this-123 this-123/.DS_Store this-123/LICENSE.txt this-123/patches this-123/patches/A.diff this-123/patches/B.diff this-123/patches/C.diff this-123/README.txt and you want to apply only B.diff and C.diff, then you need to use "patches/B.diff" and "patches/C.diff" for the lowest-level apply leaves. The code was provided by Xu Cheng. Any mistakes are mine. --- Library/Homebrew/exceptions.rb | 3 + Library/Homebrew/patch.rb | 28 +++- Library/Homebrew/resource.rb | 15 +++ Library/Homebrew/test/lib/config.rb | 3 + Library/Homebrew/test/patches/noop-c.diff | 9 ++ .../test/tarballs/testball-0.1-patches.tgz | Bin 0 -> 368 bytes Library/Homebrew/test/test_patch.rb | 25 ++++ Library/Homebrew/test/test_patching.rb | 124 +++++++++++++++++- 8 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 Library/Homebrew/test/patches/noop-c.diff create mode 100644 Library/Homebrew/test/tarballs/testball-0.1-patches.tgz diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 6f2fb849c1..36fd927dbc 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -441,6 +441,9 @@ class DuplicateResourceError < ArgumentError end end +# raised when a single patch file is not found and apply hasn't been specified +class MissingApplyError < RuntimeError ; end + class BottleVersionMismatchError < RuntimeError def initialize(bottle_file, bottle_version, formula, formula_version) super <<-EOS.undent diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 3c5bd42eaa..ebfb8e347b 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -112,7 +112,7 @@ class ExternalPatch def initialize(strip, &block) @strip = strip - @resource = Resource.new("patch", &block) + @resource = Resource::Patch.new(&block) end def external? @@ -127,9 +127,25 @@ class ExternalPatch def apply dir = Pathname.pwd resource.unpack do - # Assumption: the only file in the staging directory is the patch - patchfile = Pathname.pwd.children.first - dir.cd { safe_system "/usr/bin/patch", "-g", "0", "-f", "-#{strip}", "-i", patchfile } + patch_dir = Pathname.pwd + if patch_files.empty? + children = patch_dir.children + if (children.count == 1 && children.first.file?) + patch_files << children.first.basename + else + raise MissingApplyError, <<-EOS.undent + There should be exactly one patch file in the staging directory unless + the "apply" method was used one or more times in the patch-do block. + EOS + end + end + dir.cd do + patch_files.each do |patch_file| + ohai "Applying #{patch_file}" + patch_file = patch_dir/patch_file + safe_system "/usr/bin/patch", "-g", "0", "-f", "-#{strip}", "-i", patch_file + end + end end end @@ -141,6 +157,10 @@ class ExternalPatch resource.fetch end + def patch_files + resource.patch_files + end + def verify_download_integrity(fn) resource.verify_download_integrity(fn) end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index bc5d62aeec..a15788fb3f 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -165,4 +165,19 @@ class Resource super(target/name) end end + + class Patch < Resource + attr_reader :patch_files + + def initialize(&block) + @patch_files = [] + super "patch", &block + end + + def apply(*paths) + paths.flatten! + @patch_files.concat(paths) + @patch_files.uniq! + end + end end diff --git a/Library/Homebrew/test/lib/config.rb b/Library/Homebrew/test/lib/config.rb index 3f72a57642..39c4ae27f1 100644 --- a/Library/Homebrew/test/lib/config.rb +++ b/Library/Homebrew/test/lib/config.rb @@ -21,3 +21,6 @@ HOMEBREW_LOGS = HOMEBREW_PREFIX.parent+"logs" TESTBALL_SHA1 = "be478fd8a80fe7f29196d6400326ac91dad68c37" TESTBALL_SHA256 = "91e3f7930c98d7ccfb288e115ed52d06b0e5bc16fec7dce8bdda86530027067b" +TESTBALL_PATCHES_SHA256 = "799c2d551ac5c3a5759bea7796631a7906a6a24435b52261a317133a0bfb34d9" +PATCH_A_SHA256 = "83404f4936d3257e65f176c4ffb5a5b8d6edd644a21c8d8dcc73e22a6d28fcfa" +PATCH_B_SHA256 = "57958271bb802a59452d0816e0670d16c8b70bdf6530bcf6f78726489ad89b90" diff --git a/Library/Homebrew/test/patches/noop-c.diff b/Library/Homebrew/test/patches/noop-c.diff new file mode 100644 index 0000000000..6d0de5b7ba --- /dev/null +++ b/Library/Homebrew/test/patches/noop-c.diff @@ -0,0 +1,9 @@ +diff --git a/libexec/NOOP b/libexec/NOOP +index e08d8f4..3ebfb9d 100755 +--- a/libexec/NOOP ++++ b/libexec/NOOP +@@ -1,2 +1,2 @@ + #!/bin/bash +-echo ABCD +\ No newline at end of file ++echo 1234 diff --git a/Library/Homebrew/test/tarballs/testball-0.1-patches.tgz b/Library/Homebrew/test/tarballs/testball-0.1-patches.tgz new file mode 100644 index 0000000000000000000000000000000000000000..4b43f535e86d9160d5a765d3cf8547122644d890 GIT binary patch literal 368 zcmV-$0gwJ4iwFSWMW$8&1MSvNPlGTR2JoHv6tD4!1xgFd8~!+ z&ojYTj|)k>%eKQ9+dAHHU3dE&X-bS=gygoHGr@7Qc-DM z=e9JYYBHs!s-VKojpKI1uC8xxcMco+xt@w%{