resource: allow patches to be applied

This commit is contained in:
ilovezfs 2018-01-21 08:29:38 -08:00
parent 97f0ef4c49
commit 7c07ec5fc1
5 changed files with 84 additions and 5 deletions

View File

@ -119,7 +119,7 @@ class ExternalPatch
def initialize(strip, &block) def initialize(strip, &block)
@strip = strip @strip = strip
@resource = Resource::Patch.new(&block) @resource = Resource::PatchResource.new(&block)
end end
def external? def external?

View File

@ -8,13 +8,13 @@ require "version"
class Resource class Resource
include FileUtils include FileUtils
attr_reader :mirrors, :specs, :using, :source_modified_time attr_reader :mirrors, :specs, :using, :source_modified_time, :patches, :owner
attr_writer :version attr_writer :version
attr_accessor :download_strategy, :checksum attr_accessor :download_strategy, :checksum
# Formula name must be set after the DSL, as we have no access to the # Formula name must be set after the DSL, as we have no access to the
# formula name before initialization of the formula # formula name before initialization of the formula
attr_accessor :name, :owner attr_accessor :name
class Download class Download
def initialize(resource) def initialize(resource)
@ -46,9 +46,15 @@ class Resource
@specs = {} @specs = {}
@checksum = nil @checksum = nil
@using = nil @using = nil
@patches = []
instance_eval(&block) if block_given? instance_eval(&block) if block_given?
end end
def owner=(owner)
@owner = owner
patches.each { |p| p.owner = owner }
end
def downloader def downloader
download_strategy.new(download_name, Download.new(self)) download_strategy.new(download_name, Download.new(self))
end end
@ -82,9 +88,24 @@ class Resource
end end
verify_download_integrity(fetch) verify_download_integrity(fetch)
prepare_patches
unpack(target, &block) unpack(target, &block)
end end
def prepare_patches
patches.grep(DATAPatch) { |p| p.path = owner.owner.path }
patches.each do |patch|
patch.verify_download_integrity(patch.fetch) if patch.external?
end
end
def apply_patches
return if patches.empty?
ohai "Patching #{name}"
patches.each(&:apply)
end
# If a target is given, unpack there; else unpack to a temp folder. # If a target is given, unpack there; else unpack to a temp folder.
# If block is given, yield to that block with |stage|, where stage # If block is given, yield to that block with |stage|, where stage
# is a ResourceStagingContext. # is a ResourceStagingContext.
@ -93,6 +114,7 @@ class Resource
mktemp(download_name) do |staging| mktemp(download_name) do |staging|
downloader.stage downloader.stage
@source_modified_time = downloader.source_modified_time @source_modified_time = downloader.source_modified_time
apply_patches
if block_given? if block_given?
yield ResourceStageContext.new(self, staging) yield ResourceStageContext.new(self, staging)
elsif target elsif target
@ -154,6 +176,11 @@ class Resource
mirrors << val mirrors << val
end end
def patch(strip = :p1, src = nil, &block)
p = Patch.create(strip, src, &block)
patches << p
end
private private
def detect_version(val) def detect_version(val)
@ -174,7 +201,7 @@ class Resource
end end
end end
class Patch < Resource class PatchResource < Resource
attr_reader :patch_files attr_reader :patch_files
def initialize(&block) def initialize(&block)

View File

@ -48,7 +48,7 @@ describe Patch do
subject { described_class.create(:p2, nil) } subject { described_class.create(:p2, nil) }
context "empty patch" do context "empty patch" do
its(:resource) { is_expected.to be_kind_of Resource::Patch } its(:resource) { is_expected.to be_kind_of Resource::PatchResource }
its(:patch_files) { is_expected.to eq(subject.resource.patch_files) } its(:patch_files) { is_expected.to eq(subject.resource.patch_files) }
its(:patch_files) { is_expected.to eq([]) } its(:patch_files) { is_expected.to eq([]) }
end end

View File

@ -30,6 +30,17 @@ describe "patching" do
end end
end end
matcher :have_its_resource_patched do
match do |formula|
formula.brew do
formula.resources.first.stage Pathname.pwd/"resource_dir"
s = File.read("resource_dir/libexec/NOOP")
expect(s).not_to include("NOOP"), "libexec/NOOP was not patched as expected"
expect(s).to include("ABCD"), "libexec/NOOP was not patched as expected"
end
end
end
matcher :be_sequentially_patched do matcher :be_sequentially_patched do
match do |formula| match do |formula|
formula.brew do formula.brew do
@ -73,6 +84,22 @@ describe "patching" do
).to be_patched ).to be_patched
end end
specify "single_patch_dsl_for_resource" do
expect(
formula do
resource "some_resource" do
url TESTBALL_URL
sha256 TESTBALL_SHA256
patch do
url PATCH_URL_A
sha256 PATCH_A_SHA256
end
end
end,
).to have_its_resource_patched
end
specify "single_patch_dsl_with_apply" do specify "single_patch_dsl_with_apply" do
expect( expect(
formula do formula do

View File

@ -119,6 +119,31 @@ describe Resource do
end end
end end
describe "#owner" do
it "sets the owner" do
owner = Object.new
subject.owner = owner
expect(subject.owner).to eq(owner)
end
it "sets its owner to be the patches' owner" do
subject.patch(:p1) { url "file:///my.patch" }
owner = Object.new
subject.owner = owner
subject.patches.each do |p|
expect(p.resource.owner).to eq(owner)
end
end
end
describe "#patch" do
it "adds a patch" do
subject.patch(:p1, :DATA)
expect(subject.patches.count).to eq(1)
expect(subject.patches.first.strip).to eq(:p1)
end
end
specify "#verify_download_integrity_missing" do specify "#verify_download_integrity_missing" do
fn = Pathname.new("test") fn = Pathname.new("test")