Merge pull request #11525 from cnnrmnn/install-upgrade-outdated

Automatically upgrade installed but out of date formulae with `brew install`
This commit is contained in:
Mike McQuaid 2021-06-16 11:18:22 +01:00 committed by GitHub
commit 01cd65d09b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 37 deletions

View File

@ -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 but outdated formulae",
boolean: true,
},
HOMEBREW_PRY: {
description: "If set, use Pry for the `brew irb` command.",
boolean: true,

View File

@ -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 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)

View File

@ -5,6 +5,7 @@ require "diagnostic"
require "fileutils"
require "hardware"
require "development_tools"
require "upgrade"
module Homebrew
# Helper module for performing (pre-)install checks.
@ -124,6 +125,8 @@ module Homebrew
# dependencies. Therefore before performing other checks we need to be
# sure --force flag is passed.
if f.outdated?
return true unless Homebrew::EnvConfig.no_install_upgrade?
optlinked_version = Keg.for(f.opt_prefix).version
onoe <<~EOS
#{f.full_name} #{optlinked_version} is already installed.
@ -266,8 +269,37 @@ module Homebrew
quiet: quiet,
verbose: verbose,
)
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
fi.fetch
kegs.each(&:unlink) if kegs.present?
fi.install
fi.finish
rescue FormulaInstallationAlreadyAttemptedError
@ -276,6 +308,13 @@ module Homebrew
nil
rescue CannotInstallFormulaError => e
ofail e.message
ensure
# Re-link kegs if upgrade fails
begin
linked_kegs.each(&:link) if linked_kegs.present? && !f.latest_version_installed?
rescue
nil
end
end
end
end

View File

@ -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

View File

@ -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