diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 9895706138..e7f56cb919 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -220,10 +220,7 @@ module Homebrew Install.perform_preinstall_checks_once - # Main block: if asking the user is enabled, show dependency and size information. - Install.ask_formulae(formulae_to_install, args: args) if args.ask? - - Upgrade.upgrade_formulae( + formulae_installer = Upgrade.get_formulae_dependencies( formulae_to_install, flags: args.flags_only, dry_run: args.dry_run?, @@ -239,10 +236,11 @@ module Homebrew verbose: args.verbose?, ) - Upgrade.check_installed_dependents( + dependants = Upgrade.get_dependants( formulae_to_install, flags: args.flags_only, dry_run: args.dry_run?, + ask: args.ask?, force_bottle: args.force_bottle?, build_from_source_formulae: args.build_from_source_formulae, interactive: args.interactive?, @@ -254,6 +252,36 @@ module Homebrew verbose: args.verbose?, ) + formulae_dependencies = formulae_installer.flat_map do |f| + [f.formula, f.compute_dependencies.flatten.filter do |c| + c.is_a? Dependency + end.flat_map(&:to_formula)] + end.flatten.uniq + formulae_dependencies.concat(dependants.upgradeable) if dependants + # Main block: if asking the user is enabled, show dependency and size information. + Install.ask_formulae(formulae_dependencies, args: args) if args.ask? + + Upgrade.upgrade_formulae(formulae_installer, + dry_run: args.dry_run?, + verbose: args.verbose?) + + if dependants + Upgrade.upgrade_dependents( + dependants, formulae_to_install, + flags: args.flags_only, + dry_run: args.dry_run?, + force_bottle: args.force_bottle?, + build_from_source_formulae: args.build_from_source_formulae, + interactive: args.interactive?, + keep_tmp: args.keep_tmp?, + debug_symbols: args.debug_symbols?, + force: args.force?, + debug: args.debug?, + quiet: args.quiet?, + verbose: args.verbose? + ) + end + true end diff --git a/Library/Homebrew/upgrade.rb b/Library/Homebrew/upgrade.rb index 112893aac1..6bac1f4c7e 100644 --- a/Library/Homebrew/upgrade.rb +++ b/Library/Homebrew/upgrade.rb @@ -11,7 +11,9 @@ require "utils/topological_hash" module Homebrew # Helper functions for upgrading formulae. module Upgrade - def self.upgrade_formulae( + Dependents = Struct.new(:upgradeable, :pinned, :skipped) + + def self.get_formulae_dependencies( formulae_to_install, flags:, dry_run: false, @@ -48,7 +50,7 @@ module Homebrew raise CyclicDependencyError, dependency_graph.strongly_connected_components if Homebrew::EnvConfig.developer? end - formula_installers = formulae_to_install.filter_map do |formula| + formulae_to_install.filter_map do |formula| Migrator.migrate_if_needed(formula, force:, dry_run:) begin fi = create_formula_installer( @@ -65,18 +67,15 @@ module Homebrew quiet:, verbose:, ) - unless dry_run - fi.prelude - + if !dry_run && dependents && fi.bottle_tab_runtime_dependencies.presence&.all? do |dependency, hash| + minimum_version = Version.new(hash["version"]) if hash["version"].present? + Dependency.new(dependency).installed?(minimum_version:, minimum_revision: hash["revision"]) + end # 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| - minimum_version = Version.new(hash["version"]) if hash["version"].present? - Dependency.new(dependency).installed?(minimum_version:, minimum_revision: hash["revision"]) - end - - fi.fetch + next end + fi rescue CannotInstallFormulaError => e ofail e @@ -86,8 +85,19 @@ module Homebrew nil end end + end + def self.upgrade_formulae(formula_installers, dry_run: false, verbose: false) formula_installers.each do |fi| + begin + fi.prelude + fi.fetch + rescue CannotInstallFormulaError => e + ofail e + rescue UnsatisfiedRequirements, DownloadError => e + ofail "#{formula}: #{e}" + end + upgrade_formula(fi, dry_run:, verbose:) Cleanup.install_formula_clean!(fi.formula, dry_run:) end @@ -250,10 +260,11 @@ module Homebrew @puts_no_installed_dependents_check_disable_message_if_not_already = true end - def self.check_installed_dependents( + def self.get_dependants( formulae, flags:, dry_run: false, + ask: false, installed_on_request: false, force_bottle: false, build_from_source_formulae: [], @@ -275,7 +286,7 @@ module Homebrew return end - installed_formulae = (dry_run ? formulae : FormulaInstaller.installed.to_a).dup + installed_formulae = ((dry_run || ask) ? formulae : FormulaInstaller.installed.to_a).dup installed_formulae.reject! { |f| f.core_formula? && f.versioned_formula? } return if installed_formulae.empty? @@ -292,14 +303,6 @@ module Homebrew dependent.bottled? && dependent.deps.map(&:to_formula).all?(&:bottled?) end - if skipped_dependents.present? - opoo <<~EOS - The following dependents of upgraded formulae are outdated but will not - be upgraded because they are not bottled: - #{skipped_dependents * "\n "} - EOS - end - return if outdated_dependents.blank? && already_broken_dependents.blank? outdated_dependents -= installed_formulae if dry_run @@ -311,24 +314,50 @@ module Homebrew outdated_dependents.select(&:pinned?) .sort { |a, b| depends_on(a, b) } - if pinned_dependents.present? - plural = Utils.pluralize("dependent", pinned_dependents.count) - opoo "Not upgrading #{pinned_dependents.count} pinned #{plural}:" - puts(pinned_dependents.map do |f| + Dependents.new(upgradeable_dependents, pinned_dependents, skipped_dependents) + end + + def self.upgrade_dependents(deps, formulae, + flags:, + dry_run: false, + installed_on_request: false, + force_bottle: false, + build_from_source_formulae: [], + interactive: false, + keep_tmp: false, + debug_symbols: false, + force: false, + debug: false, + quiet: false, + verbose: false) + upgradeable = deps.upgradeable + pinned = deps.pinned + skipped = deps.skipped + if pinned.present? + plural = Utils.pluralize("dependent", pinned.count) + opoo "Not upgrading #{pinned.count} pinned #{plural}:" + puts(pinned.map do |f| "#{f.full_specified_name} #{f.pkg_version}" end.join(", ")) end - + if skipped.present? + opoo <<~EOS + The following dependents of upgraded formulae are outdated but will not + be upgraded because they are not bottled: + #{skipped * "\n "} + EOS + end # Print the upgradable dependents. - if upgradeable_dependents.blank? + if upgradeable.blank? ohai "No outdated dependents to upgrade!" unless dry_run else + installed_formulae = (dry_run ? formulae : FormulaInstaller.installed.to_a).dup formula_plural = Utils.pluralize("formula", installed_formulae.count, plural: "e") upgrade_verb = dry_run ? "Would upgrade" : "Upgrading" - ohai "#{upgrade_verb} #{Utils.pluralize("dependent", upgradeable_dependents.count, + ohai "#{upgrade_verb} #{Utils.pluralize("dependent", upgradeable.count, include_count: true)} of upgraded #{formula_plural}:" Upgrade.puts_no_installed_dependents_check_disable_message_if_not_already! - formulae_upgrades = upgradeable_dependents.map do |f| + formulae_upgrades = upgradeable.map do |f| name = f.full_specified_name if f.optlinked? "#{name} #{Keg.new(f.opt_prefix).version} -> #{f.pkg_version}" @@ -340,8 +369,8 @@ module Homebrew end unless dry_run - upgrade_formulae( - upgradeable_dependents, + formulae_dependencies = get_formulae_dependencies( + upgradeable, flags:, force_bottle:, build_from_source_formulae:, @@ -354,6 +383,7 @@ module Homebrew quiet:, verbose:, ) + upgrade_formulae formulae_dependencies end # Update installed formulae after upgrading