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.
|
# Patching patchelf using itself fails with "Text file busy" or SIGBUS.
|
||||||
return if name == "patchelf"
|
return if name == "patchelf"
|
||||||
|
|
||||||
|
old_prefix, new_prefix = relocation.replacement_pair_for(:prefix)
|
||||||
|
|
||||||
elf_files.each do |file|
|
elf_files.each do |file|
|
||||||
file.ensure_writable do
|
file.ensure_writable do
|
||||||
change_rpath(file, relocation.old_prefix, relocation.new_prefix)
|
change_rpath(file, old_prefix, new_prefix)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -19,18 +19,21 @@ class Keg
|
|||||||
undef relocate_dynamic_linkage
|
undef relocate_dynamic_linkage
|
||||||
|
|
||||||
def relocate_dynamic_linkage(relocation)
|
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|
|
mach_o_files.each do |file|
|
||||||
file.ensure_writable do
|
file.ensure_writable do
|
||||||
if file.dylib?
|
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)
|
change_dylib_id(id, file)
|
||||||
end
|
end
|
||||||
|
|
||||||
each_install_name_for(file) do |old_name|
|
each_install_name_for(file) do |old_name|
|
||||||
if old_name.start_with? relocation.old_cellar
|
if old_name.start_with? old_cellar
|
||||||
new_name = old_name.sub(relocation.old_cellar, relocation.new_cellar)
|
new_name = old_name.sub(old_cellar, new_cellar)
|
||||||
elsif old_name.start_with? relocation.old_prefix
|
elsif old_name.start_with? old_prefix
|
||||||
new_name = old_name.sub(relocation.old_prefix, relocation.new_prefix)
|
new_name = old_name.sub(old_prefix, new_prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
change_install_name(old_name, new_name, file) if new_name
|
change_install_name(old_name, new_name, file) if new_name
|
||||||
@ -38,10 +41,10 @@ class Keg
|
|||||||
|
|
||||||
if ENV["HOMEBREW_RELOCATE_RPATHS"]
|
if ENV["HOMEBREW_RELOCATE_RPATHS"]
|
||||||
each_rpath_for(file) do |old_name|
|
each_rpath_for(file) do |old_name|
|
||||||
new_name = if old_name.start_with? relocation.old_cellar
|
new_name = if old_name.start_with? old_cellar
|
||||||
old_name.sub(relocation.old_cellar, relocation.new_cellar)
|
old_name.sub(old_cellar, new_cellar)
|
||||||
elsif old_name.start_with? relocation.old_prefix
|
elsif old_name.start_with? old_prefix
|
||||||
old_name.sub(relocation.old_prefix, relocation.new_prefix)
|
old_name.sub(old_prefix, new_prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
change_rpath(old_name, new_name, file) if new_name
|
change_rpath(old_name, new_name, file) if new_name
|
||||||
@ -172,6 +175,25 @@ class Keg
|
|||||||
mach_o_files
|
mach_o_files
|
||||||
end
|
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
|
def recursive_fgrep_args
|
||||||
# Don't recurse into symlinks; the man page says this is the default, but
|
# Don't recurse into symlinks; the man page says this is the default, but
|
||||||
# it's wrong. -O is a BSD-grep-only option.
|
# it's wrong. -O is a BSD-grep-only option.
|
||||||
|
@ -6,12 +6,44 @@ class Keg
|
|||||||
CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@"
|
CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@"
|
||||||
REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@"
|
REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@"
|
||||||
LIBRARY_PLACEHOLDER = "@@HOMEBREW_LIBRARY@@"
|
LIBRARY_PLACEHOLDER = "@@HOMEBREW_LIBRARY@@"
|
||||||
|
PERL_PLACEHOLDER = "@@HOMEBREW_PERL@@"
|
||||||
|
|
||||||
Relocation = Struct.new(:old_prefix, :old_cellar, :old_repository, :old_library,
|
class Relocation
|
||||||
:new_prefix, :new_cellar, :new_repository, :new_library) do
|
extend T::Sig
|
||||||
# Use keyword args instead of positional args for initialization.
|
|
||||||
def initialize(**kwargs)
|
def initialize
|
||||||
super(*members.map { |k| kwargs[k] })
|
@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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -36,32 +68,42 @@ class Keg
|
|||||||
[]
|
[]
|
||||||
end
|
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
|
def replace_locations_with_placeholders
|
||||||
relocation = Relocation.new(
|
relocation = prepare_relocation_to_placeholders.freeze
|
||||||
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,
|
|
||||||
)
|
|
||||||
relocate_dynamic_linkage(relocation)
|
relocate_dynamic_linkage(relocation)
|
||||||
replace_text_in_files(relocation)
|
replace_text_in_files(relocation)
|
||||||
end
|
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)
|
def replace_placeholders_with_locations(files, skip_linkage: false)
|
||||||
relocation = Relocation.new(
|
relocation = prepare_relocation_to_locations.freeze
|
||||||
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,
|
|
||||||
)
|
|
||||||
relocate_dynamic_linkage(relocation) unless skip_linkage
|
relocate_dynamic_linkage(relocation) unless skip_linkage
|
||||||
replace_text_in_files(relocation, files: files)
|
replace_text_in_files(relocation, files: files)
|
||||||
end
|
end
|
||||||
@ -73,16 +115,7 @@ class Keg
|
|||||||
files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest|
|
files.map(&path.method(:join)).group_by { |f| f.stat.ino }.each_value do |first, *rest|
|
||||||
s = first.open("rb", &:read)
|
s = first.open("rb", &:read)
|
||||||
|
|
||||||
replacements = {
|
next unless relocation.replace_text(s)
|
||||||
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
|
|
||||||
|
|
||||||
changed_files += [first, *rest].map { |file| file.relative_path_from(path) }
|
changed_files += [first, *rest].map { |file| file.relative_path_from(path) }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user