| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 19:06:31 -05:00
										 |  |  | class Keg | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  |   PREFIX_PLACEHOLDER = "@@HOMEBREW_PREFIX@@" | 
					
						
							|  |  |  |   CELLAR_PLACEHOLDER = "@@HOMEBREW_CELLAR@@" | 
					
						
							| 
									
										
										
										
											2020-12-18 12:22:15 +00:00
										 |  |  |   REPOSITORY_PLACEHOLDER = "@@HOMEBREW_REPOSITORY@@" | 
					
						
							| 
									
										
										
										
											2020-12-17 09:42:08 +00:00
										 |  |  |   LIBRARY_PLACEHOLDER = "@@HOMEBREW_LIBRARY@@" | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |   PERL_PLACEHOLDER = "@@HOMEBREW_PERL@@" | 
					
						
							| 
									
										
										
										
											2021-10-27 15:01:17 +08:00
										 |  |  |   JAVA_PLACEHOLDER = "@@HOMEBREW_JAVA@@" | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |   NULL_BYTE = "\x00" | 
					
						
							|  |  |  |   NULL_BYTE_STRING = "\\x00" | 
					
						
							| 
									
										
										
										
											2020-12-16 14:03:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |   class Relocation | 
					
						
							| 
									
										
										
										
											2024-01-18 22:18:42 +00:00
										 |  |  |     RELOCATABLE_PATH_REGEX_PREFIX = /(?:(?<=-F|-I|-L|-isystem)|(?<![a-zA-Z0-9]))/ | 
					
						
							| 
									
										
										
										
											2021-05-06 00:50:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     def initialize | 
					
						
							|  |  |  |       @replacement_map = {} | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def freeze | 
					
						
							|  |  |  |       @replacement_map.freeze | 
					
						
							|  |  |  |       super | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 10:46:23 -04:00
										 |  |  |     sig { params(key: Symbol, old_value: T.any(String, Regexp), new_value: String, path: T::Boolean).void } | 
					
						
							|  |  |  |     def add_replacement_pair(key, old_value, new_value, path: false) | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |       old_value = self.class.path_to_regex(old_value) if path | 
					
						
							| 
									
										
										
										
											2021-05-11 10:46:23 -04:00
										 |  |  |       @replacement_map[key] = [old_value, new_value] | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sig { params(key: Symbol).returns(T::Array[T.any(String, Regexp)]) } | 
					
						
							|  |  |  |     def replacement_pair_for(key) | 
					
						
							|  |  |  |       @replacement_map.fetch(key) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-28 00:43:30 +01:00
										 |  |  |     sig { params(text: String).returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |       any_changed = T.let(nil, T.nilable(String)) | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |       sorted_keys.each do |key| | 
					
						
							|  |  |  |         changed = text.gsub!(key, replacements[key]) | 
					
						
							|  |  |  |         any_changed ||= changed | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2023-07-28 00:43:30 +01:00
										 |  |  |       !any_changed.nil? | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-05-06 00:50:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |     sig { params(path: T.any(String, Regexp)).returns(Regexp) } | 
					
						
							|  |  |  |     def self.path_to_regex(path) | 
					
						
							|  |  |  |       path = case path | 
					
						
							| 
									
										
										
										
											2021-05-10 14:02:07 -04:00
										 |  |  |       when String | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |         Regexp.escape(path) | 
					
						
							| 
									
										
										
										
											2021-05-10 14:02:07 -04:00
										 |  |  |       when Regexp | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |         path.source | 
					
						
							| 
									
										
										
										
											2021-05-10 14:02:07 -04:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |       Regexp.new(RELOCATABLE_PATH_REGEX_PREFIX.source + path) | 
					
						
							| 
									
										
										
										
											2021-05-06 00:50:31 -04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  |   def fix_dynamic_linkage | 
					
						
							| 
									
										
										
										
											2015-09-11 16:32:14 +08:00
										 |  |  |     symlink_files.each do |file| | 
					
						
							|  |  |  |       link = file.readlink | 
					
						
							|  |  |  |       # Don't fix relative symlinks | 
					
						
							|  |  |  |       next unless link.absolute? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-05 09:00:11 +01:00
										 |  |  |       link_starts_cellar = link.to_s.start_with?(HOMEBREW_CELLAR.to_s) | 
					
						
							|  |  |  |       link_starts_prefix = link.to_s.start_with?(HOMEBREW_PREFIX.to_s) | 
					
						
							|  |  |  |       next if !link_starts_cellar && !link_starts_prefix | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-02 10:26:05 -07:00
										 |  |  |       new_src = link.relative_path_from(file.parent) | 
					
						
							|  |  |  |       file.unlink | 
					
						
							|  |  |  |       FileUtils.ln_s(new_src, file) | 
					
						
							| 
									
										
										
										
											2015-09-11 16:32:14 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-05-10 00:19:14 +01:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-09-23 18:13:48 +02:00
										 |  |  |   alias generic_fix_dynamic_linkage fix_dynamic_linkage | 
					
						
							| 
									
										
										
										
											2010-05-10 00:19:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  |   def relocate_dynamic_linkage(_relocation) | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  |     [] | 
					
						
							| 
									
										
										
										
											2015-09-11 18:55:46 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-10-31 01:08:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 22:18:42 +00:00
										 |  |  |   JAVA_REGEX = %r{#{HOMEBREW_PREFIX}/opt/openjdk(@\d+(\.\d+)*)?/libexec(/openjdk\.jdk/Contents/Home)?} | 
					
						
							| 
									
										
										
										
											2021-10-27 15:01:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |   def prepare_relocation_to_placeholders | 
					
						
							|  |  |  |     relocation = Relocation.new | 
					
						
							| 
									
										
										
										
											2021-05-11 10:46:23 -04:00
										 |  |  |     relocation.add_replacement_pair(:prefix, HOMEBREW_PREFIX.to_s, PREFIX_PLACEHOLDER, path: true) | 
					
						
							|  |  |  |     relocation.add_replacement_pair(:cellar, HOMEBREW_CELLAR.to_s, CELLAR_PLACEHOLDER, path: true) | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     # 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 | 
					
						
							| 
									
										
										
										
											2021-05-11 10:46:23 -04:00
										 |  |  |       relocation.add_replacement_pair(:repository, HOMEBREW_REPOSITORY.to_s, REPOSITORY_PLACEHOLDER, path: true) | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-05-11 10:46:23 -04:00
										 |  |  |     relocation.add_replacement_pair(:library, HOMEBREW_LIBRARY.to_s, LIBRARY_PLACEHOLDER, path: true) | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     relocation.add_replacement_pair(:perl, | 
					
						
							| 
									
										
										
										
											2021-05-04 15:59:53 +01:00
										 |  |  |                                     %r{\A#!(?:/usr/bin/perl\d\.\d+|#{HOMEBREW_PREFIX}/opt/perl/bin/perl)( |$)}o, | 
					
						
							|  |  |  |                                     "#!#{PERL_PLACEHOLDER}\\1") | 
					
						
							| 
									
										
										
										
											2021-10-28 17:05:17 +08:00
										 |  |  |     relocation.add_replacement_pair(:java, JAVA_REGEX, JAVA_PLACEHOLDER) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     relocation | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   alias generic_prepare_relocation_to_placeholders prepare_relocation_to_placeholders | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 12:02:12 -04:00
										 |  |  |   def replace_locations_with_placeholders | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     relocation = prepare_relocation_to_placeholders.freeze | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  |     relocate_dynamic_linkage(relocation) | 
					
						
							|  |  |  |     replace_text_in_files(relocation) | 
					
						
							| 
									
										
										
										
											2016-10-10 12:02:12 -04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |   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") | 
					
						
							| 
									
										
										
										
											2021-10-27 18:25:59 +08:00
										 |  |  |     if (openjdk = openjdk_dep_name_if_applicable) | 
					
						
							|  |  |  |       relocation.add_replacement_pair(:java, JAVA_PLACEHOLDER, "#{HOMEBREW_PREFIX}/opt/#{openjdk}/libexec") | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-10-27 15:01:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     relocation | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   alias generic_prepare_relocation_to_locations prepare_relocation_to_locations | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-25 03:41:35 -04:00
										 |  |  |   def replace_placeholders_with_locations(files, skip_linkage: false) | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |     relocation = prepare_relocation_to_locations.freeze | 
					
						
							| 
									
										
										
										
											2016-10-25 03:41:35 -04:00
										 |  |  |     relocate_dynamic_linkage(relocation) unless skip_linkage | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |     replace_text_in_files(relocation, files:) | 
					
						
							| 
									
										
										
										
											2016-10-10 12:02:12 -04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 15:01:17 +08:00
										 |  |  |   def openjdk_dep_name_if_applicable | 
					
						
							| 
									
										
										
										
											2021-10-27 18:25:59 +08:00
										 |  |  |     deps = runtime_dependencies | 
					
						
							|  |  |  |     return if deps.blank? | 
					
						
							| 
									
										
										
										
											2021-10-27 19:22:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 18:25:59 +08:00
										 |  |  |     dep_names = deps.map { |d| d["full_name"] } | 
					
						
							|  |  |  |     dep_names.find { |d| d.match? Version.formula_optionally_versioned_regex(:openjdk) } | 
					
						
							| 
									
										
										
										
											2021-10-27 15:01:17 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  |   def replace_text_in_files(relocation, files: nil) | 
					
						
							| 
									
										
										
										
											2016-10-09 19:43:55 -04:00
										 |  |  |     files ||= text_files | libtool_files | 
					
						
							| 
									
										
										
										
											2015-07-23 16:29:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |     changed_files = T.let([], Array) | 
					
						
							| 
									
										
										
										
											2024-03-03 18:55:56 -08:00
										 |  |  |     files.map { path.join(_1) }.group_by { |f| f.stat.ino }.each_value do |first, *rest| | 
					
						
							| 
									
										
										
										
											2014-03-27 14:17:13 -05:00
										 |  |  |       s = first.open("rb", &:read) | 
					
						
							| 
									
										
										
										
											2016-10-23 23:48:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 17:52:10 +01:00
										 |  |  |       next unless relocation.replace_text(s) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 12:58:38 -04:00
										 |  |  |       changed_files += [first, *rest].map { |file| file.relative_path_from(path) } | 
					
						
							| 
									
										
										
										
											2015-11-20 14:40:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-05 23:07:28 -05:00
										 |  |  |       begin | 
					
						
							| 
									
										
										
										
											2014-03-27 21:42:09 -05:00
										 |  |  |         first.atomic_write(s) | 
					
						
							| 
									
										
										
										
											2014-09-25 14:34:28 -05:00
										 |  |  |       rescue SystemCallError | 
					
						
							| 
									
										
										
										
											2014-04-05 23:07:28 -05:00
										 |  |  |         first.ensure_writable do | 
					
						
							|  |  |  |           first.open("wb") { |f| f.write(s) } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2016-09-17 15:32:44 +01:00
										 |  |  |         rest.each { |file| FileUtils.ln(first, file, force: true) } | 
					
						
							| 
									
										
										
										
											2015-11-20 14:40:28 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-10-31 01:08:57 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-10-09 19:43:55 -04:00
										 |  |  |     changed_files | 
					
						
							| 
									
										
										
										
											2013-03-11 18:56:26 +00:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 13:38:01 -08:00
										 |  |  |   def relocate_build_prefix(keg, old_prefix, new_prefix) | 
					
						
							|  |  |  |     each_unique_file_matching(old_prefix) do |file| | 
					
						
							|  |  |  |       # Skip files which are not binary, as they do not need null padding. | 
					
						
							|  |  |  |       next unless keg.binary_file?(file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Skip sharballs, which appear to break if patched. | 
					
						
							|  |  |  |       next if file.text_executable? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Split binary by null characters into array and substitute new prefix for old prefix. | 
					
						
							|  |  |  |       # Null padding is added if the new string is too short. | 
					
						
							|  |  |  |       file.ensure_writable do | 
					
						
							|  |  |  |         binary = File.binread file | 
					
						
							|  |  |  |         odebug "Replacing build prefix in: #{file}" | 
					
						
							|  |  |  |         binary_strings = binary.split(/#{NULL_BYTE}/o, -1) | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |         match_indices = binary_strings.each_index.select { |i| binary_strings.fetch(i).include?(old_prefix) } | 
					
						
							| 
									
										
										
										
											2022-03-11 13:38:01 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Only perform substitution on strings which match prefix regex. | 
					
						
							|  |  |  |         match_indices.each do |i| | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |           s = binary_strings.fetch(i) | 
					
						
							| 
									
										
										
										
											2022-03-11 13:38:01 -08:00
										 |  |  |           binary_strings[i] = s.gsub(old_prefix, new_prefix) | 
					
						
							|  |  |  |                                .ljust(s.size, NULL_BYTE) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Rejoin strings by null bytes. | 
					
						
							|  |  |  |         patched_binary = binary_strings.join(NULL_BYTE) | 
					
						
							|  |  |  |         if patched_binary.size != binary.size | 
					
						
							|  |  |  |           raise <<~EOS | 
					
						
							|  |  |  |             Patching failed!  Original and patched binary sizes do not match. | 
					
						
							|  |  |  |             Original size: #{binary.size} | 
					
						
							|  |  |  |             Patched size: #{patched_binary.size} | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         file.atomic_write patched_binary | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       codesign_patched_binary(file) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   def detect_cxx_stdlibs(_options = {}) | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  |     [] | 
					
						
							| 
									
										
										
										
											2013-10-06 01:51:31 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-02 09:04:49 -07:00
										 |  |  |   def recursive_fgrep_args | 
					
						
							|  |  |  |     # for GNU grep; overridden for BSD grep on OS X | 
					
						
							|  |  |  |     "-lr" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   alias generic_recursive_fgrep_args recursive_fgrep_args | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |   def egrep_args | 
					
						
							|  |  |  |     grep_bin = "grep" | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |     grep_args = [ | 
					
						
							|  |  |  |       "--files-with-matches", | 
					
						
							|  |  |  |       "--perl-regexp", | 
					
						
							|  |  |  |       "--binary-files=text", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |     [grep_bin, grep_args] | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   alias generic_egrep_args egrep_args | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |   def each_unique_file_matching(string) | 
					
						
							|  |  |  |     Utils.popen_read("fgrep", recursive_fgrep_args, string, to_s) do |io| | 
					
						
							|  |  |  |       hardlinks = Set.new | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |       until io.eof? | 
					
						
							|  |  |  |         file = Pathname.new(io.readline.chomp) | 
					
						
							|  |  |  |         # Don't return symbolic links. | 
					
						
							|  |  |  |         next if file.symlink? | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |         # To avoid returning hardlinks, only return files with unique inodes. | 
					
						
							|  |  |  |         # Hardlinks will have the same inode as the file they point to. | 
					
						
							|  |  |  |         yield file if hardlinks.add? file.stat.ino | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-12-17 20:46:42 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |   def binary_file?(file) | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |     grep_bin, grep_args = egrep_args | 
					
						
							| 
									
										
										
										
											2021-12-06 01:26:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-16 21:29:08 -08:00
										 |  |  |     # We need to pass NULL_BYTE_STRING, the literal string "\x00", to grep | 
					
						
							|  |  |  |     # rather than NULL_BYTE, a literal null byte, because grep will internally | 
					
						
							|  |  |  |     # convert the literal string "\x00" to a null byte. | 
					
						
							| 
									
										
										
										
											2022-03-05 19:23:50 -08:00
										 |  |  |     Utils.popen_read(grep_bin, *grep_args, NULL_BYTE_STRING, file).present? | 
					
						
							| 
									
										
										
										
											2021-12-06 01:26:02 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 19:06:31 -05:00
										 |  |  |   def lib | 
					
						
							| 
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 |  |  |     path/"lib" | 
					
						
							| 
									
										
										
										
											2014-06-26 19:06:31 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-09-04 10:49:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-03 17:30:15 +02:00
										 |  |  |   def libexec | 
					
						
							|  |  |  |     path/"libexec" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 11:56:34 -07:00
										 |  |  |   def text_files | 
					
						
							|  |  |  |     text_files = [] | 
					
						
							| 
									
										
										
										
											2021-01-07 13:49:05 -08:00
										 |  |  |     return text_files if !which("file") || !which("xargs") | 
					
						
							| 
									
										
										
										
											2016-07-29 15:53:05 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 03:11:27 +01:00
										 |  |  |     # file has known issues with reading files on other locales. Has | 
					
						
							|  |  |  |     # been fixed upstream for some time, but a sufficiently new enough | 
					
						
							|  |  |  |     # file with that fix is only available in macOS Sierra. | 
					
						
							| 
									
										
										
										
											2017-03-12 19:44:01 +00:00
										 |  |  |     # https://bugs.gw.com/view.php?id=292 | 
					
						
							| 
									
										
										
										
											2016-08-02 03:11:27 +01:00
										 |  |  |     with_custom_locale("C") do | 
					
						
							| 
									
										
										
										
											2016-10-12 11:37:34 -04:00
										 |  |  |       files = Set.new path.find.reject { |pn| | 
					
						
							| 
									
										
										
										
											2016-10-12 11:35:37 +01:00
										 |  |  |         next true if pn.symlink? | 
					
						
							|  |  |  |         next true if pn.directory? | 
					
						
							| 
									
										
										
										
											2017-05-06 15:54:56 -07:00
										 |  |  |         next false if pn.basename.to_s == "orig-prefix.txt" # for python virtualenvs | 
					
						
							| 
									
										
										
										
											2017-10-01 09:52:29 -07:00
										 |  |  |         next true if pn == self/".brew/#{name}.rb" | 
					
						
							| 
									
										
										
										
											2024-07-14 08:49:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         require "metafiles" | 
					
						
							| 
									
										
										
										
											2016-10-12 11:35:37 +01:00
										 |  |  |         next true if Metafiles::EXTENSIONS.include?(pn.extname) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 11:35:37 +01:00
										 |  |  |         if pn.text_executable? | 
					
						
							|  |  |  |           text_files << pn | 
					
						
							|  |  |  |           next true | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         false | 
					
						
							| 
									
										
										
										
											2016-10-10 21:46:19 -04:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-12-11 15:32:57 -08:00
										 |  |  |       output, _status = Open3.capture2("xargs -0 file --no-dereference --print0", | 
					
						
							| 
									
										
										
										
											2016-10-12 11:37:34 -04:00
										 |  |  |                                        stdin_data: files.to_a.join("\0")) | 
					
						
							| 
									
										
										
										
											2016-10-15 21:21:08 -07:00
										 |  |  |       # `file` output sometimes contains data from the file, which may include | 
					
						
							|  |  |  |       # invalid UTF-8 entities, so tell Ruby this is just a bytestring | 
					
						
							|  |  |  |       output.force_encoding(Encoding::ASCII_8BIT) | 
					
						
							| 
									
										
										
										
											2016-10-12 11:37:34 -04:00
										 |  |  |       output.each_line do |line| | 
					
						
							| 
									
										
										
										
											2016-10-15 21:21:08 -07:00
										 |  |  |         path, info = line.split("\0", 2) | 
					
						
							| 
									
										
										
										
											2016-10-15 23:52:55 -07:00
										 |  |  |         # `file` sometimes prints more than one line of output per file; | 
					
						
							|  |  |  |         # subsequent lines do not contain a null-byte separator, so `info` | 
					
						
							|  |  |  |         # will be `nil` for those lines | 
					
						
							|  |  |  |         next unless info | 
					
						
							| 
									
										
										
										
											2016-10-15 21:21:08 -07:00
										 |  |  |         next unless info.include?("text") | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 11:37:34 -04:00
										 |  |  |         path = Pathname.new(path) | 
					
						
							|  |  |  |         next unless files.include?(path) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 11:37:34 -04:00
										 |  |  |         text_files << path | 
					
						
							| 
									
										
										
										
											2015-07-20 12:06:13 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2013-10-31 01:08:57 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 11:56:34 -07:00
										 |  |  |     text_files | 
					
						
							| 
									
										
										
										
											2015-07-10 19:51:43 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-07-23 16:29:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def libtool_files | 
					
						
							|  |  |  |     libtool_files = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 22:06:14 +01:00
										 |  |  |     path.find do |pn| | 
					
						
							| 
									
										
										
										
											2020-12-01 17:04:59 +00:00
										 |  |  |       next if pn.symlink? || pn.directory? || Keg::LIBTOOL_EXTENSIONS.exclude?(pn.extname) | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-23 16:29:37 +08:00
										 |  |  |       libtool_files << pn | 
					
						
							| 
									
										
										
										
											2016-04-24 22:06:14 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-07-23 16:29:37 +08:00
										 |  |  |     libtool_files | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-09-11 16:32:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def symlink_files | 
					
						
							|  |  |  |     symlink_files = [] | 
					
						
							|  |  |  |     path.find do |pn| | 
					
						
							|  |  |  |       symlink_files << pn if pn.symlink? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     symlink_files | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:34:50 -04:00
										 |  |  |   def self.text_matches_in_file(file, string, ignores, linked_libraries, formula_and_runtime_deps_names) | 
					
						
							|  |  |  |     text_matches = [] | 
					
						
							| 
									
										
										
										
											2021-05-13 11:02:39 -04:00
										 |  |  |     path_regex = Relocation.path_to_regex(string) | 
					
						
							| 
									
										
										
										
											2021-05-11 09:34:50 -04:00
										 |  |  |     Utils.popen_read("strings", "-t", "x", "-", file.to_s) do |io| | 
					
						
							|  |  |  |       until io.eof? | 
					
						
							|  |  |  |         str = io.readline.chomp | 
					
						
							| 
									
										
										
										
											2023-12-27 15:29:33 -08:00
										 |  |  |         next if ignores.any? { |i| str.match?(i) } | 
					
						
							| 
									
										
										
										
											2021-05-11 09:34:50 -04:00
										 |  |  |         next unless str.match? path_regex | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         offset, match = str.split(" ", 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Some binaries contain strings with lists of files | 
					
						
							|  |  |  |         # e.g. `/usr/local/lib/foo:/usr/local/share/foo:/usr/lib/foo` | 
					
						
							|  |  |  |         # Each item in the list should be checked separately | 
					
						
							|  |  |  |         match.split(":").each do |sub_match| | 
					
						
							|  |  |  |           # Not all items in the list may be matches | 
					
						
							|  |  |  |           next unless sub_match.match? path_regex | 
					
						
							|  |  |  |           next if linked_libraries.include? sub_match # Don't bother reporting a string if it was found by otool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # Do not report matches to files that do not exist. | 
					
						
							|  |  |  |           next unless File.exist? sub_match | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # Do not report matches to build dependencies. | 
					
						
							|  |  |  |           if formula_and_runtime_deps_names.present? | 
					
						
							|  |  |  |             begin | 
					
						
							|  |  |  |               keg_name = Keg.for(Pathname.new(sub_match)).name | 
					
						
							|  |  |  |               next unless formula_and_runtime_deps_names.include? keg_name | 
					
						
							|  |  |  |             rescue NotAKegError | 
					
						
							|  |  |  |               nil | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           text_matches << [match, offset] unless text_matches.any? { |text| text.last == offset } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     text_matches | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |   def self.file_linked_libraries(_file, _string) | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  |     [] | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-05-10 00:19:14 +01:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2016-07-09 13:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/keg_relocate" |