From a96e28640072168ed23f64a7bb1ed0343a3a2684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Fri, 10 Sep 2021 06:06:02 -0700 Subject: [PATCH 1/3] install: check if formula is already linked before fetching --- Library/Homebrew/install.rb | 51 +++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 52e630ab00..798bd99047 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -209,6 +209,25 @@ module Homebrew Or to force-install it, run: brew install #{f} --force EOS + elsif f.linked? + message = "#{f.name} #{f.linked_version} is already installed" + if f.outdated? && !head + return true unless Homebrew::EnvConfig.no_install_upgrade? + + onoe <<~EOS + #{message} + To upgrade to #{f.pkg_version}, run: + brew upgrade #{f.full_name} + EOS + elsif only_dependencies + return true + else + onoe <<~EOS + #{message} + To install #{f.pkg_version}, first run: + brew unlink #{f.name} + EOS + end else # If none of the above is true and the formula is linked, then # FormulaInstaller will handle this case. @@ -281,41 +300,23 @@ module Homebrew end.compact formula_installers.each do |fi| - install_formula(fi, only_deps: only_deps) + install_formula(fi) Cleanup.install_formula_clean!(fi.formula) end end - def install_formula(formula_installer, only_deps: false) + def install_formula(formula_installer) f = formula_installer.formula formula_installer.prelude f.print_tap_action - 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, formula_installer.options) - end + if f.linked? && f.outdated? && !f.head? && !Homebrew::EnvConfig.no_install_upgrade? + puts "#{f.full_name} #{f.linked_version} is installed but outdated" + kegs = Upgrade.outdated_kegs(f) + linked_kegs = kegs.select(&:linked?) + Upgrade.print_upgrade_message(f, formula_installer.options) end kegs.each(&:unlink) if kegs.present? From 0c3afa583716e55fe7e5ebcc31fd6f9e1b3f581d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Fri, 10 Sep 2021 06:01:37 -0700 Subject: [PATCH 2/3] install, upgrade: run formula installer prelude before fetching --- Library/Homebrew/formula_installer.rb | 6 +++++- Library/Homebrew/install.rb | 7 ++++--- Library/Homebrew/upgrade.rb | 11 +++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 04375fcbe7..7a7fc8b8ef 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -218,8 +218,12 @@ class FormulaInstaller raise end - def check_install_sanity + def check_installation_already_attempted raise FormulaInstallationAlreadyAttemptedError, formula if self.class.attempted.include?(formula) + end + + def check_install_sanity + check_installation_already_attempted if force_bottle? && !pour_bottle? raise CannotInstallFormulaError, "--force-bottle passed but #{formula.full_name} has no bottle!" diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 798bd99047..191ad6f0b5 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -291,8 +291,11 @@ module Homebrew ) begin + fi.prelude fi.fetch fi + rescue CannotInstallFormulaError => e + ofail e.message rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e ofail "#{f}: #{e}" nil @@ -308,7 +311,7 @@ module Homebrew def install_formula(formula_installer) f = formula_installer.formula - formula_installer.prelude + formula_installer.check_installation_already_attempted f.print_tap_action @@ -327,8 +330,6 @@ module Homebrew # We already attempted to install f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. nil - rescue CannotInstallFormulaError => e - ofail e.message ensure # Re-link kegs if upgrade fails begin diff --git a/Library/Homebrew/upgrade.rb b/Library/Homebrew/upgrade.rb index b90bdfb6dc..e203045090 100644 --- a/Library/Homebrew/upgrade.rb +++ b/Library/Homebrew/upgrade.rb @@ -58,8 +58,13 @@ module Homebrew quiet: quiet, verbose: verbose, ) - fi.fetch unless dry_run + unless dry_run + fi.prelude + fi.fetch + end fi + rescue CannotInstallFormulaError => e + ofail e rescue UnsatisfiedRequirements, DownloadError => e ofail "#{formula}: #{e}" nil @@ -167,7 +172,7 @@ module Homebrew return end - formula_installer.prelude + formula_installer.check_installation_already_attempted print_upgrade_message(formula, formula_installer.options) @@ -182,8 +187,6 @@ module Homebrew # We already attempted to upgrade f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. nil - rescue CannotInstallFormulaError => e - ofail e rescue BuildError => e e.dump(verbose: verbose) puts From 15e8852128bfe0da12c02d105fabccbed3758b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Fri, 10 Sep 2021 08:31:53 -0700 Subject: [PATCH 3/3] upgrade: add install_formula helper method --- Library/Homebrew/install.rb | 28 ++++++---------------------- Library/Homebrew/upgrade.rb | 30 +++++++++++++++++++----------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 191ad6f0b5..5c563b4e46 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -212,7 +212,10 @@ module Homebrew elsif f.linked? message = "#{f.name} #{f.linked_version} is already installed" if f.outdated? && !head - return true unless Homebrew::EnvConfig.no_install_upgrade? + unless Homebrew::EnvConfig.no_install_upgrade? + puts "#{message} but outdated" + return true + end onoe <<~EOS #{message} @@ -315,28 +318,9 @@ module Homebrew f.print_tap_action - if f.linked? && f.outdated? && !f.head? && !Homebrew::EnvConfig.no_install_upgrade? - puts "#{f.full_name} #{f.linked_version} is installed but outdated" - kegs = Upgrade.outdated_kegs(f) - linked_kegs = kegs.select(&:linked?) - Upgrade.print_upgrade_message(f, formula_installer.options) - end + upgrade = f.linked? && f.outdated? && !f.head? && !Homebrew::EnvConfig.no_install_upgrade? - kegs.each(&:unlink) if kegs.present? - - formula_installer.install - formula_installer.finish - rescue FormulaInstallationAlreadyAttemptedError - # We already attempted to install f as part of the dependency tree of - # another formula. In that case, don't generate an error, just move on. - nil - ensure - # Re-link kegs if upgrade fails - begin - linked_kegs.each(&:link) if linked_kegs.present? && !f.latest_version_installed? - rescue - nil - end + Upgrade.install_formula(formula_installer, upgrade: upgrade) end private_class_method :install_formula end diff --git a/Library/Homebrew/upgrade.rb b/Library/Homebrew/upgrade.rb index e203045090..dd9071f170 100644 --- a/Library/Homebrew/upgrade.rb +++ b/Library/Homebrew/upgrade.rb @@ -164,9 +164,6 @@ module Homebrew def upgrade_formula(formula_installer, dry_run: false, verbose: false) formula = formula_installer.formula - kegs = outdated_kegs(formula) - linked_kegs = kegs.select(&:linked?) - if dry_run print_dry_run_dependencies(formula, formula_installer.compute_dependencies) return @@ -174,12 +171,28 @@ module Homebrew formula_installer.check_installation_already_attempted - print_upgrade_message(formula, formula_installer.options) + install_formula(formula_installer, upgrade: true) + rescue BuildError => e + e.dump(verbose: verbose) + puts + Homebrew.failed = true + end + private_class_method :upgrade_formula + + def install_formula(formula_installer, upgrade:) + formula = formula_installer.formula + + if upgrade + print_upgrade_message(formula, formula_installer.options) + + kegs = outdated_kegs(formula) + linked_kegs = kegs.select(&:linked?) + end # 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! - kegs.each(&:unlink) + kegs.each(&:unlink) if kegs.present? formula_installer.install formula_installer.finish @@ -187,19 +200,14 @@ module Homebrew # We already attempted to upgrade f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. nil - rescue BuildError => e - e.dump(verbose: verbose) - puts - Homebrew.failed = true ensure # restore previous installation state if build failed begin - linked_kegs.each(&:link) unless formula.latest_version_installed? + linked_kegs.each(&:link) if linked_kegs.present? && !f.latest_version_installed? rescue nil end end - private_class_method :upgrade_formula def check_broken_dependents(installed_formulae) CacheStoreDatabase.use(:linkage) do |db|