2024-08-12 10:30:59 +01:00
|
|
|
# typed: true # rubocop:todo Sorbet/StrictSigil
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
require "resource"
|
|
|
|
require "erb"
|
2014-03-13 19:51:23 -05:00
|
|
|
|
2020-08-17 20:06:08 +02:00
|
|
|
# Helper module for creating patches.
|
2014-07-28 16:23:42 -05:00
|
|
|
module Patch
|
2014-07-29 16:06:07 -05:00
|
|
|
def self.create(strip, src, &block)
|
2014-07-10 12:38:09 -05:00
|
|
|
case strip
|
2014-07-29 16:06:06 -05:00
|
|
|
when :DATA
|
|
|
|
DATAPatch.new(:p1)
|
2014-03-13 19:51:23 -05:00
|
|
|
when String
|
2014-07-29 16:06:07 -05:00
|
|
|
StringPatch.new(:p1, strip)
|
2014-03-13 19:51:23 -05:00
|
|
|
when Symbol
|
2014-07-29 16:06:07 -05:00
|
|
|
case src
|
2014-07-29 16:06:06 -05:00
|
|
|
when :DATA
|
|
|
|
DATAPatch.new(strip)
|
2014-03-13 19:51:23 -05:00
|
|
|
when String
|
2014-07-29 16:06:07 -05:00
|
|
|
StringPatch.new(strip, src)
|
2014-03-13 19:51:23 -05:00
|
|
|
else
|
|
|
|
ExternalPatch.new(strip, &block)
|
|
|
|
end
|
2018-04-08 16:48:50 -07:00
|
|
|
when nil
|
|
|
|
raise ArgumentError, "nil value for strip"
|
2014-03-13 19:51:23 -05:00
|
|
|
else
|
2023-02-10 23:15:40 -05:00
|
|
|
raise ArgumentError, "Unexpected value #{strip.inspect} for strip"
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-17 20:06:08 +02:00
|
|
|
# An abstract class representing a patch embedded into a formula.
|
2014-07-29 16:06:07 -05:00
|
|
|
class EmbeddedPatch
|
2014-03-13 19:51:23 -05:00
|
|
|
attr_writer :owner
|
|
|
|
attr_reader :strip
|
|
|
|
|
2014-07-29 16:06:07 -05:00
|
|
|
def initialize(strip)
|
|
|
|
@strip = strip
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2014-07-28 16:23:42 -05:00
|
|
|
def external?
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2017-10-07 00:31:28 +02:00
|
|
|
def contents; end
|
2014-03-13 19:51:23 -05:00
|
|
|
|
|
|
|
def apply
|
2014-07-29 16:06:06 -05:00
|
|
|
data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX)
|
2015-08-03 13:09:07 +01:00
|
|
|
args = %W[-g 0 -f -#{strip}]
|
2018-07-16 23:17:16 +02:00
|
|
|
Utils.safe_popen_write("patch", *args) { |p| p.write(data) }
|
2014-07-29 16:06:06 -05:00
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(String) }
|
2014-03-13 19:51:24 -05:00
|
|
|
def inspect
|
2014-07-01 15:07:06 -05:00
|
|
|
"#<#{self.class.name}: #{strip.inspect}>"
|
2014-03-13 19:51:24 -05:00
|
|
|
end
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
|
|
|
|
2020-08-17 20:06:08 +02:00
|
|
|
# A patch at the `__END__` of a formula file.
|
2014-07-29 16:06:07 -05:00
|
|
|
class DATAPatch < EmbeddedPatch
|
2014-07-29 16:06:06 -05:00
|
|
|
attr_accessor :path
|
|
|
|
|
|
|
|
def initialize(strip)
|
2014-07-29 16:06:07 -05:00
|
|
|
super
|
2014-07-29 16:06:06 -05:00
|
|
|
@path = nil
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(String) }
|
2014-07-29 16:06:06 -05:00
|
|
|
def contents
|
2019-04-18 17:33:02 +09:00
|
|
|
data = +""
|
2014-07-29 16:06:06 -05:00
|
|
|
path.open("rb") do |f|
|
2017-10-07 00:31:28 +02:00
|
|
|
loop do
|
2014-07-29 16:06:06 -05:00
|
|
|
line = f.gets
|
2023-12-27 13:00:48 -08:00
|
|
|
break if line.nil? || /^__END__$/.match?(line)
|
2017-10-07 00:31:28 +02:00
|
|
|
end
|
2021-02-12 18:33:37 +05:30
|
|
|
while (line = f.gets)
|
2017-10-07 00:31:28 +02:00
|
|
|
data << line
|
|
|
|
end
|
2014-07-29 16:06:06 -05:00
|
|
|
end
|
2019-04-18 17:33:02 +09:00
|
|
|
data.freeze
|
2014-07-29 16:06:06 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-17 20:06:08 +02:00
|
|
|
# A string containing a patch.
|
2014-07-29 16:06:07 -05:00
|
|
|
class StringPatch < EmbeddedPatch
|
|
|
|
def initialize(strip, str)
|
|
|
|
super(strip)
|
|
|
|
@str = str
|
|
|
|
end
|
|
|
|
|
|
|
|
def contents
|
|
|
|
@str
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-10-23 12:37:53 +01:00
|
|
|
# A file containing a patch.
|
2014-07-28 16:23:42 -05:00
|
|
|
class ExternalPatch
|
2017-05-22 20:35:15 +01:00
|
|
|
extend Forwardable
|
|
|
|
|
2014-03-13 19:51:23 -05:00
|
|
|
attr_reader :resource, :strip
|
|
|
|
|
2017-05-22 20:35:15 +01:00
|
|
|
def_delegators :resource,
|
2020-05-12 12:37:54 +01:00
|
|
|
:url, :fetch, :patch_files, :verify_download_integrity,
|
|
|
|
:cached_download, :downloaded?, :clear_cache
|
2017-05-22 20:35:15 +01:00
|
|
|
|
2014-03-13 19:51:23 -05:00
|
|
|
def initialize(strip, &block)
|
|
|
|
@strip = strip
|
2024-07-14 11:42:22 -04:00
|
|
|
@resource = Resource::Patch.new(&block)
|
2014-07-28 16:23:42 -05:00
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(T::Boolean) }
|
2014-07-28 16:23:42 -05:00
|
|
|
def external?
|
|
|
|
true
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def owner=(owner)
|
2023-04-18 00:22:13 +01:00
|
|
|
resource.owner = owner
|
|
|
|
resource.version(resource.checksum&.hexdigest || ERB::Util.url_encode(resource.url))
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def apply
|
2020-03-08 18:33:04 +00:00
|
|
|
base_dir = Pathname.pwd
|
2014-03-13 19:51:23 -05:00
|
|
|
resource.unpack do
|
2016-01-25 08:21:57 -08:00
|
|
|
patch_dir = Pathname.pwd
|
|
|
|
if patch_files.empty?
|
|
|
|
children = patch_dir.children
|
2023-03-15 14:29:15 -07:00
|
|
|
if children.length != 1 || !children.fetch(0).file?
|
2017-10-15 02:28:32 +02:00
|
|
|
raise MissingApplyError, <<~EOS
|
2016-01-25 08:21:57 -08:00
|
|
|
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
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2023-03-15 14:29:15 -07:00
|
|
|
patch_files << children.fetch(0).basename
|
2016-01-25 08:21:57 -08:00
|
|
|
end
|
2020-03-08 18:33:04 +00:00
|
|
|
dir = base_dir
|
|
|
|
dir /= resource.directory if resource.directory.present?
|
2016-01-25 08:21:57 -08:00
|
|
|
dir.cd do
|
|
|
|
patch_files.each do |patch_file|
|
|
|
|
ohai "Applying #{patch_file}"
|
|
|
|
patch_file = patch_dir/patch_file
|
2024-10-23 12:37:53 +01:00
|
|
|
args = %W[-g 0 -f -#{strip}]
|
|
|
|
Utils.safe_popen_write("patch", *args) do |p|
|
|
|
|
File.foreach(patch_file) do |line|
|
|
|
|
data = line.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX)
|
|
|
|
p.write(data)
|
|
|
|
end
|
|
|
|
end
|
2016-01-25 08:21:57 -08:00
|
|
|
end
|
|
|
|
end
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
2020-07-26 11:53:05 +02:00
|
|
|
rescue ErrorDuringExecution => e
|
2020-07-27 11:50:40 +02:00
|
|
|
f = resource.owner.owner
|
2020-07-26 11:53:05 +02:00
|
|
|
cmd, *args = e.cmd
|
|
|
|
raise BuildError.new(f, cmd, args, ENV.to_hash)
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|
2014-03-13 19:51:24 -05:00
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(String) }
|
2014-03-13 19:51:24 -05:00
|
|
|
def inspect
|
2014-07-01 15:07:06 -05:00
|
|
|
"#<#{self.class.name}: #{strip.inspect} #{url.inspect}>"
|
2014-03-13 19:51:24 -05:00
|
|
|
end
|
2014-03-13 19:51:23 -05:00
|
|
|
end
|