| 
									
										
										
										
											2023-02-14 08:48:00 -08:00
										 |  |  | # typed: true | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require "reinstall" | 
					
						
							|  |  |  | require "formula_installer" | 
					
						
							|  |  |  | require "development_tools" | 
					
						
							|  |  |  | require "messages" | 
					
						
							|  |  |  | require "cleanup" | 
					
						
							| 
									
										
										
										
											2021-09-09 13:30:55 -07:00
										 |  |  | require "utils/topological_hash" | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |   # Helper functions for upgrading formulae. | 
					
						
							|  |  |  |   # | 
					
						
							|  |  |  |   # @api private | 
					
						
							|  |  |  |   module Upgrade | 
					
						
							|  |  |  |     module_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |     def upgrade_formulae( | 
					
						
							|  |  |  |       formulae_to_install, | 
					
						
							|  |  |  |       flags:, | 
					
						
							| 
									
										
										
										
											2021-08-31 12:27:14 -04:00
										 |  |  |       dry_run: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       installed_on_request: false, | 
					
						
							|  |  |  |       force_bottle: false, | 
					
						
							|  |  |  |       build_from_source_formulae: [], | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  |       dependents: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       interactive: false, | 
					
						
							|  |  |  |       keep_tmp: false, | 
					
						
							| 
									
										
										
										
											2022-07-26 12:15:53 +01:00
										 |  |  |       debug_symbols: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       force: false, | 
					
						
							| 
									
										
										
										
											2024-03-07 13:13:28 -08:00
										 |  |  |       overwrite: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       debug: false, | 
					
						
							|  |  |  |       quiet: false, | 
					
						
							|  |  |  |       verbose: false | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       return if formulae_to_install.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Sort keg-only before non-keg-only formulae to avoid any needless conflicts | 
					
						
							|  |  |  |       # with outdated, non-keg-only versions of formulae being upgraded. | 
					
						
							|  |  |  |       formulae_to_install.sort! do |a, b| | 
					
						
							|  |  |  |         if !a.keg_only? && b.keg_only? | 
					
						
							|  |  |  |           1
 | 
					
						
							|  |  |  |         elsif a.keg_only? && !b.keg_only? | 
					
						
							|  |  |  |           -1
 | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           0
 | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 13:30:55 -07:00
										 |  |  |       dependency_graph = Utils::TopologicalHash.graph_package_dependencies(formulae_to_install) | 
					
						
							|  |  |  |       begin | 
					
						
							|  |  |  |         formulae_to_install = dependency_graph.tsort & formulae_to_install | 
					
						
							|  |  |  |       rescue TSort::Cyclic | 
					
						
							| 
									
										
										
										
											2021-09-12 07:56:37 -07:00
										 |  |  |         raise CyclicDependencyError, dependency_graph.strongly_connected_components if Homebrew::EnvConfig.developer? | 
					
						
							| 
									
										
										
										
											2021-09-09 13:30:55 -07:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |       formula_installers = formulae_to_install.filter_map do |formula| | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         Migrator.migrate_if_needed(formula, force:, dry_run:) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         begin | 
					
						
							| 
									
										
										
										
											2021-09-01 05:48:12 -07:00
										 |  |  |           fi = create_formula_installer( | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |             formula, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |             flags:, | 
					
						
							|  |  |  |             installed_on_request:, | 
					
						
							|  |  |  |             force_bottle:, | 
					
						
							|  |  |  |             build_from_source_formulae:, | 
					
						
							|  |  |  |             interactive:, | 
					
						
							|  |  |  |             keep_tmp:, | 
					
						
							|  |  |  |             debug_symbols:, | 
					
						
							|  |  |  |             force:, | 
					
						
							| 
									
										
										
										
											2024-03-08 08:27:04 +00:00
										 |  |  |             overwrite:, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |             debug:, | 
					
						
							|  |  |  |             quiet:, | 
					
						
							|  |  |  |             verbose:, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |           ) | 
					
						
							| 
									
										
										
										
											2021-09-10 06:01:37 -07:00
										 |  |  |           unless dry_run | 
					
						
							|  |  |  |             fi.prelude | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 17:17:24 +00:00
										 |  |  |             # Don't need to install this bottle if all of the runtime | 
					
						
							|  |  |  |             # dependencies have the same or newer version already installed. | 
					
						
							|  |  |  |             next if dependents && fi.bottle_tab_runtime_dependencies.presence&.all? do |dependency, hash| | 
					
						
							|  |  |  |               dependency_formula = begin | 
					
						
							|  |  |  |                 Formula[dependency] | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  |               rescue FormulaUnavailableError | 
					
						
							|  |  |  |                 nil | 
					
						
							|  |  |  |               end | 
					
						
							| 
									
										
										
										
											2023-11-10 17:17:24 +00:00
										 |  |  |               next false if dependency_formula.nil? | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-14 16:46:53 +00:00
										 |  |  |               next true if dependency_formula.latest_version_installed? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-10 17:17:24 +00:00
										 |  |  |               installed_version = dependency_formula.any_installed_version | 
					
						
							|  |  |  |               next false unless installed_version | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               next false if hash["version"].blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               # Tabs prior to 4.1.18 did not have revision or pkg_version fields. | 
					
						
							|  |  |  |               # As a result, we have to be more conversative when we do not have | 
					
						
							|  |  |  |               # a revision in the tab and assume that if the formula has a | 
					
						
							|  |  |  |               # the same version and a non-zero revision that it needs upgraded. | 
					
						
							|  |  |  |               tab_version = Version.new(hash["version"]) | 
					
						
							|  |  |  |               if hash["revision"].present? | 
					
						
							|  |  |  |                 tab_pkg_version = PkgVersion.new(tab_version, hash["revision"]) | 
					
						
							|  |  |  |                 installed_version >= tab_pkg_version | 
					
						
							|  |  |  |               elsif installed_version.version == tab_version | 
					
						
							|  |  |  |                 dependency_formula.revision.zero? | 
					
						
							|  |  |  |               else | 
					
						
							|  |  |  |                 installed_version.version > tab_version | 
					
						
							|  |  |  |               end | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-10 06:01:37 -07:00
										 |  |  |             fi.fetch | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2021-08-31 07:06:39 -07:00
										 |  |  |           fi | 
					
						
							| 
									
										
										
										
											2021-09-10 06:01:37 -07:00
										 |  |  |         rescue CannotInstallFormulaError => e | 
					
						
							|  |  |  |           ofail e | 
					
						
							| 
									
										
										
										
											2021-09-14 03:37:40 +01:00
										 |  |  |           nil | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  |         rescue UnsatisfiedRequirements, DownloadError => e | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |           ofail "#{formula}: #{e}" | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  |           nil | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-02-22 23:29:55 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       formula_installers.each do |fi| | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         upgrade_formula(fi, dry_run:, verbose:) | 
					
						
							|  |  |  |         Cleanup.install_formula_clean!(fi.formula, dry_run:) | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 10:11:40 -04:00
										 |  |  |     def outdated_kegs(formula) | 
					
						
							|  |  |  |       [formula, *formula.old_installed_formulae].map(&:linked_keg) | 
					
						
							|  |  |  |                                                 .select(&:directory?) | 
					
						
							|  |  |  |                                                 .map { |k| Keg.new(k.resolved_path) } | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def print_upgrade_message(formula, fi_options) | 
					
						
							|  |  |  |       version_upgrade = if formula.optlinked? | 
					
						
							|  |  |  |         "#{Keg.new(formula.opt_prefix).version} -> #{formula.pkg_version}" | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         "-> #{formula.pkg_version}" | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2024-03-27 17:44:09 -04:00
										 |  |  |       oh1 "Upgrading #{Formatter.identifier(formula.full_specified_name)}" | 
					
						
							|  |  |  |       puts "  #{version_upgrade} #{fi_options.to_a.join(" ")}" | 
					
						
							| 
									
										
										
										
											2021-06-15 10:11:40 -04:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 05:48:12 -07:00
										 |  |  |     def create_formula_installer( | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       formula, | 
					
						
							|  |  |  |       flags:, | 
					
						
							|  |  |  |       installed_on_request: false, | 
					
						
							|  |  |  |       force_bottle: false, | 
					
						
							|  |  |  |       build_from_source_formulae: [], | 
					
						
							|  |  |  |       interactive: false, | 
					
						
							|  |  |  |       keep_tmp: false, | 
					
						
							| 
									
										
										
										
											2022-07-26 12:15:53 +01:00
										 |  |  |       debug_symbols: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       force: false, | 
					
						
							| 
									
										
										
										
											2024-03-07 13:13:28 -08:00
										 |  |  |       overwrite: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       debug: false, | 
					
						
							|  |  |  |       quiet: false, | 
					
						
							|  |  |  |       verbose: false | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |       if formula.opt_prefix.directory? | 
					
						
							|  |  |  |         keg = Keg.new(formula.opt_prefix.resolved_path) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         keg_had_linked_opt = true | 
					
						
							|  |  |  |         keg_was_linked = keg.linked? | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       if formula.opt_prefix.directory? | 
					
						
							|  |  |  |         keg = Keg.new(formula.opt_prefix.resolved_path) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         tab = Tab.for_keg(keg) | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       build_options = BuildOptions.new(Options.create(flags), formula.options) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       options = build_options.used_options | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       options |= formula.build.used_options | 
					
						
							|  |  |  |       options &= formula.options | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 07:06:39 -07:00
										 |  |  |       FormulaInstaller.new( | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         formula, | 
					
						
							| 
									
										
										
										
											2020-11-18 05:37:12 +01:00
										 |  |  |         **{ | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           options:, | 
					
						
							| 
									
										
										
										
											2020-11-18 05:37:12 +01:00
										 |  |  |           link_keg:                   keg_had_linked_opt ? keg_was_linked : nil, | 
					
						
							|  |  |  |           installed_as_dependency:    tab&.installed_as_dependency, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |           installed_on_request:       installed_on_request || tab&.installed_on_request, | 
					
						
							|  |  |  |           build_bottle:               tab&.built_bottle?, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           force_bottle:, | 
					
						
							|  |  |  |           build_from_source_formulae:, | 
					
						
							|  |  |  |           interactive:, | 
					
						
							|  |  |  |           keep_tmp:, | 
					
						
							|  |  |  |           debug_symbols:, | 
					
						
							|  |  |  |           force:, | 
					
						
							| 
									
										
										
										
											2024-03-08 08:27:04 +00:00
										 |  |  |           overwrite:, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           debug:, | 
					
						
							|  |  |  |           quiet:, | 
					
						
							|  |  |  |           verbose:, | 
					
						
							| 
									
										
										
										
											2020-11-18 05:37:12 +01:00
										 |  |  |         }.compact, | 
					
						
							|  |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-09-01 05:48:12 -07:00
										 |  |  |     private_class_method :create_formula_installer | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 12:27:14 -04:00
										 |  |  |     def upgrade_formula(formula_installer, dry_run: false, verbose: false) | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  |       formula = formula_installer.formula | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 12:27:14 -04:00
										 |  |  |       if dry_run | 
					
						
							| 
									
										
										
										
											2022-09-03 16:01:55 +09:00
										 |  |  |         Install.print_dry_run_dependencies(formula, formula_installer.compute_dependencies) do |f| | 
					
						
							|  |  |  |           name = f.full_specified_name | 
					
						
							|  |  |  |           if f.optlinked? | 
					
						
							|  |  |  |             "#{name} #{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}" | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             "#{name} #{f.pkg_version}" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-08-31 12:27:14 -04:00
										 |  |  |         return | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-10 08:31:53 -07:00
										 |  |  |       install_formula(formula_installer, upgrade: true) | 
					
						
							|  |  |  |     rescue BuildError => e | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |       e.dump(verbose:) | 
					
						
							| 
									
										
										
										
											2021-09-10 08:31:53 -07:00
										 |  |  |       puts | 
					
						
							|  |  |  |       Homebrew.failed = true | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     private_class_method :upgrade_formula | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def install_formula(formula_installer, upgrade:) | 
					
						
							|  |  |  |       formula = formula_installer.formula | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-13 07:38:01 -07:00
										 |  |  |       formula_installer.check_installation_already_attempted | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-10 08:31:53 -07:00
										 |  |  |       if upgrade | 
					
						
							|  |  |  |         print_upgrade_message(formula, formula_installer.options) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kegs = outdated_kegs(formula) | 
					
						
							|  |  |  |         linked_kegs = kegs.select(&:linked?) | 
					
						
							| 
									
										
										
										
											2021-09-13 07:38:01 -07:00
										 |  |  |       else | 
					
						
							|  |  |  |         formula.print_tap_action | 
					
						
							| 
									
										
										
										
											2021-09-10 08:31:53 -07:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-09-09 10:54:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       # first we unlink the currently active keg for this formula otherwise it is | 
					
						
							|  |  |  |       # possible for the existing build to interfere with the build we are about to | 
					
						
							|  |  |  |       # do! Seriously, it happens! | 
					
						
							| 
									
										
										
										
											2021-09-10 08:31:53 -07:00
										 |  |  |       kegs.each(&:unlink) if kegs.present? | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-30 07:47:47 -07:00
										 |  |  |       formula_installer.install | 
					
						
							|  |  |  |       formula_installer.finish | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |     rescue FormulaInstallationAlreadyAttemptedError | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       # We already attempted to upgrade f as part of the dependency tree of | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |       # another formula. In that case, don't generate an error, just move on. | 
					
						
							|  |  |  |       nil | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |     ensure | 
					
						
							|  |  |  |       # restore previous installation state if build failed | 
					
						
							|  |  |  |       begin | 
					
						
							| 
									
										
										
										
											2023-02-14 08:48:00 -08:00
										 |  |  |         linked_kegs&.each(&:link) unless formula.latest_version_installed? | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       rescue | 
					
						
							|  |  |  |         nil | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:24:42 -07:00
										 |  |  |     def check_broken_dependents(installed_formulae) | 
					
						
							|  |  |  |       CacheStoreDatabase.use(:linkage) do |db| | 
					
						
							| 
									
										
										
										
											2020-08-26 08:53:47 -07:00
										 |  |  |         installed_formulae.flat_map(&:runtime_installed_formula_dependents) | 
					
						
							|  |  |  |                           .uniq | 
					
						
							|  |  |  |                           .select do |f| | 
					
						
							| 
									
										
										
										
											2020-08-31 10:58:36 -07:00
										 |  |  |           keg = f.any_installed_keg | 
					
						
							| 
									
										
										
										
											2020-08-26 08:53:47 -07:00
										 |  |  |           next unless keg | 
					
						
							| 
									
										
										
										
											2020-10-29 08:31:04 +00:00
										 |  |  |           next unless keg.directory? | 
					
						
							| 
									
										
										
										
											2020-08-26 08:53:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |           LinkageChecker.new(keg, cache_db: db) | 
					
						
							|  |  |  |                         .broken_library_linkage? | 
					
						
							|  |  |  |         end.compact | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-08-30 01:24:42 -07:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |     def self.puts_no_installed_dependents_check_disable_message_if_not_already! | 
					
						
							|  |  |  |       return if Homebrew::EnvConfig.no_env_hints? | 
					
						
							|  |  |  |       return if Homebrew::EnvConfig.no_installed_dependents_check? | 
					
						
							|  |  |  |       return if @puts_no_installed_dependents_check_disable_message_if_not_already | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       puts "Disable this behaviour by setting HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK." | 
					
						
							|  |  |  |       puts "Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`)." | 
					
						
							|  |  |  |       @puts_no_installed_dependents_check_disable_message_if_not_already = true | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |     def check_installed_dependents( | 
					
						
							|  |  |  |       formulae, | 
					
						
							|  |  |  |       flags:, | 
					
						
							|  |  |  |       dry_run: false, | 
					
						
							|  |  |  |       installed_on_request: false, | 
					
						
							|  |  |  |       force_bottle: false, | 
					
						
							|  |  |  |       build_from_source_formulae: [], | 
					
						
							|  |  |  |       interactive: false, | 
					
						
							|  |  |  |       keep_tmp: false, | 
					
						
							| 
									
										
										
										
											2022-07-26 12:15:53 +01:00
										 |  |  |       debug_symbols: false, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       force: false, | 
					
						
							|  |  |  |       debug: false, | 
					
						
							|  |  |  |       quiet: false, | 
					
						
							|  |  |  |       verbose: false | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |       if Homebrew::EnvConfig.no_installed_dependents_check? | 
					
						
							| 
									
										
										
										
											2023-08-04 09:36:27 +01:00
										 |  |  |         unless Homebrew::EnvConfig.no_env_hints? | 
					
						
							|  |  |  |           opoo <<~EOS | 
					
						
							|  |  |  |             HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK is set: not checking for outdated | 
					
						
							|  |  |  |             dependents or dependents with broken linkage! | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-10-06 10:50:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-26 13:05:50 +00:00
										 |  |  |       installed_formulae = (dry_run ? formulae : FormulaInstaller.installed.to_a).dup | 
					
						
							|  |  |  |       installed_formulae.reject! { |f| f.core_formula? && f.versioned_formula? } | 
					
						
							| 
									
										
										
										
											2020-08-30 01:24:42 -07:00
										 |  |  |       return if installed_formulae.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       already_broken_dependents = check_broken_dependents(installed_formulae) | 
					
						
							| 
									
										
										
										
											2020-08-26 08:53:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-03 09:18:58 -04:00
										 |  |  |       # TODO: this should be refactored to use FormulaInstaller new logic | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       outdated_dependents = | 
					
						
							|  |  |  |         installed_formulae.flat_map(&:runtime_installed_formula_dependents) | 
					
						
							| 
									
										
										
										
											2020-09-18 00:58:53 -07:00
										 |  |  |                           .uniq | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |                           .select(&:outdated?) | 
					
						
							| 
									
										
										
										
											2021-11-27 15:51:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       # Ensure we never attempt a source build for outdated dependents of upgraded formulae. | 
					
						
							|  |  |  |       outdated_dependents, skipped_dependents = outdated_dependents.partition do |dependent| | 
					
						
							| 
									
										
										
										
											2021-12-01 00:42:06 +08:00
										 |  |  |         dependent.bottled? && dependent.deps.map(&:to_formula).all?(&:bottled?) | 
					
						
							| 
									
										
										
										
											2021-11-27 15:51:57 +08:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if skipped_dependents.present? | 
					
						
							|  |  |  |         opoo <<~EOS | 
					
						
							|  |  |  |           The following dependents of upgraded formulae are outdated but will not | 
					
						
							| 
									
										
										
										
											2021-11-29 20:42:41 +08:00
										 |  |  |           be upgraded because they are not bottled: | 
					
						
							| 
									
										
										
										
											2021-11-27 15:51:57 +08:00
										 |  |  |             #{skipped_dependents * "\n  "} | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 08:53:47 -07:00
										 |  |  |       return if outdated_dependents.blank? && already_broken_dependents.blank? | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       outdated_dependents -= installed_formulae if dry_run | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       upgradeable_dependents = | 
					
						
							|  |  |  |         outdated_dependents.reject(&:pinned?) | 
					
						
							|  |  |  |                            .sort { |a, b| depends_on(a, b) } | 
					
						
							|  |  |  |       pinned_dependents = | 
					
						
							|  |  |  |         outdated_dependents.select(&:pinned?) | 
					
						
							|  |  |  |                            .sort { |a, b| depends_on(a, b) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if pinned_dependents.present? | 
					
						
							| 
									
										
										
										
											2023-02-27 20:16:34 -08:00
										 |  |  |         plural = Utils.pluralize("dependent", pinned_dependents.count) | 
					
						
							| 
									
										
										
										
											2023-12-05 23:11:59 -08:00
										 |  |  |         opoo "Not upgrading #{pinned_dependents.count} pinned #{plural}:" | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         puts(pinned_dependents.map do |f| | 
					
						
							|  |  |  |           "#{f.full_specified_name} #{f.pkg_version}" | 
					
						
							|  |  |  |         end.join(", ")) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       # Print the upgradable dependents. | 
					
						
							|  |  |  |       if upgradeable_dependents.blank? | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         ohai "No outdated dependents to upgrade!" unless dry_run | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2023-02-27 20:16:34 -08:00
										 |  |  |         formula_plural = Utils.pluralize("formula", installed_formulae.count, plural: "e") | 
					
						
							| 
									
										
										
										
											2022-02-23 11:43:08 -07:00
										 |  |  |         upgrade_verb = dry_run ? "Would upgrade" : "Upgrading" | 
					
						
							| 
									
										
										
										
											2023-03-19 23:17:15 -04:00
										 |  |  |         ohai "#{upgrade_verb} #{Utils.pluralize("dependent", upgradeable_dependents.count, | 
					
						
							| 
									
										
										
										
											2023-03-20 07:23:17 -04:00
										 |  |  |                                                 include_count: true)} of upgraded #{formula_plural}:" | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |         Upgrade.puts_no_installed_dependents_check_disable_message_if_not_already! | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         formulae_upgrades = upgradeable_dependents.map do |f| | 
					
						
							|  |  |  |           name = f.full_specified_name | 
					
						
							|  |  |  |           if f.optlinked? | 
					
						
							|  |  |  |             "#{name} #{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}" | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             "#{name} #{f.pkg_version}" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         puts formulae_upgrades.join(", ") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       unless dry_run | 
					
						
							|  |  |  |         upgrade_formulae( | 
					
						
							|  |  |  |           upgradeable_dependents, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           flags:, | 
					
						
							|  |  |  |           installed_on_request:, | 
					
						
							|  |  |  |           force_bottle:, | 
					
						
							|  |  |  |           build_from_source_formulae:, | 
					
						
							| 
									
										
										
										
											2023-09-04 22:18:55 -04:00
										 |  |  |           dependents:                 true, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           interactive:, | 
					
						
							|  |  |  |           keep_tmp:, | 
					
						
							|  |  |  |           debug_symbols:, | 
					
						
							|  |  |  |           force:, | 
					
						
							|  |  |  |           debug:, | 
					
						
							|  |  |  |           quiet:, | 
					
						
							|  |  |  |           verbose:, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         ) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 08:31:04 +00:00
										 |  |  |       # Update installed formulae after upgrading | 
					
						
							| 
									
										
										
										
											2020-10-26 19:29:55 -07:00
										 |  |  |       installed_formulae = FormulaInstaller.installed.to_a | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       # Assess the dependents tree again now we've upgraded. | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |       unless dry_run | 
					
						
							|  |  |  |         oh1 "Checking for dependents of upgraded formulae..." | 
					
						
							|  |  |  |         Upgrade.puts_no_installed_dependents_check_disable_message_if_not_already! | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-11-25 09:10:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:24:42 -07:00
										 |  |  |       broken_dependents = check_broken_dependents(installed_formulae) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       if broken_dependents.blank? | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         if dry_run | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |           ohai "No currently broken dependents found!" | 
					
						
							|  |  |  |           opoo "If they are broken by the upgrade they will also be upgraded or reinstalled." | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           ohai "No broken dependents found!" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       reinstallable_broken_dependents = | 
					
						
							|  |  |  |         broken_dependents.reject(&:outdated?) | 
					
						
							|  |  |  |                          .reject(&:pinned?) | 
					
						
							|  |  |  |                          .sort { |a, b| depends_on(a, b) } | 
					
						
							|  |  |  |       outdated_pinned_broken_dependents = | 
					
						
							|  |  |  |         broken_dependents.select(&:outdated?) | 
					
						
							|  |  |  |                          .select(&:pinned?) | 
					
						
							|  |  |  |                          .sort { |a, b| depends_on(a, b) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Print the pinned dependents. | 
					
						
							|  |  |  |       if outdated_pinned_broken_dependents.present? | 
					
						
							|  |  |  |         count = outdated_pinned_broken_dependents.count | 
					
						
							| 
									
										
										
										
											2023-02-27 20:16:34 -08:00
										 |  |  |         plural = Utils.pluralize("dependent", outdated_pinned_broken_dependents.count) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         onoe "Not reinstalling #{count} broken and outdated, but pinned #{plural}:" | 
					
						
							|  |  |  |         $stderr.puts(outdated_pinned_broken_dependents.map do |f| | 
					
						
							|  |  |  |           "#{f.full_specified_name} #{f.pkg_version}" | 
					
						
							|  |  |  |         end.join(", ")) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Print the broken dependents. | 
					
						
							|  |  |  |       if reinstallable_broken_dependents.blank? | 
					
						
							|  |  |  |         ohai "No broken dependents to reinstall!" | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2023-03-19 23:17:15 -04:00
										 |  |  |         ohai "Reinstalling #{Utils.pluralize("dependent", reinstallable_broken_dependents.count, | 
					
						
							| 
									
										
										
										
											2023-03-20 07:23:17 -04:00
										 |  |  |                                              include_count: true)} with broken linkage from source:"
 | 
					
						
							| 
									
										
										
										
											2021-11-26 13:14:10 +00:00
										 |  |  |         Upgrade.puts_no_installed_dependents_check_disable_message_if_not_already! | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         puts reinstallable_broken_dependents.map(&:full_specified_name) | 
					
						
							|  |  |  |                                             .join(", ") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       return if dry_run | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       reinstallable_broken_dependents.each do |formula| | 
					
						
							|  |  |  |         Homebrew.reinstall_formula( | 
					
						
							|  |  |  |           formula, | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           flags:, | 
					
						
							|  |  |  |           force_bottle:, | 
					
						
							| 
									
										
										
										
											2021-04-27 17:16:15 +01:00
										 |  |  |           build_from_source_formulae: build_from_source_formulae + [formula.full_name], | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |           interactive:, | 
					
						
							|  |  |  |           keep_tmp:, | 
					
						
							|  |  |  |           debug_symbols:, | 
					
						
							|  |  |  |           force:, | 
					
						
							|  |  |  |           debug:, | 
					
						
							|  |  |  |           quiet:, | 
					
						
							|  |  |  |           verbose:, | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       rescue FormulaInstallationAlreadyAttemptedError | 
					
						
							|  |  |  |         # We already attempted to reinstall f as part of the dependency tree of | 
					
						
							|  |  |  |         # another formula. In that case, don't generate an error, just move on. | 
					
						
							|  |  |  |         nil | 
					
						
							| 
									
										
										
										
											2020-11-13 10:07:02 -05:00
										 |  |  |       rescue CannotInstallFormulaError, DownloadError => e | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         ofail e | 
					
						
							|  |  |  |       rescue BuildError => e | 
					
						
							| 
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 |  |  |         e.dump(verbose:) | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         puts | 
					
						
							|  |  |  |         Homebrew.failed = true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 00:04:10 +00:00
										 |  |  |     def depends_on(one, two) | 
					
						
							|  |  |  |       if one.any_installed_keg | 
					
						
							| 
									
										
										
										
											2023-12-14 02:52:30 +00:00
										 |  |  |             &.runtime_dependencies | 
					
						
							|  |  |  |             &.any? { |dependency| dependency["full_name"] == two.full_name } | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |         1
 | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2023-03-11 00:04:10 +00:00
										 |  |  |         one <=> two | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2020-08-24 00:37:22 +02:00
										 |  |  |     private_class_method :depends_on | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end |