From 56e6710064bcbe8edc1caa97ed0bfb6ac8450e99 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Thu, 10 Jun 2021 12:53:25 -0400 Subject: [PATCH 01/14] Upgrade outdated formulae with `brew install` --- Library/Homebrew/cmd/install.rb | 24 ++++++++++++++++++++++++ Library/Homebrew/formula_installer.rb | 7 +------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index c7d079cb84..ecce00852b 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -396,6 +396,20 @@ module Homebrew f.print_tap_action build_options = f.build + if f.outdated? && !f.head? + formulae = [f] + f.old_installed_formulae + version_upgrade = "#{f.linked_version} -> #{f.pkg_version}" + + oh1 <<~EOS + #{f.name} #{f.linked_version} is installed and out of date + Upgrading #{Formatter.identifier(f.name)} #{version_upgrade} + EOS + outdated_kegs = formulae.map(&:linked_keg) + .select(&:directory?) + .map { |k| Keg.new(k.resolved_path) } + linked_kegs = outdated_kegs.select(&:linked?) + end + fi = FormulaInstaller.new( f, **{ @@ -419,6 +433,9 @@ module Homebrew ) fi.prelude fi.fetch + + outdated_kegs.each(&:unlink) if outdated_kegs.present? + fi.install fi.finish rescue FormulaInstallationAlreadyAttemptedError @@ -427,5 +444,12 @@ module Homebrew nil rescue CannotInstallFormulaError => e ofail e.message + ensure + begin + # Re-link kegs if upgrade fails + linked_kegs.each(&:link) unless formula.latest_version_installed? + rescue + nil + end end end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 1d9193dcab..cd5d6aa846 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -351,12 +351,7 @@ class FormulaInstaller message = <<~EOS #{formula.name} #{formula.linked_version} is already installed EOS - if formula.outdated? && !formula.head? - message += <<~EOS - To upgrade to #{formula.pkg_version}, run: - brew upgrade #{formula.full_name} - EOS - elsif only_deps? + if only_deps? message = nil else # some other version is already installed *and* linked From b6cb3d2b6a69385648924e1be51efc282d9a1623 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Thu, 10 Jun 2021 15:06:12 -0400 Subject: [PATCH 02/14] Add `HOMEBREW_NO_INSTALL_UPGRADE` --- Library/Homebrew/env_config.rb | 4 ++++ Library/Homebrew/formula_installer.rb | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index def50503d5..039560e834 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -257,6 +257,10 @@ module Homebrew "`HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS` days.", boolean: true, }, + HOMEBREW_NO_INSTALL_UPGRADE: { + description: "If set, `brew install` will not automatically upgrade installed and out of date formulae", + boolean: true, + }, HOMEBREW_PRY: { description: "If set, use Pry for the `brew irb` command.", boolean: true, diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index cd5d6aa846..4beaf70323 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -351,7 +351,12 @@ class FormulaInstaller message = <<~EOS #{formula.name} #{formula.linked_version} is already installed EOS - if only_deps? + if Homebrew::EnvConfig.no_install_upgrade? && formula.outdated? && !formula.head? + message += <<~EOS + To upgrade to #{formula.pkg_version}, run: + brew upgrade #{formula.full_name} + EOS + elsif only_deps? message = nil else # some other version is already installed *and* linked From 989e3cd2fa36c7e761551eebb1caabea308094f5 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Fri, 11 Jun 2021 13:48:25 -0400 Subject: [PATCH 03/14] Update `HOMEBREW_NO_INSTALL_UPGRADE` description --- Library/Homebrew/env_config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 039560e834..1a0aae3a4d 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -258,7 +258,7 @@ module Homebrew boolean: true, }, HOMEBREW_NO_INSTALL_UPGRADE: { - description: "If set, `brew install` will not automatically upgrade installed and out of date formulae", + description: "If set, `brew install` will not automatically upgrade installed but outdated formulae", boolean: true, }, HOMEBREW_PRY: { From 1ee0c1987eb5b94c117a05fc928193d2c74804e5 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Fri, 11 Jun 2021 13:55:46 -0400 Subject: [PATCH 04/14] Skip unlinking if `HOMEBREW_NO_INSTALL_UPGRADE` --- Library/Homebrew/cmd/install.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index ecce00852b..8e9aa2ee5c 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -396,7 +396,7 @@ module Homebrew f.print_tap_action build_options = f.build - if f.outdated? && !f.head? + if !Homebrew::EnvConfig.no_install_upgrade? && f.outdated? && !f.head? formulae = [f] + f.old_installed_formulae version_upgrade = "#{f.linked_version} -> #{f.pkg_version}" From beb68dca299e6e3885c1134275ff686e7ac16cca Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Fri, 11 Jun 2021 14:24:39 -0400 Subject: [PATCH 05/14] Automatically upgrade outdated keg-only formulae --- Library/Homebrew/cmd/install.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8e9aa2ee5c..ce319819f9 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -215,12 +215,16 @@ module Homebrew # dependencies. Therefore before performing other checks we need to be # sure --force flag is passed. if f.outdated? - optlinked_version = Keg.for(f.opt_prefix).version - onoe <<~EOS - #{f.full_name} #{optlinked_version} is already installed. - To upgrade to #{f.version}, run: - brew upgrade #{f.full_name} - EOS + if Homebrew::EnvConfig.no_install_upgrade? + optlinked_version = Keg.for(f.opt_prefix).version + onoe <<~EOS + #{f.full_name} #{optlinked_version} is already installed. + To upgrade to #{f.version}, run: + brew upgrade #{f.full_name} + EOS + else + installed_formulae << f + end elsif args.only_dependencies? installed_formulae << f elsif !args.quiet? From 1b1fa3fed79daca28ee4e3123f70a6ec81bde0af Mon Sep 17 00:00:00 2001 From: Connor Mann <34930543+cnnrmnn@users.noreply.github.com> Date: Mon, 14 Jun 2021 08:36:23 -0400 Subject: [PATCH 06/14] Update Library/Homebrew/cmd/install.rb Co-authored-by: Mike McQuaid --- Library/Homebrew/cmd/install.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index ce319819f9..6bf3912b7c 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -401,7 +401,7 @@ module Homebrew build_options = f.build if !Homebrew::EnvConfig.no_install_upgrade? && f.outdated? && !f.head? - formulae = [f] + f.old_installed_formulae + formulae = [f, *f.old_installed_formulae] version_upgrade = "#{f.linked_version} -> #{f.pkg_version}" oh1 <<~EOS From 48641f3a3a0423004a7e6f8bae931e752b534f28 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Mon, 14 Jun 2021 11:28:16 -0400 Subject: [PATCH 07/14] Fix method typo --- Library/Homebrew/install.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 8d7ef97e2d..1b28fff4f8 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -258,7 +258,7 @@ module Homebrew Upgrading #{Formatted.identifier(f.name)} #{version_upgrade} EOS outdated_kegs = outdated_formulae.map(&:linked_keg).select(&:directory?).map { |k| Keg.new(k.resolved_path) } - linked_kegs = outdated_kegs.select(&:linked) + linked_kegs = outdated_kegs.select(&:linked?) end fi = FormulaInstaller.new( From 4bbfe351e20e53e3c52cfd3053cfe60b043c857a Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Mon, 14 Jun 2021 11:31:55 -0400 Subject: [PATCH 08/14] Fix keg re-linking logic for failed upgrades --- Library/Homebrew/install.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 1b28fff4f8..d87bcc72d2 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -255,7 +255,7 @@ module Homebrew oh1 <<~EOS #{f.name} #{f.linked_version} is installed and outdated - Upgrading #{Formatted.identifier(f.name)} #{version_upgrade} + Upgrading #{Formatter.identifier(f.name)} #{version_upgrade} EOS outdated_kegs = outdated_formulae.map(&:linked_keg).select(&:directory?).map { |k| Keg.new(k.resolved_path) } linked_kegs = outdated_kegs.select(&:linked?) @@ -295,7 +295,11 @@ module Homebrew ofail e.message ensure # Re-link kegs if upgrade fails - linked_kegs.each(&:link) unless f.latest_version_installed? + begin + linked_kegs.each(&:link) unless f.latest_version_installed? + rescue + nil + end end end end From c1ad3d09b833f496c9dfafce973830c08142afa9 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Mon, 14 Jun 2021 11:42:49 -0400 Subject: [PATCH 09/14] Add `present?` check to `linked_kegs` --- Library/Homebrew/install.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index d87bcc72d2..e285755f42 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -296,7 +296,7 @@ module Homebrew ensure # Re-link kegs if upgrade fails begin - linked_kegs.each(&:link) unless f.latest_version_installed? + linked_kegs.each(&:link) if linked_kegs.present? && !f.latest_version_installed? rescue nil end From f0601e91bc6bbd9abbc5cf76acfd6685aabc5239 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Mon, 14 Jun 2021 11:43:44 -0400 Subject: [PATCH 10/14] Change outdated message --- Library/Homebrew/install.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index e285755f42..21b5716e6c 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -254,7 +254,7 @@ module Homebrew version_upgrade = "#{f.linked_version} -> #{f.pkg_version}" oh1 <<~EOS - #{f.name} #{f.linked_version} is installed and outdated + #{f.name} #{f.linked_version} is installed but outdated Upgrading #{Formatter.identifier(f.name)} #{version_upgrade} EOS outdated_kegs = outdated_formulae.map(&:linked_keg).select(&:directory?).map { |k| Keg.new(k.resolved_path) } From 11d030e897e65af6c9d79b5cbed8789a2d844bc6 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Tue, 15 Jun 2021 09:38:08 -0400 Subject: [PATCH 11/14] Update Library/Homebrew/install.rb Co-authored-by: Mike McQuaid --- Library/Homebrew/install.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 21b5716e6c..50347a3884 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -257,7 +257,9 @@ module Homebrew #{f.name} #{f.linked_version} is installed but outdated Upgrading #{Formatter.identifier(f.name)} #{version_upgrade} EOS - outdated_kegs = outdated_formulae.map(&:linked_keg).select(&:directory?).map { |k| Keg.new(k.resolved_path) } + outdated_kegs = outdated_formulae.map(&:linked_keg) + .select(&:directory?) + .map { |k| Keg.new(k.resolved_path) } linked_kegs = outdated_kegs.select(&:linked?) end From 13e1457249ce68a158eae72300a3de4f7361c148 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Tue, 15 Jun 2021 10:11:40 -0400 Subject: [PATCH 12/14] Consolidate shared install and upgrade logic --- Library/Homebrew/install.rb | 24 +++++++++--------------- Library/Homebrew/upgrade.rb | 35 ++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 50347a3884..48f75516d0 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -5,6 +5,7 @@ require "diagnostic" require "fileutils" require "hardware" require "development_tools" +require "upgrade" module Homebrew # Helper module for performing (pre-)install checks. @@ -249,20 +250,6 @@ module Homebrew f.print_tap_action build_options = f.build - if !Homebrew::EnvConfig.no_install_upgrade? && f.outdated? && !f.head? - outdated_formulae = [f, *f.old_installed_formulae] - version_upgrade = "#{f.linked_version} -> #{f.pkg_version}" - - oh1 <<~EOS - #{f.name} #{f.linked_version} is installed but outdated - Upgrading #{Formatter.identifier(f.name)} #{version_upgrade} - EOS - outdated_kegs = outdated_formulae.map(&:linked_keg) - .select(&:directory?) - .map { |k| Keg.new(k.resolved_path) } - linked_kegs = outdated_kegs.select(&:linked?) - end - fi = FormulaInstaller.new( f, options: build_options.used_options, @@ -282,10 +269,17 @@ module Homebrew quiet: quiet, verbose: verbose, ) + + if !Homebrew::EnvConfig.no_install_upgrade? && f.outdated? && !f.head? + kegs = Upgrade.outdated_kegs(f) + linked_kegs = kegs.select(&:linked?) + Upgrade.print_upgrade_message(f, fi.options) + end + fi.prelude fi.fetch - outdated_kegs.each(&:unlink) if outdated_kegs.present? + kegs.each(&:unlink) if kegs.present? fi.install fi.finish diff --git a/Library/Homebrew/upgrade.rb b/Library/Homebrew/upgrade.rb index 8c0f60b99c..4db35588eb 100644 --- a/Library/Homebrew/upgrade.rb +++ b/Library/Homebrew/upgrade.rb @@ -64,6 +64,24 @@ module Homebrew end end + 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 + oh1 <<~EOS + Upgrading #{Formatter.identifier(formula.full_specified_name)} + #{version_upgrade} #{fi_options.to_a.join(" ")} + EOS + end + def upgrade_formula( formula, flags:, @@ -83,11 +101,8 @@ module Homebrew keg_was_linked = keg.linked? end - formulae_maybe_with_kegs = [formula] + formula.old_installed_formulae - outdated_kegs = formulae_maybe_with_kegs.map(&:linked_keg) - .select(&:directory?) - .map { |k| Keg.new(k.resolved_path) } - linked_kegs = outdated_kegs.select(&:linked?) + kegs = outdated_kegs(formula) + linked_kegs = kegs.select(&:linked?) if formula.opt_prefix.directory? keg = Keg.new(formula.opt_prefix.resolved_path) @@ -118,13 +133,7 @@ module Homebrew }.compact, ) - upgrade_version = if formula.optlinked? - "#{Keg.new(formula.opt_prefix).version} -> #{formula.pkg_version}" - else - "-> #{formula.pkg_version}" - end - oh1 "Upgrading #{Formatter.identifier(formula.full_specified_name)} " \ - "#{upgrade_version} #{fi.options.to_a.join(" ")}" + print_upgrade_message(formula, fi.options) fi.prelude fi.fetch @@ -132,7 +141,7 @@ module Homebrew # 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! - outdated_kegs.each(&:unlink) + kegs.each(&:unlink) fi.install fi.finish From bf9876c10fe11e5e415dab513e2ccfa69b32723c Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Tue, 15 Jun 2021 10:15:44 -0400 Subject: [PATCH 13/14] Update type declarations --- Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi index 944be741a5..d13d69b850 100644 --- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi +++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi @@ -8233,6 +8233,8 @@ module Homebrew::EnvConfig def self.no_install_cleanup?(); end + def self.no_install_upgrade?(); end + def self.no_installed_dependents_check?(); end def self.no_proxy(); end From 79f9a9aac6f3aac6846898d9a9f6f95a75dd1625 Mon Sep 17 00:00:00 2001 From: Connor Mann Date: Tue, 15 Jun 2021 15:59:00 -0400 Subject: [PATCH 14/14] Move `install`-specific code to `install.rb` --- Library/Homebrew/formula_installer.rb | 24 ------------------------ Library/Homebrew/install.rb | 27 +++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index b55e686fc4..027343a079 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -344,30 +344,6 @@ class FormulaInstaller Homebrew::Install.perform_build_from_source_checks end - # not in initialize so upgrade can unlink the active keg before calling this - # function but after instantiating this class so that it can avoid having to - # relink the active keg if possible (because it is slow). - if formula.linked_keg.directory? - message = <<~EOS - #{formula.name} #{formula.linked_version} is already installed - EOS - if Homebrew::EnvConfig.no_install_upgrade? && formula.outdated? && !formula.head? - message += <<~EOS - To upgrade to #{formula.pkg_version}, run: - brew upgrade #{formula.full_name} - EOS - elsif only_deps? - message = nil - else - # some other version is already installed *and* linked - message += <<~EOS - To install #{formula.pkg_version}, first run: - brew unlink #{formula.name} - EOS - end - raise CannotInstallFormulaError, message if message - end - # Warn if a more recent version of this formula is available in the tap. begin if formula.pkg_version < (v = Formulary.factory(formula.full_name, force_bottle: force_bottle?).pkg_version) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 48f75516d0..4db75301ee 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -270,10 +270,29 @@ module Homebrew verbose: verbose, ) - if !Homebrew::EnvConfig.no_install_upgrade? && f.outdated? && !f.head? - kegs = Upgrade.outdated_kegs(f) - linked_kegs = kegs.select(&:linked?) - Upgrade.print_upgrade_message(f, fi.options) + if f.linked_keg.directory? + if Homebrew::EnvConfig.no_install_upgrade? + message = <<~EOS + #{f.name} #{f.linked_version} is already installed + EOS + message += if f.outdated? && !f.head? + <<~EOS + To upgrade to #{f.pkg_version}, run: + brew upgrade #{f.full_name} + EOS + else + <<~EOS + To install #{f.pkg_version}, first run: + brew unlink #{f.name} + EOS + end + raise CannotInstallFormulaError, message unless only_deps + elsif f.outdated? && !f.head? + puts "#{f.name} #{f.linked_version} is installed but outdated" + kegs = Upgrade.outdated_kegs(f) + linked_kegs = kegs.select(&:linked?) + Upgrade.print_upgrade_message(f, fi.options) + end end fi.prelude