keg_relocate: replace Perl shebangs
This commit is contained in:
parent
91ab5fe0ce
commit
ae49b06600
@ -11,9 +11,11 @@ class Keg
|
||||
# Patching patchelf using itself fails with "Text file busy" or SIGBUS.
|
||||
return if name == "patchelf"
|
||||
|
||||
old_prefix, new_prefix = relocation.replacement_pair_for(:prefix)
|
||||
|
||||
elf_files.each do |file|
|
||||
file.ensure_writable do
|
||||
change_rpath(file, relocation.old_prefix, relocation.new_prefix)
|
||||
change_rpath(file, old_prefix, new_prefix)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -19,18 +19,21 @@ class Keg
|
||||
undef relocate_dynamic_linkage
|
||||
|
||||
def relocate_dynamic_linkage(relocation)
|
||||
old_prefix, new_prefix = relocation.replacement_pair_for(:prefix)
|
||||
old_cellar, new_cellar = relocation.replacement_pair_for(:cellar)
|
||||
|
||||
mach_o_files.each do |file|
|
||||
file.ensure_writable do
|
||||
if file.dylib?
|
||||
id = dylib_id_for(file).sub(relocation.old_prefix, relocation.new_prefix)
|
||||
id = dylib_id_for(file).sub(old_prefix, new_prefix)
|
||||
change_dylib_id(id, file)
|
||||
end
|
||||
|
||||
each_install_name_for(file) do |old_name|
|
||||
if old_name.start_with? relocation.old_cellar
|
||||
new_name = old_name.sub(relocation.old_cellar, relocation.new_cellar)
|
||||
elsif old_name.start_with? relocation.old_prefix
|
||||
new_name = old_name.sub(relocation.old_prefix, relocation.new_prefix)
|
||||
if old_name.start_with? old_cellar
|
||||
new_name = old_name.sub(old_cellar, new_cellar)
|
||||
elsif old_name.start_with? old_prefix
|
||||
new_name = old_name.sub(old_prefix, new_prefix)
|
||||
end
|
||||
|
||||
change_install_name(old_name, new_name, file) if new_name
|
||||
@ -38,10 +41,10 @@ class Keg
|
||||
|
||||
if ENV["HOMEBREW_RELOCATE_RPATHS"]
|
||||
each_rpath_for(file) do |old_name|
|
||||
new_name = if old_name.start_with? relocation.old_cellar
|
||||
old_name.sub(relocation.old_cellar, relocation.new_cellar)
|
||||
elsif old_name.start_with? relocation.old_prefix
|
||||
old_name.sub(relocation.old_prefix, relocation.new_prefix)
|
||||
new_name = if old_name.start_with? old_cellar
|
||||
old_name.sub(old_cellar, new_cellar)
|
||||
elsif old_name.start_with? old_prefix
|
||||
old_name.sub(old_prefix, new_prefix)
|
||||
end
|
||||
|
||||
change_rpath(old_name, new_name, file) if new_name
|
||||
@ -172,6 +175,25 @@ class Keg
|
||||
mach_o_files
|
||||
end
|
||||
|
||||
def prepare_relocation_to_locations
|
||||
relocation = generic_prepare_relocation_to_locations
|
||||
|
||||
brewed_perl = runtime_dependencies&.any? { |dep| dep["full_name"] == "perl" && dep["declared_directly"] }
|
||||
perl_path = if brewed_perl
|
||||
"#{HOMEBREW_PREFIX}/opt/perl/bin/perl"
|
||||
else
|
||||
perl_version = if tab["built_on"].present?
|
||||
tab["built_on"]["preferred_perl"]
|
||||
else
|
||||
MacOS.preferred_perl_version
|
||||
end
|
||||
"/usr/bin/perl#{perl_version}"
|
||||
end
|
||||
relocation.add_replacement_pair(:perl, PERL_PLACEHOLDER, perl_path)
|
||||
|
||||
relocation
|
||||
end
|
||||
|
||||
def recursive_fgrep_args
|
||||
# Don't recurse into symlinks; the man page says this is the default, but
|
||||
# it's wrong. -O is a BSD-grep-only option.
|
||||
|
@ -6,12 +6,44 @@ class Keg
|
||||
CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@"
|
||||
REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@"
|
||||
LIBRARY_PLACEHOLDER = "@@HOMEBREW_LIBRARY@@"
|
||||
PERL_PLACEHOLDER = "@@HOMEBREW_PERL@@"
|
||||
|
||||
Relocation = Struct.new(:old_prefix, :old_cellar, :old_repository, :old_library,
|
||||
:new_prefix, :new_cellar, :new_repository, :new_library) do
|
||||
# Use keyword args instead of positional args for initialization.
|
||||
def initialize(**kwargs)
|
||||
super(*members.map { |k| kwargs[k] })
|
||||
class Relocation
|
||||
extend T::Sig
|
||||
|
||||
def initialize
|
||||
@replacement_map = {}
|
||||
end
|
||||
|
||||
def freeze
|
||||
@replacement_map.freeze
|
||||
super
|
||||
end
|
||||
|
||||
sig { params(key: Symbol, old_value: T.any(String, Regexp), new_value: String).void }
|
||||
def add_replacement_pair(key, old_value, new_value)
|
||||
@replacement_map[key] = [old_value, new_value]
|
||||
end
|
||||
|
||||
sig { params(key: Symbol).returns(T::Array[T.any(String, Regexp)]) }
|
||||
def replacement_pair_for(key)
|
||||
@replacement_map.fetch(key)
|
||||
end
|
||||
|
||||
sig { params(text: String).void }
|
||||
def replace_text(text)
|
||||
replacements = @replacement_map.values.to_h
|
||||
|
||||
sorted_keys = replacements.keys.sort_by do |key|
|
||||
key.is_a?(String) ? key.length : 999
|
||||
end.reverse
|
||||
|
||||
any_changed = false
|
||||
sorted_keys.each do |key|
|
||||
changed = text.gsub!(key, replacements[key])
|
||||
any_changed ||= changed
|
||||
end
|
||||
any_changed
|
||||
end
|
||||
end
|
||||
|
||||
@ -36,32 +68,42 @@ class Keg
|
||||
[]
|
||||
end
|
||||
|
||||
def prepare_relocation_to_placeholders
|
||||
relocation = Relocation.new
|
||||
relocation.add_replacement_pair(:prefix, HOMEBREW_PREFIX.to_s, PREFIX_PLACEHOLDER)
|
||||
relocation.add_replacement_pair(:cellar, HOMEBREW_CELLAR.to_s, CELLAR_PLACEHOLDER)
|
||||
# when HOMEBREW_PREFIX == HOMEBREW_REPOSITORY we should use HOMEBREW_PREFIX for all relocations to avoid
|
||||
# being unable to differentiate between them.
|
||||
if HOMEBREW_PREFIX != HOMEBREW_REPOSITORY
|
||||
relocation.add_replacement_pair(:repository, HOMEBREW_REPOSITORY.to_s, REPOSITORY_PLACEHOLDER)
|
||||
end
|
||||
relocation.add_replacement_pair(:library, HOMEBREW_LIBRARY.to_s, LIBRARY_PLACEHOLDER)
|
||||
relocation.add_replacement_pair(:perl,
|
||||
%r{\A#!(/usr/bin/perl\d\.\d+|#{HOMEBREW_PREFIX}/opt/perl/bin/perl)$}o,
|
||||
"#!#{PERL_PLACEHOLDER}")
|
||||
relocation
|
||||
end
|
||||
alias generic_prepare_relocation_to_placeholders prepare_relocation_to_placeholders
|
||||
|
||||
def replace_locations_with_placeholders
|
||||
relocation = Relocation.new(
|
||||
old_prefix: HOMEBREW_PREFIX.to_s,
|
||||
old_cellar: HOMEBREW_CELLAR.to_s,
|
||||
new_prefix: PREFIX_PLACEHOLDER,
|
||||
new_cellar: CELLAR_PLACEHOLDER,
|
||||
old_repository: HOMEBREW_REPOSITORY.to_s,
|
||||
new_repository: REPOSITORY_PLACEHOLDER,
|
||||
old_library: HOMEBREW_LIBRARY.to_s,
|
||||
new_library: LIBRARY_PLACEHOLDER,
|
||||
)
|
||||
relocation = prepare_relocation_to_placeholders.freeze
|
||||
relocate_dynamic_linkage(relocation)
|
||||
replace_text_in_files(relocation)
|
||||
end
|
||||
|
||||
def prepare_relocation_to_locations
|
||||
relocation = Relocation.new
|
||||
relocation.add_replacement_pair(:prefix, PREFIX_PLACEHOLDER, HOMEBREW_PREFIX.to_s)
|
||||
relocation.add_replacement_pair(:cellar, CELLAR_PLACEHOLDER, HOMEBREW_CELLAR.to_s)
|
||||
relocation.add_replacement_pair(:repository, REPOSITORY_PLACEHOLDER, HOMEBREW_REPOSITORY.to_s)
|
||||
relocation.add_replacement_pair(:library, LIBRARY_PLACEHOLDER, HOMEBREW_LIBRARY.to_s)
|
||||
relocation.add_replacement_pair(:perl, PERL_PLACEHOLDER, "#{HOMEBREW_PREFIX}/opt/perl/bin/perl")
|
||||
relocation
|
||||
end
|
||||
alias generic_prepare_relocation_to_locations prepare_relocation_to_locations
|
||||
|
||||
def replace_placeholders_with_locations(files, skip_linkage: false)
|
||||
relocation = Relocation.new(
|
||||
old_prefix: PREFIX_PLACEHOLDER,
|
||||
old_cellar: CELLAR_PLACEHOLDER,
|
||||
old_repository: REPOSITORY_PLACEHOLDER,
|
||||
old_library: LIBRARY_PLACEHOLDER,
|
||||
new_prefix: HOMEBREW_PREFIX.to_s,
|
||||
new_cellar: HOMEBREW_CELLAR.to_s,
|
||||
new_repository: HOMEBREW_REPOSITORY.to_s,
|
||||
new_library: HOMEBREW_LIBRARY.to_s,
|
||||
)
|
||||
relocation = prepare_relocation_to_locations.freeze
|
||||
relocate_dynamic_linkage(relocation) unless skip_linkage
|
||||
replace_text_in_files(relocation, files: files)
|
||||
end
|
||||
@ -73,16 +115,7 @@ class Keg
|
||||
files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest|
|
||||
s = first.open("rb", &:read)
|
||||
|
||||
replacements = {
|
||||
relocation.old_prefix => relocation.new_prefix,
|
||||
relocation.old_cellar => relocation.new_cellar,
|
||||
relocation.old_library => relocation.new_library,
|
||||
}.compact
|
||||
# when HOMEBREW_PREFIX == HOMEBREW_REPOSITORY we should use HOMEBREW_PREFIX for all relocations to avoid
|
||||
# being unable to differentiate between them.
|
||||
replacements[relocation.old_repository] = relocation.new_repository if HOMEBREW_PREFIX != HOMEBREW_REPOSITORY
|
||||
changed = s.gsub!(Regexp.union(replacements.keys.sort_by(&:length).reverse), replacements)
|
||||
next unless changed
|
||||
next unless relocation.replace_text(s)
|
||||
|
||||
changed_files += [first, *rest].map { |file| file.relative_path_from(path) }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user