| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | require "keg" | 
					
						
							|  |  |  | require "language/python" | 
					
						
							|  |  |  | require "formula" | 
					
						
							| 
									
										
										
										
											2020-05-19 22:22:31 +09:00
										 |  |  | require "formulary" | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | require "version" | 
					
						
							| 
									
										
										
										
											2016-07-29 20:31:32 -06:00
										 |  |  | require "development_tools" | 
					
						
							| 
									
										
										
										
											2016-08-10 23:19:09 -07:00
										 |  |  | require "utils/shell" | 
					
						
							| 
									
										
										
										
											2025-08-20 19:20:19 +01:00
										 |  |  | require "utils/output" | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | require "system_config" | 
					
						
							|  |  |  | require "cask/caskroom" | 
					
						
							|  |  |  | require "cask/quarantine" | 
					
						
							| 
									
										
										
										
											2024-01-26 17:33:55 -08:00
										 |  |  | require "system_command" | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2020-08-14 04:33:33 +02:00
										 |  |  |   # Module containing diagnostic checks. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |   module Diagnostic | 
					
						
							| 
									
										
										
										
											2025-08-20 19:20:19 +01:00
										 |  |  |     extend Utils::Output::Mixin | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |     sig { | 
					
						
							|  |  |  |       params(formulae: T::Array[Formula], hide: T::Array[String], _block: T.nilable( | 
					
						
							|  |  |  |         T.proc.params(formula_name: String, missing_dependencies: T::Array[Formula]).void, | 
					
						
							|  |  |  |       )).returns(T::Hash[String, T::Array[String]]) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     def self.missing_deps(formulae, hide = [], &_block) | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       missing = {} | 
					
						
							| 
									
										
										
										
											2023-03-08 00:29:47 +00:00
										 |  |  |       formulae.each do |f| | 
					
						
							| 
									
										
										
										
											2025-02-25 19:10:25 +08:00
										 |  |  |         missing_dependencies = f.missing_dependencies(hide: hide) | 
					
						
							| 
									
										
										
										
											2018-03-25 12:43:24 +01:00
										 |  |  |         next if missing_dependencies.empty? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 12:43:24 +01:00
										 |  |  |         yield f.full_name, missing_dependencies if block_given? | 
					
						
							|  |  |  |         missing[f.full_name] = missing_dependencies | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |       missing | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |     sig { params(type: Symbol, fatal: T::Boolean).void } | 
					
						
							| 
									
										
										
										
											2020-09-11 12:05:22 +01:00
										 |  |  |     def self.checks(type, fatal: true) | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       @checks ||= T.let(Checks.new, T.nilable(Checks)) | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |       failed = T.let(false, T::Boolean) | 
					
						
							| 
									
										
										
										
											2020-09-11 12:05:22 +01:00
										 |  |  |       @checks.public_send(type).each do |check| | 
					
						
							|  |  |  |         out = @checks.public_send(check) | 
					
						
							|  |  |  |         next if out.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if fatal | 
					
						
							|  |  |  |           failed ||= true | 
					
						
							|  |  |  |           ofail out | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           opoo out | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       exit 1 if failed && fatal | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 04:33:33 +02:00
										 |  |  |     # Diagnostic checks. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |     class Checks | 
					
						
							| 
									
										
										
										
											2024-01-26 17:33:55 -08:00
										 |  |  |       include SystemCommand::Mixin | 
					
						
							| 
									
										
										
										
											2025-08-23 20:52:26 +08:00
										 |  |  |       include Utils::Output::Mixin | 
					
						
							| 
									
										
										
										
											2024-01-26 17:33:55 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(verbose: T::Boolean).void } | 
					
						
							| 
									
										
										
										
											2020-08-19 17:12:32 +01:00
										 |  |  |       def initialize(verbose: true) | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |         @verbose = T.let(verbose, T::Boolean) | 
					
						
							|  |  |  |         @found = T.let([], T::Array[String]) | 
					
						
							|  |  |  |         @seen_prefix_bin = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         @seen_prefix_sbin = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         @user_path_1_done = T.let(false, T::Boolean) | 
					
						
							|  |  |  |         @non_core_taps = T.let([], T.nilable(T::Array[Tap])) | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:19:56 -05:00
										 |  |  |       ############# @!group HELPERS | 
					
						
							| 
									
										
										
										
											2018-10-18 21:42:43 -04:00
										 |  |  |       # Finds files in `HOMEBREW_PREFIX` *and* /usr/local. | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |       # Specify paths relative to a prefix, e.g. "include/foo.h". | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       # Sets @found for your convenience. | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(relative_paths: T.any(String, T::Array[String])).void } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def find_relative_paths(*relative_paths) | 
					
						
							| 
									
										
										
										
											2018-09-02 20:14:54 +01:00
										 |  |  |         @found = [HOMEBREW_PREFIX, "/usr/local"].uniq.reduce([]) do |found, prefix| | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           found + relative_paths.map { |f| File.join(prefix, f) }.select { |f| File.exist? f } | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-16 22:20:37 -08:00
										 |  |  |       sig { params(list: T::Array[T.any(Formula, Pathname, String)], string: String).returns(String) } | 
					
						
							| 
									
										
										
										
											2016-09-21 14:36:11 +02:00
										 |  |  |       def inject_file_list(list, string) | 
					
						
							| 
									
										
										
										
											2019-04-20 14:07:29 +09:00
										 |  |  |         list.reduce(string.dup) { |acc, elem| acc << "  #{elem}\n" } | 
					
						
							|  |  |  |             .freeze | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(path: String).returns(String) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def user_tilde(path) | 
					
						
							| 
									
										
										
										
											2025-08-19 16:29:06 +08:00
										 |  |  |         home = Dir.home | 
					
						
							|  |  |  |         if path == home | 
					
						
							|  |  |  |           "~" | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           path.gsub(%r{^#{home}/}, "~/") | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def none_string | 
					
						
							|  |  |  |         "<NONE>" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 17:29:44 +01:00
										 |  |  |       sig { params(args: T.anything).void } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def add_info(*args) | 
					
						
							|  |  |  |         ohai(*args) if @verbose | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-11-05 15:19:56 -05:00
										 |  |  |       ############# @!endgroup END HELPERS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2019-01-21 19:23:31 +00:00
										 |  |  |       def fatal_preinstall_checks | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |         %w[
 | 
					
						
							|  |  |  |           check_access_directories | 
					
						
							|  |  |  |         ].freeze | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2019-01-21 19:23:31 +00:00
										 |  |  |       def fatal_build_from_source_checks | 
					
						
							| 
									
										
										
										
											2016-07-04 18:35:03 +01:00
										 |  |  |         %w[
 | 
					
						
							|  |  |  |           check_for_installed_developer_tools | 
					
						
							| 
									
										
										
										
											2016-11-05 10:38:39 -04:00
										 |  |  |         ].freeze | 
					
						
							| 
									
										
										
										
											2016-07-04 18:35:03 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2020-09-11 12:05:22 +01:00
										 |  |  |       def fatal_setup_build_environment_checks | 
					
						
							|  |  |  |         [].freeze | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2019-01-21 19:23:31 +00:00
										 |  |  |       def supported_configuration_checks | 
					
						
							|  |  |  |         [].freeze | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2019-01-21 19:23:31 +00:00
										 |  |  |       def build_from_source_checks | 
					
						
							|  |  |  |         [].freeze | 
					
						
							| 
									
										
										
										
											2016-11-05 10:38:39 -04:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-11-05 10:39:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2016-11-05 10:39:00 -04:00
										 |  |  |       def build_error_checks | 
					
						
							| 
									
										
										
										
											2019-01-21 19:23:31 +00:00
										 |  |  |         supported_configuration_checks + build_from_source_checks | 
					
						
							| 
									
										
										
										
											2016-09-07 09:11:06 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |       sig { params(tier: T.any(Integer, String, Symbol)).returns(T.nilable(String)) } | 
					
						
							|  |  |  |       def support_tier_message(tier:) | 
					
						
							|  |  |  |         return if tier.to_s == "1" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 15:27:26 +01:00
										 |  |  |         tier_title, tier_slug, tier_issues = if tier.to_s == "unsupported" | 
					
						
							|  |  |  |           ["Unsupported", "unsupported", "Do not report any"] | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2025-06-27 15:27:26 +01:00
										 |  |  |           ["Tier #{tier}", "tier-#{tier.to_s.downcase}", "You can report Tier #{tier} unrelated"] | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-01 15:46:57 -08:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |           This is a #{tier_title} configuration: | 
					
						
							|  |  |  |             #{Formatter.url("https://docs.brew.sh/Support-Tiers##{tier_slug}")} | 
					
						
							| 
									
										
										
										
											2025-06-27 15:27:26 +01:00
										 |  |  |           #{Formatter.bold("#{tier_issues} issues to Homebrew/* repositories!")} | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |           Read the above document instead before opening any issues or PRs. | 
					
						
							| 
									
										
										
										
											2019-01-01 15:46:57 -08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 19:06:40 -07:00
										 |  |  |       sig { params(repository_path: GitRepository, desired_origin: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |       def examine_git_origin(repository_path, desired_origin) | 
					
						
							| 
									
										
										
										
											2024-06-10 09:31:53 +01:00
										 |  |  |         return if !Utils::Git.available? || !repository_path.git_repository? | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 16:46:13 -07:00
										 |  |  |         current_origin = repository_path.origin_url | 
					
						
							| 
									
										
										
										
											2019-12-19 00:05:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |         if current_origin.nil? | 
					
						
							|  |  |  |           <<~EOS | 
					
						
							|  |  |  |             Missing #{desired_origin} git origin remote. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Without a correctly configured origin, Homebrew won't update | 
					
						
							|  |  |  |             properly. You can solve this by adding the remote: | 
					
						
							| 
									
										
										
										
											2020-01-09 14:14:44 +00:00
										 |  |  |               git -C "#{repository_path}" remote add origin #{Formatter.url(desired_origin)} | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2019-12-19 00:05:20 +09:00
										 |  |  |         elsif !current_origin.match?(%r{#{desired_origin}(\.git|/)?$}i) | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |           <<~EOS | 
					
						
							|  |  |  |             Suspicious #{desired_origin} git origin remote found. | 
					
						
							|  |  |  |             The current git origin is: | 
					
						
							|  |  |  |               #{current_origin} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             With a non-standard origin, Homebrew won't update properly. | 
					
						
							|  |  |  |             You can solve this by setting the origin remote: | 
					
						
							| 
									
										
										
										
											2020-01-09 14:14:44 +00:00
										 |  |  |               git -C "#{repository_path}" remote set-url origin #{Formatter.url(desired_origin)} | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(tap: Tap).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  |       def broken_tap(tap) | 
					
						
							|  |  |  |         return unless Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2021-05-12 16:07:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 19:06:40 -07:00
										 |  |  |         repo = GitRepository.new(HOMEBREW_REPOSITORY) | 
					
						
							| 
									
										
										
										
											2024-06-10 09:31:53 +01:00
										 |  |  |         return unless repo.git_repository? | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 00:08:33 +08:00
										 |  |  |         message = <<~EOS | 
					
						
							|  |  |  |           #{tap.full_name} was not tapped properly! Run: | 
					
						
							|  |  |  |             rm -rf "#{tap.path}" | 
					
						
							|  |  |  |             brew tap #{tap.name} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return message if tap.remote.blank? | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         tap_head = tap.git_head | 
					
						
							| 
									
										
										
										
											2021-06-02 00:08:33 +08:00
										 |  |  |         return message if tap_head.blank? | 
					
						
							| 
									
										
										
										
											2023-04-15 19:06:40 -07:00
										 |  |  |         return if tap_head != repo.head_ref | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 00:08:33 +08:00
										 |  |  |         message | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-07-04 18:35:03 +01:00
										 |  |  |       def check_for_installed_developer_tools | 
					
						
							|  |  |  |         return if DevelopmentTools.installed? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-07-04 18:35:03 +01:00
										 |  |  |           No developer tools installed. | 
					
						
							| 
									
										
										
										
											2016-07-16 21:03:12 +01:00
										 |  |  |           #{DevelopmentTools.installation_instructions} | 
					
						
							| 
									
										
										
										
											2016-07-04 18:35:03 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(dir: String, pattern: String, allow_list: T::Array[String], message: String).returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |       def __check_stray_files(dir, pattern, allow_list, message) | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         return unless File.directory?(dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         files = Dir.chdir(dir) do | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |           (Dir.glob(pattern) - Dir.glob(allow_list)) | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |             .select { |f| File.file?(f) && !File.symlink?(f) } | 
					
						
							| 
									
										
										
										
											2025-01-19 12:36:37 +08:00
										 |  |  |             .map do |f| | 
					
						
							| 
									
										
										
										
											2025-01-19 23:06:46 +08:00
										 |  |  |               f.sub!(%r{/.*}, "/*") unless @verbose | 
					
						
							| 
									
										
										
										
											2025-01-19 12:36:37 +08:00
										 |  |  |               File.join(dir, f) | 
					
						
							|  |  |  |             end | 
					
						
							| 
									
										
										
										
											2025-01-19 23:06:46 +08:00
										 |  |  |             .sort.uniq | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         return if files.empty? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-19 23:06:46 +08:00
										 |  |  |         inject_file_list(files, message) | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_stray_dylibs | 
					
						
							|  |  |  |         # Dylibs which are generally OK should be added to this list, | 
					
						
							|  |  |  |         # with a short description of the software they come with. | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         allow_list = [ | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libfuse.2.dylib", # MacFuse | 
					
						
							| 
									
										
										
										
											2025-03-30 21:40:11 +08:00
										 |  |  |           "libfuse3.*.dylib", # MacFuse | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libfuse_ino64.2.dylib", # MacFuse | 
					
						
							|  |  |  |           "libmacfuse_i32.2.dylib", # OSXFuse MacFuse compatibility layer | 
					
						
							|  |  |  |           "libmacfuse_i64.2.dylib", # OSXFuse MacFuse compatibility layer | 
					
						
							|  |  |  |           "libosxfuse_i32.2.dylib", # OSXFuse | 
					
						
							|  |  |  |           "libosxfuse_i64.2.dylib", # OSXFuse | 
					
						
							| 
									
										
										
										
											2016-02-20 19:24:30 +00:00
										 |  |  |           "libosxfuse.2.dylib", # OSXFuse | 
					
						
							| 
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 |  |  |           "libTrAPI.dylib", # TrAPI/Endpoint Security VPN | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libntfs-3g.*.dylib", # NTFS-3G | 
					
						
							|  |  |  |           "libntfs.*.dylib", # NTFS-3G | 
					
						
							|  |  |  |           "libublio.*.dylib", # NTFS-3G | 
					
						
							|  |  |  |           "libUFSDNTFS.dylib", # Paragon NTFS | 
					
						
							|  |  |  |           "libUFSDExtFS.dylib", # Paragon ExtFS | 
					
						
							| 
									
										
										
										
											2016-11-04 14:35:54 +00:00
										 |  |  |           "libecomlodr.dylib", # Symantec Endpoint Protection | 
					
						
							| 
									
										
										
										
											2017-06-22 16:00:54 +08:00
										 |  |  |           "libsymsea*.dylib", # Symantec Endpoint Protection | 
					
						
							| 
									
										
										
										
											2016-11-04 12:18:23 -04:00
										 |  |  |           "sentinel.dylib", # SentinelOne | 
					
						
							| 
									
										
										
										
											2017-11-28 17:34:16 -05:00
										 |  |  |           "sentinel-*.dylib", # SentinelOne | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         __check_stray_files "/usr/local/lib", "*.dylib", allow_list, <<~EOS | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unbrewed dylibs were found in /usr/local/lib. | 
					
						
							|  |  |  |           If you didn't put them there on purpose they could cause problems when | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           building Homebrew formulae and may need to be deleted. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unexpected dylibs: | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_stray_static_libs | 
					
						
							|  |  |  |         # Static libs which are generally OK should be added to this list, | 
					
						
							|  |  |  |         # with a short description of the software they come with. | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         allow_list = [ | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libntfs-3g.a", # NTFS-3G | 
					
						
							|  |  |  |           "libntfs.a", # NTFS-3G | 
					
						
							|  |  |  |           "libublio.a", # NTFS-3G | 
					
						
							| 
									
										
										
										
											2016-11-04 14:35:54 +00:00
										 |  |  |           "libappfirewall.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "libautoblock.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "libautosetup.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "libconnectionsclient.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "liblocationawareness.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "libpersonalfirewall.a", # Symantec Endpoint Protection | 
					
						
							|  |  |  |           "libtrustedcomponents.a", # Symantec Endpoint Protection | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         __check_stray_files "/usr/local/lib", "*.a", allow_list, <<~EOS | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unbrewed static libraries were found in /usr/local/lib. | 
					
						
							|  |  |  |           If you didn't put them there on purpose they could cause problems when | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           building Homebrew formulae and may need to be deleted. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unexpected static libraries: | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_stray_pcs | 
					
						
							|  |  |  |         # Package-config files which are generally OK should be added to this list, | 
					
						
							|  |  |  |         # with a short description of the software they come with. | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         allow_list = [ | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "fuse.pc", # OSXFuse/MacFuse | 
					
						
							| 
									
										
										
										
											2025-03-30 21:40:11 +08:00
										 |  |  |           "fuse3.pc", # OSXFuse/MacFuse | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "macfuse.pc", # OSXFuse MacFuse compatibility layer | 
					
						
							|  |  |  |           "osxfuse.pc", # OSXFuse | 
					
						
							|  |  |  |           "libntfs-3g.pc", # NTFS-3G | 
					
						
							|  |  |  |           "libublio.pc", # NTFS-3G | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         __check_stray_files "/usr/local/lib/pkgconfig", "*.pc", allow_list, <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Unbrewed '.pc' files were found in /usr/local/lib/pkgconfig. | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           If you didn't put them there on purpose they could cause problems when | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           building Homebrew formulae and may need to be deleted. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Unexpected '.pc' files: | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_stray_las | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         allow_list = [ | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libfuse.la", # MacFuse | 
					
						
							|  |  |  |           "libfuse_ino64.la", # MacFuse | 
					
						
							|  |  |  |           "libosxfuse_i32.la", # OSXFuse | 
					
						
							|  |  |  |           "libosxfuse_i64.la", # OSXFuse | 
					
						
							| 
									
										
										
										
											2016-02-20 19:24:30 +00:00
										 |  |  |           "libosxfuse.la", # OSXFuse | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "libntfs-3g.la", # NTFS-3G | 
					
						
							|  |  |  |           "libntfs.la", # NTFS-3G | 
					
						
							|  |  |  |           "libublio.la", # NTFS-3G | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         __check_stray_files "/usr/local/lib", "*.la", allow_list, <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Unbrewed '.la' files were found in /usr/local/lib. | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           If you didn't put them there on purpose they could cause problems when | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           building Homebrew formulae and may need to be deleted. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Unexpected '.la' files: | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_stray_headers | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         allow_list = [ | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "fuse.h", # MacFuse | 
					
						
							|  |  |  |           "fuse/**/*.h", # MacFuse | 
					
						
							| 
									
										
										
										
											2025-03-30 21:40:11 +08:00
										 |  |  |           "fuse3/**/*.h", # MacFuse | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           "macfuse/**/*.h", # OSXFuse MacFuse compatibility layer | 
					
						
							|  |  |  |           "osxfuse/**/*.h", # OSXFuse | 
					
						
							|  |  |  |           "ntfs/**/*.h", # NTFS-3G | 
					
						
							|  |  |  |           "ntfs-3g/**/*.h", # NTFS-3G | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 19:12:12 +01:00
										 |  |  |         __check_stray_files "/usr/local/include", "**/*.h", allow_list, <<~EOS | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unbrewed header files were found in /usr/local/include. | 
					
						
							|  |  |  |           If you didn't put them there on purpose they could cause problems when | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           building Homebrew formulae and may need to be deleted. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Unexpected header files: | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_broken_symlinks | 
					
						
							|  |  |  |         broken_symlinks = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-05 13:46:24 -07:00
										 |  |  |         Keg.must_exist_subdirectories.each do |d| | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           next unless d.directory? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           d.find do |path| | 
					
						
							| 
									
										
										
										
											2019-02-19 13:11:32 +00:00
										 |  |  |             broken_symlinks << path if path.symlink? && !path.resolved_path_exists? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         return if broken_symlinks.empty? | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         inject_file_list broken_symlinks, <<~EOS | 
					
						
							| 
									
										
										
										
											2019-01-02 13:21:34 +00:00
										 |  |  |           Broken symlinks were found. Remove them with `brew cleanup`: | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-09-09 13:08:02 +01:00
										 |  |  |       def check_tmpdir_sticky_bit | 
					
						
							|  |  |  |         world_writable = HOMEBREW_TEMP.stat.mode & 0777 == 0777
 | 
					
						
							|  |  |  |         return if !world_writable || HOMEBREW_TEMP.sticky? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-09-09 13:08:02 +01:00
										 |  |  |           #{HOMEBREW_TEMP} is world-writable but does not have the sticky bit set. | 
					
						
							| 
									
										
										
										
											2021-01-24 21:25:12 -05:00
										 |  |  |           To set it, run the following command: | 
					
						
							|  |  |  |             sudo chmod +t #{HOMEBREW_TEMP} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |       def check_exist_directories | 
					
						
							| 
									
										
										
										
											2024-03-27 06:26:32 +00:00
										 |  |  |         return if HOMEBREW_PREFIX.writable? | 
					
						
							| 
									
										
										
										
											2020-12-07 14:32:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-05 13:46:24 -07:00
										 |  |  |         not_exist_dirs = Keg.must_exist_directories.reject(&:exist?) | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |         return if not_exist_dirs.empty? | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |           The following directories do not exist: | 
					
						
							|  |  |  |           #{not_exist_dirs.join("\n")} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           You should create these directories and change their ownership to your user. | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |             sudo mkdir -p #{not_exist_dirs.join(" ")} | 
					
						
							| 
									
										
										
										
											2023-09-29 12:32:22 +01:00
										 |  |  |             sudo chown -R #{current_user} #{not_exist_dirs.join(" ")} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |       def check_access_directories | 
					
						
							|  |  |  |         not_writable_dirs = | 
					
						
							| 
									
										
										
										
											2024-10-05 13:46:24 -07:00
										 |  |  |           Keg.must_be_writable_directories.select(&:exist?) | 
					
						
							|  |  |  |              .reject(&:writable?) | 
					
						
							| 
									
										
										
										
											2016-09-09 08:06:37 +01:00
										 |  |  |         return if not_writable_dirs.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |           The following directories are not writable by your user: | 
					
						
							| 
									
										
										
										
											2016-09-09 08:06:37 +01:00
										 |  |  |           #{not_writable_dirs.join("\n")} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:38:43 +01:00
										 |  |  |           You should change the ownership of these directories to your user. | 
					
						
							| 
									
										
										
										
											2023-09-29 12:32:22 +01:00
										 |  |  |             sudo chown -R #{current_user} #{not_writable_dirs.join(" ")} | 
					
						
							| 
									
										
										
										
											2019-03-22 22:45:41 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |           And make sure that your user has write permission. | 
					
						
							|  |  |  |             chmod u+w #{not_writable_dirs.join(" ")} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-12-13 00:19:46 +00:00
										 |  |  |       def check_multiple_cellars | 
					
						
							|  |  |  |         return if HOMEBREW_PREFIX.to_s == HOMEBREW_REPOSITORY.to_s | 
					
						
							|  |  |  |         return unless (HOMEBREW_REPOSITORY/"Cellar").exist? | 
					
						
							|  |  |  |         return unless (HOMEBREW_PREFIX/"Cellar").exist? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-12-13 00:19:46 +00:00
										 |  |  |           You have multiple Cellars. | 
					
						
							|  |  |  |           You should delete #{HOMEBREW_REPOSITORY}/Cellar: | 
					
						
							|  |  |  |             rm -rf #{HOMEBREW_REPOSITORY}/Cellar | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_user_path_1 | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |         @seen_prefix_bin = false | 
					
						
							|  |  |  |         @seen_prefix_sbin = false | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         message = "" | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 17:41:58 +00:00
										 |  |  |         paths.each do |p| | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           case p | 
					
						
							|  |  |  |           when "/usr/bin" | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |             unless @seen_prefix_bin | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |               # only show the doctor message if there are any conflicts | 
					
						
							|  |  |  |               # rationale: a default install should not trigger any brew doctor messages | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |               conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"] | 
					
						
							|  |  |  |                           .map { |fn| File.basename fn } | 
					
						
							|  |  |  |                           .select { |bn| File.exist? "/usr/bin/#{bn}" } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |               unless conflicts.empty? | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |                 message = inject_file_list conflicts, <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |                   /usr/bin occurs before #{HOMEBREW_PREFIX}/bin in your PATH. | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |                   This means that system-provided programs will be used instead of those | 
					
						
							| 
									
										
										
										
											2020-07-14 18:48:47 +08:00
										 |  |  |                   provided by Homebrew. Consider setting your PATH so that | 
					
						
							|  |  |  |                   #{HOMEBREW_PREFIX}/bin occurs before /usr/bin. Here is a one-liner: | 
					
						
							| 
									
										
										
										
											2017-04-22 16:28:07 +01:00
										 |  |  |                     #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")} | 
					
						
							| 
									
										
										
										
											2020-07-14 18:48:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                   The following tools exist at both paths: | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |                 EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |               end | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           when "#{HOMEBREW_PREFIX}/bin" | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |             @seen_prefix_bin = true | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           when "#{HOMEBREW_PREFIX}/sbin" | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |             @seen_prefix_sbin = true | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-10 10:01:38 +08:00
										 |  |  |         @user_path_1_done = true | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         message unless message.empty? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_user_path_2 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |         check_user_path_1 unless @user_path_1_done | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |         return if @seen_prefix_bin | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Homebrew's "bin" was not found in your PATH. | 
					
						
							|  |  |  |           Consider setting your PATH for example like so: | 
					
						
							| 
									
										
										
										
											2017-04-22 16:28:07 +01:00
										 |  |  |             #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_user_path_3 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |         check_user_path_1 unless @user_path_1_done | 
					
						
							| 
									
										
										
										
											2017-10-07 00:31:28 +02:00
										 |  |  |         return if @seen_prefix_sbin | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         # Don't complain about sbin not being in the path if it doesn't exist | 
					
						
							| 
									
										
										
										
											2017-06-01 16:06:51 +02:00
										 |  |  |         sbin = HOMEBREW_PREFIX/"sbin" | 
					
						
							| 
									
										
										
										
											2019-10-09 19:33:11 +01:00
										 |  |  |         return unless sbin.directory? | 
					
						
							|  |  |  |         return if sbin.children.empty? | 
					
						
							|  |  |  |         return if sbin.children.one? && sbin.children.first.basename.to_s == ".keepme" | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Homebrew's "sbin" was not found in your PATH but you have installed | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           formulae that put executables in #{HOMEBREW_PREFIX}/sbin. | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Consider setting your PATH for example like so: | 
					
						
							| 
									
										
										
										
											2017-04-22 16:28:07 +01:00
										 |  |  |             #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/sbin")} | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_symlinked_cellar | 
					
						
							|  |  |  |         return unless HOMEBREW_CELLAR.exist? | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         return unless HOMEBREW_CELLAR.symlink? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           Symlinked Cellars can cause problems. | 
					
						
							|  |  |  |           Your Homebrew Cellar is a symlink: #{HOMEBREW_CELLAR} | 
					
						
							|  |  |  |                           which resolves to: #{HOMEBREW_CELLAR.realpath} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           The recommended Homebrew installations are either: | 
					
						
							| 
									
										
										
										
											2025-08-02 23:27:59 -04:00
										 |  |  |           (A) Have Cellar be a real directory inside of your `$HOMEBREW_PREFIX` | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           (B) Symlink "bin/brew" into your prefix, but don't symlink "Cellar". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Older installations of Homebrew may have created a symlinked Cellar, but this can | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |           cause problems when two formulae install to locations that are mapped on top of each | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           other during the linking step. | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-06-13 02:57:35 +02:00
										 |  |  |       def check_git_version | 
					
						
							| 
									
										
										
										
											2022-05-30 04:37:09 +01:00
										 |  |  |         minimum_version = ENV.fetch("HOMEBREW_MINIMUM_GIT_VERSION") | 
					
						
							| 
									
										
										
										
											2020-08-23 06:32:26 +02:00
										 |  |  |         return unless Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2023-07-06 16:47:09 +01:00
										 |  |  |         return if Version.new(Utils::Git.version) >= Version.new(minimum_version) | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         git = Formula["git"] | 
					
						
							|  |  |  |         git_upgrade_cmd = git.any_version_installed? ? "upgrade" : "install" | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2020-08-23 06:32:26 +02:00
										 |  |  |           An outdated version (#{Utils::Git.version}) of Git was detected in your PATH. | 
					
						
							| 
									
										
										
										
											2018-09-06 12:38:20 +01:00
										 |  |  |           Git #{minimum_version} or newer is required for Homebrew. | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Please upgrade: | 
					
						
							|  |  |  |             brew #{git_upgrade_cmd} git | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_git | 
					
						
							| 
									
										
										
										
											2020-08-23 06:32:26 +02:00
										 |  |  |         return if Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2016-06-13 02:57:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-06-13 02:57:35 +02:00
										 |  |  |           Git could not be found in your PATH. | 
					
						
							| 
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 |  |  |           Homebrew uses Git for several internal functions and some formulae use Git | 
					
						
							| 
									
										
										
										
											2016-06-13 02:57:35 +02:00
										 |  |  |           checkouts instead of stable tarballs. You may want to install Git: | 
					
						
							|  |  |  |             brew install git | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_git_newline_settings | 
					
						
							| 
									
										
										
										
											2020-08-23 06:32:26 +02:00
										 |  |  |         return unless Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-26 13:35:36 -05:00
										 |  |  |         autocrlf = HOMEBREW_REPOSITORY.cd { `git config --get core.autocrlf`.chomp } | 
					
						
							| 
									
										
										
										
											2023-04-18 15:06:50 -07:00
										 |  |  |         return if autocrlf != "true" | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           Suspicious Git newline settings found. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           The detected Git newline settings will cause checkout problems: | 
					
						
							|  |  |  |             core.autocrlf = #{autocrlf} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           If you are not routinely dealing with Windows-based projects, | 
					
						
							|  |  |  |           consider removing these by running: | 
					
						
							|  |  |  |             git config --global core.autocrlf input | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2017-03-26 20:28:11 +01:00
										 |  |  |       def check_brew_git_origin | 
					
						
							| 
									
										
										
										
											2023-04-15 19:06:40 -07:00
										 |  |  |         repo = GitRepository.new(HOMEBREW_REPOSITORY) | 
					
						
							| 
									
										
										
										
											2021-05-12 16:07:47 +01:00
										 |  |  |         examine_git_origin(repo, Homebrew::EnvConfig.brew_git_remote) | 
					
						
							| 
									
										
										
										
											2017-03-26 20:28:11 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  |       def check_coretap_integrity | 
					
						
							| 
									
										
										
										
											2024-02-20 21:10:15 +01:00
										 |  |  |         core_tap = CoreTap.instance | 
					
						
							|  |  |  |         unless core_tap.installed? | 
					
						
							| 
									
										
										
										
											2023-02-24 13:25:18 +00:00
										 |  |  |           return unless EnvConfig.no_install_from_api? | 
					
						
							| 
									
										
										
										
											2022-08-26 12:38:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 21:10:15 +01:00
										 |  |  |           core_tap.ensure_installed! | 
					
						
							| 
									
										
										
										
											2022-08-26 12:38:03 +00:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-10-27 01:41:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-10 09:31:53 +01:00
										 |  |  |         broken_tap(core_tap) || examine_git_origin(core_tap.git_repository, Homebrew::EnvConfig.core_git_remote) | 
					
						
							| 
									
										
										
										
											2019-02-18 13:09:58 +11:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-03-26 20:28:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2021-06-01 00:41:44 +08:00
										 |  |  |       def check_casktap_integrity | 
					
						
							| 
									
										
										
										
											2024-02-20 21:10:15 +01:00
										 |  |  |         core_cask_tap = CoreCaskTap.instance | 
					
						
							|  |  |  |         return unless core_cask_tap.installed? | 
					
						
							| 
									
										
										
										
											2020-01-09 14:14:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-03 15:44:38 -07:00
										 |  |  |         broken_tap(core_cask_tap) || examine_git_origin(core_cask_tap.git_repository, T.must(core_cask_tap.remote)) | 
					
						
							| 
									
										
										
										
											2019-01-24 22:51:33 -08:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-09-27 16:32:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-26 13:20:22 +11:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							|  |  |  |       def check_tap_git_branch | 
					
						
							| 
									
										
										
										
											2018-02-12 16:38:10 +00:00
										 |  |  |         return if ENV["CI"] | 
					
						
							| 
									
										
										
										
											2020-11-26 13:20:22 +11:00
										 |  |  |         return unless Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2017-09-27 16:32:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 20:58:34 -08:00
										 |  |  |         commands = Tap.installed.filter_map do |tap| | 
					
						
							| 
									
										
										
										
											2024-06-10 09:31:53 +01:00
										 |  |  |           next if tap.git_repository.default_origin_branch? | 
					
						
							| 
									
										
										
										
											2019-01-24 22:51:33 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-10 09:31:53 +01:00
										 |  |  |           "git -C $(brew --repo #{tap.name}) checkout #{tap.git_repository.origin_branch_name}" | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2017-09-27 16:32:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-26 13:20:22 +11:00
										 |  |  |         return if commands.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           Some taps are not on the default git origin branch and may not receive | 
					
						
							|  |  |  |           updates. If this is a surprise to you, check out the default branch with: | 
					
						
							|  |  |  |             #{commands.join("\n  ")} | 
					
						
							| 
									
										
										
										
											2017-09-27 16:32:13 -04:00
										 |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2019-02-16 20:07:10 +00:00
										 |  |  |       def check_deprecated_official_taps | 
					
						
							|  |  |  |         tapped_deprecated_taps = | 
					
						
							| 
									
										
										
										
											2024-09-24 10:15:34 +01:00
										 |  |  |           Tap.select(&:official?).map(&:repository) & DEPRECATED_OFFICIAL_TAPS | 
					
						
							| 
									
										
										
										
											2025-03-18 17:38:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # TODO: remove this once it's no longer in the default GitHub Actions image | 
					
						
							|  |  |  |         tapped_deprecated_taps -= ["bundle"] if GitHub::Actions.env_set? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-16 20:07:10 +00:00
										 |  |  |         return if tapped_deprecated_taps.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           You have the following deprecated, official taps tapped: | 
					
						
							| 
									
										
										
										
											2019-02-21 00:06:57 +09:00
										 |  |  |             Homebrew/homebrew-#{tapped_deprecated_taps.join("\n  Homebrew/homebrew-")} | 
					
						
							| 
									
										
										
										
											2019-02-16 20:07:10 +00:00
										 |  |  |           Untap them with `brew untap`. | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { params(formula: Formula).returns(T::Boolean) } | 
					
						
							| 
									
										
										
										
											2025-07-14 14:48:08 +01:00
										 |  |  |       def __check_linked_brew!(formula) | 
					
						
							| 
									
										
										
										
											2023-03-10 23:46:07 +00:00
										 |  |  |         formula.installed_prefixes.each do |prefix| | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           prefix.find do |src| | 
					
						
							|  |  |  |             next if src == prefix | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |             dst = HOMEBREW_PREFIX + src.relative_path_from(prefix) | 
					
						
							|  |  |  |             return true if dst.symlink? && src == dst.resolved_path | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         false | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_other_frameworks | 
					
						
							|  |  |  |         # Other frameworks that are known to cause problems when present | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         frameworks_to_check = %w[
 | 
					
						
							|  |  |  |           expat.framework | 
					
						
							|  |  |  |           libexpat.framework | 
					
						
							|  |  |  |           libcurl.framework | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2016-09-17 15:17:27 +01:00
										 |  |  |         frameworks_found = frameworks_to_check | 
					
						
							|  |  |  |                            .map { |framework| "/Library/Frameworks/#{framework}" } | 
					
						
							|  |  |  |                            .select { |framework| File.exist? framework } | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         return if frameworks_found.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         inject_file_list frameworks_found, <<~EOS | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |           Some frameworks can be picked up by CMake's build system and will likely | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           cause the build to fail. To compile CMake, you may wish to move these | 
					
						
							|  |  |  |           out of the way: | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_tmpdir | 
					
						
							| 
									
										
										
										
											2022-05-30 04:37:09 +01:00
										 |  |  |         tmpdir = ENV.fetch("TMPDIR", nil) | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         return if tmpdir.nil? || File.directory?(tmpdir) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           TMPDIR #{tmpdir.inspect} doesn't exist. | 
					
						
							|  |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_missing_deps | 
					
						
							|  |  |  |         return unless HOMEBREW_CELLAR.exist? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         missing = Set.new | 
					
						
							|  |  |  |         Homebrew::Diagnostic.missing_deps(Formula.installed).each_value do |deps| | 
					
						
							|  |  |  |           missing.merge(deps) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         return if missing.empty? | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2018-02-07 09:50:01 +01:00
										 |  |  |           Some installed formulae are missing dependencies. | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           You should `brew install` the missing dependencies: | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |             brew install #{missing.sort_by(&:full_name) * " "} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |           Run `brew missing` for more details. | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-04-01 13:43:15 +01:00
										 |  |  |       def check_deprecated_disabled | 
					
						
							|  |  |  |         return unless HOMEBREW_CELLAR.exist? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         deprecated_or_disabled = Formula.installed.select(&:deprecated?) | 
					
						
							|  |  |  |         deprecated_or_disabled += Formula.installed.select(&:disabled?) | 
					
						
							|  |  |  |         return if deprecated_or_disabled.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           Some installed formulae are deprecated or disabled. | 
					
						
							|  |  |  |           You should find replacements for the following formulae: | 
					
						
							|  |  |  |             #{deprecated_or_disabled.sort_by(&:full_name).uniq * "\n  "} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-12-04 00:30:49 -05:00
										 |  |  |       def check_cask_deprecated_disabled | 
					
						
							|  |  |  |         deprecated_or_disabled = Cask::Caskroom.casks.select(&:deprecated?) | 
					
						
							|  |  |  |         deprecated_or_disabled += Cask::Caskroom.casks.select(&:disabled?) | 
					
						
							|  |  |  |         return if deprecated_or_disabled.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           Some installed casks are deprecated or disabled. | 
					
						
							|  |  |  |           You should find replacements for the following casks: | 
					
						
							|  |  |  |             #{deprecated_or_disabled.sort_by(&:token).uniq * "\n  "} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_git_status | 
					
						
							| 
									
										
										
										
											2020-08-23 06:32:26 +02:00
										 |  |  |         return unless Utils::Git.available? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 17:24:20 -08:00
										 |  |  |         message = T.let(nil, T.nilable(String)) | 
					
						
							| 
									
										
										
										
											2020-03-11 17:25:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 16:26:58 +09:00
										 |  |  |         repos = { | 
					
						
							| 
									
										
										
										
											2020-03-11 17:25:07 +00:00
										 |  |  |           "Homebrew/brew"          => HOMEBREW_REPOSITORY, | 
					
						
							|  |  |  |           "Homebrew/homebrew-core" => CoreTap.instance.path, | 
					
						
							| 
									
										
										
										
											2021-05-24 23:30:46 +09:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-21 12:39:07 +01:00
										 |  |  |         OFFICIAL_CASK_TAPS.each do |tap| | 
					
						
							| 
									
										
										
										
											2021-05-27 21:43:08 +09:00
										 |  |  |           cask_tap = Tap.fetch "homebrew", tap | 
					
						
							| 
									
										
										
										
											2021-05-30 16:26:58 +09:00
										 |  |  |           repos[cask_tap.full_name] = cask_tap.path if cask_tap.installed? | 
					
						
							| 
									
										
										
										
											2021-05-24 23:30:46 +09:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 16:26:58 +09:00
										 |  |  |         repos.each do |name, path| | 
					
						
							| 
									
										
										
										
											2021-10-27 01:41:57 -04:00
										 |  |  |           next unless path.exist? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 17:25:07 +00:00
										 |  |  |           status = path.cd do | 
					
						
							|  |  |  |             `git status --untracked-files=all --porcelain 2>/dev/null` | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |           next if status.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           message ||= "" | 
					
						
							|  |  |  |           message += "\n" unless message.empty? | 
					
						
							|  |  |  |           message += <<~EOS | 
					
						
							|  |  |  |             You have uncommitted modifications to #{name}. | 
					
						
							|  |  |  |             If this is a surprise to you, then you should stash these modifications. | 
					
						
							|  |  |  |             Stashing returns Homebrew to a pristine state but can be undone | 
					
						
							|  |  |  |             should you later need to do so for some reason. | 
					
						
							| 
									
										
										
										
											2025-08-22 19:39:31 -07:00
										 |  |  |               git -C "#{path}" stash -u && git -C "#{path}" clean -d -f | 
					
						
							| 
									
										
										
										
											2020-03-11 17:25:07 +00:00
										 |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2019-10-18 09:22:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |           modified = status.split("\n") | 
					
						
							| 
									
										
										
										
											2019-10-11 11:47:33 -04:00
										 |  |  |           message += inject_file_list modified, <<~EOS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 17:25:07 +00:00
										 |  |  |             Uncommitted files: | 
					
						
							| 
									
										
										
										
											2019-10-11 11:47:33 -04:00
										 |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         message | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_non_prefixed_coreutils | 
					
						
							| 
									
										
										
										
											2016-01-27 00:54:46 +01:00
										 |  |  |         coreutils = Formula["coreutils"] | 
					
						
							|  |  |  |         return unless coreutils.any_version_installed? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gnubin = %W[#{coreutils.opt_libexec}/gnubin #{coreutils.libexec}/gnubin] | 
					
						
							| 
									
										
										
										
											2024-01-18 14:11:43 +00:00
										 |  |  |         return unless paths.intersect?(gnubin) | 
					
						
							| 
									
										
										
										
											2016-01-27 00:54:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2020-07-29 17:31:11 -04:00
										 |  |  |           Putting non-prefixed coreutils in your path can cause GMP builds to fail. | 
					
						
							| 
									
										
										
										
											2016-01-27 00:54:46 +01:00
										 |  |  |         EOS | 
					
						
							| 
									
										
										
										
											2016-04-25 17:58:50 +01:00
										 |  |  |       rescue FormulaUnavailableError | 
					
						
							| 
									
										
										
										
											2018-03-06 09:36:49 +00:00
										 |  |  |         nil | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_pydistutils_cfg_in_home | 
					
						
							| 
									
										
										
										
											2022-05-30 04:48:54 +01:00
										 |  |  |         return unless File.exist? "#{Dir.home}/.pydistutils.cfg" | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           A '.pydistutils.cfg' file was found in $HOME, which may cause Python | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           builds to fail. See: | 
					
						
							| 
									
										
										
										
											2016-09-17 03:21:51 +02:00
										 |  |  |             #{Formatter.url("https://bugs.python.org/issue6138")} | 
					
						
							|  |  |  |             #{Formatter.url("https://bugs.python.org/issue4655")} | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2019-04-02 14:38:59 +01:00
										 |  |  |       def check_for_unreadable_installed_formula | 
					
						
							|  |  |  |         formula_unavailable_exceptions = [] | 
					
						
							|  |  |  |         Formula.racks.each do |rack| | 
					
						
							| 
									
										
										
										
											2019-10-13 10:03:26 +01:00
										 |  |  |           Formulary.from_rack(rack) | 
					
						
							|  |  |  |         rescue FormulaUnreadableError, FormulaClassUnavailableError, | 
					
						
							|  |  |  |                TapFormulaUnreadableError, TapFormulaClassUnavailableError => e | 
					
						
							|  |  |  |           formula_unavailable_exceptions << e | 
					
						
							| 
									
										
										
										
											2024-02-16 21:27:02 +01:00
										 |  |  |         rescue FormulaUnavailableError, TapFormulaAmbiguityError | 
					
						
							| 
									
										
										
										
											2019-10-13 10:03:26 +01:00
										 |  |  |           nil | 
					
						
							| 
									
										
										
										
											2019-04-02 14:38:59 +01:00
										 |  |  |         end | 
					
						
							|  |  |  |         return if formula_unavailable_exceptions.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           Some installed formulae are not readable: | 
					
						
							|  |  |  |             #{formula_unavailable_exceptions.join("\n\n  ")} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_unlinked_but_not_keg_only | 
					
						
							|  |  |  |         unlinked = Formula.racks.reject do |rack| | 
					
						
							| 
									
										
										
										
											2025-02-28 09:59:32 +00:00
										 |  |  |           next true if (HOMEBREW_LINKED_KEGS/rack.basename).directory? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           begin | 
					
						
							|  |  |  |             Formulary.from_rack(rack).keg_only? | 
					
						
							|  |  |  |           rescue FormulaUnavailableError, TapFormulaAmbiguityError | 
					
						
							|  |  |  |             false | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           end | 
					
						
							|  |  |  |         end.map(&:basename) | 
					
						
							|  |  |  |         return if unlinked.empty? | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |         inject_file_list unlinked, <<~EOS | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |           You have unlinked kegs in your Cellar. | 
					
						
							| 
									
										
										
										
											2021-01-26 15:21:24 -05:00
										 |  |  |           Leaving kegs unlinked can lead to build-trouble and cause formulae that depend on | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |           those kegs to fail to run properly once built. Run `brew link` on these: | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def check_for_external_cmd_name_conflict | 
					
						
							| 
									
										
										
										
											2024-08-10 17:38:27 -07:00
										 |  |  |         cmds = Commands.tap_cmd_directories.flat_map { |p| Dir["#{p}/brew-*"] }.uniq | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         cmds = cmds.select { |cmd| File.file?(cmd) && File.executable?(cmd) } | 
					
						
							|  |  |  |         cmd_map = {} | 
					
						
							|  |  |  |         cmds.each do |cmd| | 
					
						
							|  |  |  |           cmd_name = File.basename(cmd, ".rb") | 
					
						
							|  |  |  |           cmd_map[cmd_name] ||= [] | 
					
						
							|  |  |  |           cmd_map[cmd_name] << cmd | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         cmd_map.reject! { |_cmd_name, cmd_paths| cmd_paths.size == 1 } | 
					
						
							|  |  |  |         return if cmd_map.empty? | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-30 04:37:09 +01:00
										 |  |  |         if ENV["CI"].present? && cmd_map.keys.length == 1 && | 
					
						
							| 
									
										
										
										
											2017-06-17 14:01:42 +01:00
										 |  |  |            cmd_map.keys.first == "brew-test-bot" | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  |         message = "You have external commands with conflicting names.\n" | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |         cmd_map.each do |cmd_name, cmd_paths| | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |           message += inject_file_list cmd_paths, <<~EOS | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |             Found command `#{cmd_name}` in the following places: | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-04-06 05:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         message | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |       def check_for_tap_ruby_files_locations | 
					
						
							|  |  |  |         bad_tap_files = {} | 
					
						
							| 
									
										
										
										
											2024-03-06 20:58:34 -08:00
										 |  |  |         Tap.installed.each do |tap| | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |           unused_formula_dirs = tap.potential_formula_dirs - [tap.formula_dir] | 
					
						
							|  |  |  |           unused_formula_dirs.each do |dir| | 
					
						
							|  |  |  |             next unless dir.exist? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |             dir.children.each do |path| | 
					
						
							| 
									
										
										
										
											2023-04-18 15:06:50 -07:00
										 |  |  |               next if path.extname != ".rb" | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |               bad_tap_files[tap] ||= [] | 
					
						
							|  |  |  |               bad_tap_files[tap] << path | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         return if bad_tap_files.empty? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |         bad_tap_files.keys.map do |tap| | 
					
						
							| 
									
										
										
										
											2017-10-15 02:28:32 +02:00
										 |  |  |           <<~EOS | 
					
						
							| 
									
										
										
										
											2019-04-08 12:47:15 -04:00
										 |  |  |             Found Ruby file outside #{tap} tap formula directory. | 
					
						
							| 
									
										
										
										
											2016-12-13 01:53:05 +00:00
										 |  |  |             (#{tap.formula_dir}): | 
					
						
							|  |  |  |               #{bad_tap_files[tap].join("\n  ")} | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         end.join("\n") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2019-01-01 18:11:59 -08:00
										 |  |  |       def check_homebrew_prefix | 
					
						
							| 
									
										
										
										
											2019-01-21 12:37:42 +00:00
										 |  |  |         return if Homebrew.default_prefix? | 
					
						
							| 
									
										
										
										
											2019-01-01 18:11:59 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           Your Homebrew's prefix is not #{Homebrew::DEFAULT_PREFIX}. | 
					
						
							| 
									
										
										
										
											2022-10-06 10:01:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  |           Most of Homebrew's bottles (binary packages) can only be used with the default prefix. | 
					
						
							| 
									
										
										
										
											2022-10-06 10:01:02 +01:00
										 |  |  |           Consider uninstalling Homebrew and reinstalling into the default prefix. | 
					
						
							| 
									
										
										
										
											2025-03-31 09:53:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |           #{support_tier_message(tier: 3)} | 
					
						
							| 
									
										
										
										
											2019-01-01 18:11:59 -08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-05-17 17:23:23 +09:00
										 |  |  |       def check_deleted_formula | 
					
						
							| 
									
										
										
										
											2021-10-27 01:41:57 -04:00
										 |  |  |         kegs = Keg.all | 
					
						
							| 
									
										
										
										
											2021-06-15 22:07:36 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         deleted_formulae = kegs.filter_map do |keg| | 
					
						
							| 
									
										
										
										
											2024-04-28 03:23:21 +02:00
										 |  |  |           tap = keg.tab.tap | 
					
						
							| 
									
										
										
										
											2024-03-12 10:41:06 -04:00
										 |  |  |           tap_keg_name = tap ? "#{tap}/#{keg.name}" : keg.name | 
					
						
							| 
									
										
										
										
											2024-02-16 21:27:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |           loadable = [ | 
					
						
							|  |  |  |             Formulary::FromAPILoader, | 
					
						
							| 
									
										
										
										
											2024-03-11 19:43:22 -04:00
										 |  |  |             Formulary::FromTapLoader, | 
					
						
							| 
									
										
										
										
											2024-02-16 21:27:02 +01:00
										 |  |  |             Formulary::FromNameLoader, | 
					
						
							|  |  |  |           ].any? do |loader_class| | 
					
						
							|  |  |  |             loader = begin | 
					
						
							| 
									
										
										
										
											2024-03-12 10:41:06 -04:00
										 |  |  |               loader_class.try_new(tap_keg_name, warn: false) | 
					
						
							| 
									
										
										
										
											2024-02-16 21:27:02 +01:00
										 |  |  |             rescue TapFormulaAmbiguityError => e | 
					
						
							|  |  |  |               e.loaders.first | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 19:43:22 -04:00
										 |  |  |             loader.instance_of?(Formulary::FromTapLoader) ? loader.path.exist? : loader.present? | 
					
						
							| 
									
										
										
										
											2024-02-08 21:13:49 +01:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2021-10-27 01:41:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-16 21:27:02 +01:00
										 |  |  |           keg.name unless loadable | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |         end.uniq | 
					
						
							| 
									
										
										
										
											2021-06-15 22:07:36 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 17:23:23 +09:00
										 |  |  |         return if deleted_formulae.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 11:29:33 +01:00
										 |  |  |         <<~EOS | 
					
						
							| 
									
										
										
										
											2020-11-04 10:19:52 +00:00
										 |  |  |           Some installed kegs have no formulae! | 
					
						
							| 
									
										
										
										
											2022-05-02 21:14:34 +02:00
										 |  |  |           This means they were either deleted or installed manually. | 
					
						
							| 
									
										
										
										
											2020-05-17 17:23:23 +09:00
										 |  |  |           You should find replacements for the following formulae: | 
					
						
							| 
									
										
										
										
											2020-05-18 20:41:55 +09:00
										 |  |  |             #{deleted_formulae.join("\n  ")} | 
					
						
							| 
									
										
										
										
											2020-05-17 17:23:23 +09:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-04-30 15:03:51 +01:00
										 |  |  |       def check_for_unnecessary_core_tap | 
					
						
							| 
									
										
										
										
											2023-04-30 19:06:07 +01:00
										 |  |  |         return if Homebrew::EnvConfig.developer? | 
					
						
							|  |  |  |         return if Homebrew::EnvConfig.no_install_from_api? | 
					
						
							| 
									
										
										
										
											2024-07-14 11:50:57 -04:00
										 |  |  |         return if Homebrew::EnvConfig.devcmdrun? | 
					
						
							| 
									
										
										
										
											2023-04-30 15:03:51 +01:00
										 |  |  |         return unless CoreTap.instance.installed? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           You have an unnecessary local Core tap! | 
					
						
							|  |  |  |           This can cause problems installing up-to-date formulae. | 
					
						
							|  |  |  |           Please remove it by running: | 
					
						
							|  |  |  |            brew untap #{CoreTap.instance.name} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2023-04-30 15:03:51 +01:00
										 |  |  |       def check_for_unnecessary_cask_tap | 
					
						
							| 
									
										
										
										
											2023-04-30 19:06:07 +01:00
										 |  |  |         return if Homebrew::EnvConfig.developer? | 
					
						
							|  |  |  |         return if Homebrew::EnvConfig.no_install_from_api? | 
					
						
							| 
									
										
										
										
											2024-07-14 11:50:57 -04:00
										 |  |  |         return if Homebrew::EnvConfig.devcmdrun? | 
					
						
							| 
									
										
										
										
											2023-04-30 19:09:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 19:28:39 +01:00
										 |  |  |         cask_tap = CoreCaskTap.instance | 
					
						
							| 
									
										
										
										
											2023-04-30 19:06:07 +01:00
										 |  |  |         return unless cask_tap.installed? | 
					
						
							| 
									
										
										
										
											2023-04-30 15:03:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           You have an unnecessary local Cask tap. | 
					
						
							|  |  |  |           This can cause problems installing up-to-date casks. | 
					
						
							|  |  |  |           Please remove it by running: | 
					
						
							|  |  |  |             brew untap #{cask_tap.name} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2025-06-21 17:41:24 +00:00
										 |  |  |       def check_deprecated_cask_taps | 
					
						
							|  |  |  |         tapped_caskroom_taps = ::Tap.select { |t| t.user == "caskroom" || t.name == "phinze/cask" } | 
					
						
							|  |  |  |                                     .map(&:name) | 
					
						
							|  |  |  |         return if tapped_caskroom_taps.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           You have the following deprecated Cask taps installed: | 
					
						
							|  |  |  |             #{tapped_caskroom_taps.join("\n  ")} | 
					
						
							|  |  |  |           Please remove them with: | 
					
						
							|  |  |  |             brew untap #{tapped_caskroom_taps.join(" ")} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_software_versions | 
					
						
							|  |  |  |         add_info "Homebrew Version", HOMEBREW_VERSION | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nil | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_install_location | 
					
						
							|  |  |  |         locations = Dir.glob(HOMEBREW_CELLAR.join("brew-cask", "*")).reverse | 
					
						
							|  |  |  |         return if locations.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         locations.map do |l| | 
					
						
							|  |  |  |           "Legacy install at #{l}. Run `brew uninstall --force brew-cask`." | 
					
						
							|  |  |  |         end.join "\n" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_staging_location | 
					
						
							| 
									
										
										
										
											2020-07-11 11:26:11 -04:00
										 |  |  |         # Skip this check when running CI since the staging path is not writable for security reasons | 
					
						
							| 
									
										
										
										
											2024-05-09 13:19:14 +01:00
										 |  |  |         return if GitHub::Actions.env_set? | 
					
						
							| 
									
										
										
										
											2020-07-11 11:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |         path = Cask::Caskroom.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         add_info "Homebrew Cask Staging Location", user_tilde(path.to_s) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-07 13:49:05 -08:00
										 |  |  |         return if !path.exist? || path.writable? | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         <<~EOS | 
					
						
							|  |  |  |           The staging path #{user_tilde(path.to_s)} is not writable by the current user. | 
					
						
							| 
									
										
										
										
											2021-01-24 21:25:12 -05:00
										 |  |  |           To fix, run: | 
					
						
							| 
									
										
										
										
											2023-09-29 12:32:22 +01:00
										 |  |  |             sudo chown -R #{current_user} #{user_tilde(path.to_s)} | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_taps | 
					
						
							|  |  |  |         error_tap_paths = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-20 20:13:03 +01:00
										 |  |  |         taps = (Tap.to_a + [CoreCaskTap.instance]).uniq | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 10:23:39 +01:00
										 |  |  |         taps_info = taps.filter_map do |tap| | 
					
						
							| 
									
										
										
										
											2024-02-20 17:59:32 +01:00
										 |  |  |           cask_count = begin | 
					
						
							|  |  |  |             tap.cask_files.count | 
					
						
							|  |  |  |           rescue | 
					
						
							|  |  |  |             error_tap_paths << tap.path | 
					
						
							|  |  |  |             0
 | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2024-06-11 09:57:07 +01:00
										 |  |  |           next if cask_count.zero? | 
					
						
							| 
									
										
										
										
											2024-02-20 17:59:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |           "#{tap.path} (#{Utils.pluralize("cask", cask_count, include_count: true)})" | 
					
						
							| 
									
										
										
										
											2024-06-11 09:57:07 +01:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-06-11 10:23:39 +01:00
										 |  |  |         add_info "Homebrew Cask Taps:", taps_info | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 10:31:51 +01:00
										 |  |  |         taps_string = Utils.pluralize("tap", error_tap_paths.count) | 
					
						
							|  |  |  |         "Unable to read from cask #{taps_string}: #{error_tap_paths.to_sentence}" if error_tap_paths.present? | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_load_path | 
					
						
							| 
									
										
										
										
											2024-04-08 09:47:06 -07:00
										 |  |  |         paths = $LOAD_PATH.map { user_tilde(_1) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         add_info "$LOAD_PATHS", paths.presence || none_string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         "$LOAD_PATH is empty" if paths.blank? | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_environment_variables | 
					
						
							|  |  |  |         environment_variables = %w[
 | 
					
						
							|  |  |  |           RUBYLIB | 
					
						
							|  |  |  |           RUBYOPT | 
					
						
							|  |  |  |           RUBYPATH | 
					
						
							|  |  |  |           RBENV_VERSION | 
					
						
							|  |  |  |           CHRUBY_VERSION | 
					
						
							|  |  |  |           GEM_HOME | 
					
						
							|  |  |  |           GEM_PATH | 
					
						
							|  |  |  |           BUNDLE_PATH | 
					
						
							|  |  |  |           PATH | 
					
						
							|  |  |  |           SHELL | 
					
						
							|  |  |  |           HOMEBREW_CASK_OPTS | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 16:18:15 +08:00
										 |  |  |         cask_environment_variables = (locale_variables + environment_variables).sort.filter_map do |var| | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |           next unless ENV.key?(var) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 16:42:01 +08:00
										 |  |  |           %Q(#{var}="#{Utils::Shell.sh_quote(ENV.fetch(var))}") | 
					
						
							| 
									
										
										
										
											2025-08-13 12:23:12 -07:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2025-08-19 15:22:58 +08:00
										 |  |  |         add_info "Cask Environment Variables:", cask_environment_variables | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nil | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def check_cask_xattr | 
					
						
							| 
									
										
										
										
											2025-06-24 03:07:04 +00:00
										 |  |  |         # If quarantine is not available, a warning is already shown by check_cask_quarantine_support so just return | 
					
						
							|  |  |  |         return unless Cask::Quarantine.available? | 
					
						
							| 
									
										
										
										
											2025-06-22 18:59:52 +00:00
										 |  |  |         return "Unable to find `xattr`." unless File.exist?("/usr/bin/xattr") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 10:02:19 +08:00
										 |  |  |         result = system_command "/usr/bin/xattr", args: ["-h"] | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return if result.status.success? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if result.stderr.include? "ImportError: No module named pkg_resources" | 
					
						
							| 
									
										
										
										
											2020-09-21 01:15:31 +10:00
										 |  |  |           result = Utils.popen_read "/usr/bin/python", "--version", err: :out | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 01:15:31 +10:00
										 |  |  |           if result.include? "Python 2.7" | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |             <<~EOS | 
					
						
							|  |  |  |               Your Python installation has a broken version of setuptools. | 
					
						
							| 
									
										
										
										
											2021-01-24 21:25:12 -05:00
										 |  |  |               To fix, reinstall macOS or run: | 
					
						
							|  |  |  |                 sudo /usr/bin/python -m pip install -I setuptools | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |             EOS | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             <<~EOS | 
					
						
							|  |  |  |               The system Python version is wrong. | 
					
						
							| 
									
										
										
										
											2021-01-24 21:25:12 -05:00
										 |  |  |               To fix, run: | 
					
						
							|  |  |  |                 defaults write com.apple.versioner.python Version 2.7
 | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |             EOS | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         elsif result.stderr.include? "pkg_resources.DistributionNotFound" | 
					
						
							| 
									
										
										
										
											2021-01-24 21:40:41 -05:00
										 |  |  |           "Your Python installation is unable to find `xattr`." | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |         else | 
					
						
							|  |  |  |           "unknown xattr error: #{result.stderr.split("\n").last}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[Tap]) } | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |       def non_core_taps | 
					
						
							|  |  |  |         @non_core_taps ||= Tap.installed.reject(&:core_tap?).reject(&:core_cask_tap?) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |       def check_for_duplicate_formulae | 
					
						
							| 
									
										
										
										
											2025-02-19 08:38:31 +00:00
										 |  |  |         return if ENV["HOMEBREW_TEST_BOT"].present? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         core_formula_names = CoreTap.instance.formula_names | 
					
						
							|  |  |  |         shadowed_formula_full_names = non_core_taps.flat_map do |tap| | 
					
						
							|  |  |  |           tap_formula_names = tap.formula_names.map { |s| s.delete_prefix("#{tap.name}/") } | 
					
						
							|  |  |  |           (core_formula_names & tap_formula_names).map { |f| "#{tap.name}/#{f}" } | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |         end.compact.sort | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         return if shadowed_formula_full_names.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |         installed_formula_tap_names = Formula.installed.filter_map(&:tap).uniq.reject(&:official?).map(&:name) | 
					
						
							|  |  |  |         shadowed_formula_tap_names = shadowed_formula_full_names.map { |s| s.rpartition("/").first }.uniq | 
					
						
							|  |  |  |         unused_shadowed_formula_tap_names = (shadowed_formula_tap_names - installed_formula_tap_names).sort | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         resolution = if unused_shadowed_formula_tap_names.empty? | 
					
						
							|  |  |  |           "Their taps are in use, so you must use these full names throughout Homebrew." | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           "Some of these can be resolved with:\n  brew untap #{unused_shadowed_formula_tap_names.join(" ")}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         <<~EOS | 
					
						
							|  |  |  |           The following formulae have the same name as core formulae: | 
					
						
							|  |  |  |             #{shadowed_formula_full_names.join("\n  ")} | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |           #{resolution} | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T.nilable(String)) } | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |       def check_for_duplicate_casks | 
					
						
							| 
									
										
										
										
											2025-02-19 08:38:31 +00:00
										 |  |  |         return if ENV["HOMEBREW_TEST_BOT"].present? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         core_cask_names = CoreCaskTap.instance.cask_tokens | 
					
						
							|  |  |  |         shadowed_cask_full_names = non_core_taps.flat_map do |tap| | 
					
						
							|  |  |  |           tap_cask_names = tap.cask_tokens.map { |s| s.delete_prefix("#{tap.name}/") } | 
					
						
							|  |  |  |           (core_cask_names & tap_cask_names).map { |f| "#{tap.name}/#{f}" } | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |         end.compact.sort | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         return if shadowed_cask_full_names.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |         installed_cask_tap_names = Cask::Caskroom.casks.filter_map(&:tap).uniq.reject(&:official?).map(&:name) | 
					
						
							|  |  |  |         shadowed_cask_tap_names = shadowed_cask_full_names.map { |s| s.rpartition("/").first }.uniq | 
					
						
							|  |  |  |         unused_shadowed_cask_tap_names = (shadowed_cask_tap_names - installed_cask_tap_names).sort | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         resolution = if unused_shadowed_cask_tap_names.empty? | 
					
						
							|  |  |  |           "Their taps are in use, so you must use these full names throughout Homebrew." | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           "Some of these can be resolved with:\n  brew untap #{unused_shadowed_cask_tap_names.join(" ")}" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         <<~EOS | 
					
						
							|  |  |  |           The following casks have the same name as core casks: | 
					
						
							|  |  |  |             #{shadowed_cask_full_names.join("\n  ")} | 
					
						
							| 
									
										
										
										
											2025-02-20 12:03:47 +08:00
										 |  |  |           #{resolution} | 
					
						
							| 
									
										
										
										
											2025-02-18 20:44:36 +08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       def all | 
					
						
							| 
									
										
										
										
											2021-06-22 20:57:09 +09:00
										 |  |  |         methods.map(&:to_s).grep(/^check_/).sort | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2020-07-10 10:36:59 -04:00
										 |  |  |       def cask_checks | 
					
						
							|  |  |  |         all.grep(/^check_cask_/) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2023-09-29 12:32:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-19 09:10:24 +01:00
										 |  |  |       sig { returns(String) } | 
					
						
							| 
									
										
										
										
											2023-09-29 12:32:22 +01:00
										 |  |  |       def current_user | 
					
						
							|  |  |  |         ENV.fetch("USER", "$(whoami)") | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2025-08-16 16:38:27 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:42:36 -07:00
										 |  |  |       sig { returns(T::Array[String]) } | 
					
						
							| 
									
										
										
										
											2025-08-16 16:38:27 -07:00
										 |  |  |       def paths | 
					
						
							| 
									
										
										
										
											2025-09-07 14:42:36 -07:00
										 |  |  |         @paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[String])) | 
					
						
							| 
									
										
										
										
											2025-08-16 16:38:27 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-10-21 19:52:43 +02:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-01-04 23:14:58 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2016-04-25 17:58:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | require "extend/os/diagnostic" |