Skip to content

Commit

Permalink
Make formula upgrades more liberal based on bottle
Browse files Browse the repository at this point in the history
When we're installing a formula from a bottle, we currently always
upgrade all dependencies in the dependency tree to be safe.

However, if we're installing a bottle and the `runtime_dependencies`
within that bottle's tab all have older or equal versions to those
already installed: we do not need to upgrade these dependencies.

This should help a lot of upgrading a lot of the time, at least for
users using bottles (which is the huge majority).

The only downside or other noticeable change is that this requires us
to download or attempt to download the bottle tab before we compute
the dependencies at installation time.

Co-authored-by: Kevin <[email protected]>
  • Loading branch information
MikeMcQuaid and apainintheneck committed Sep 3, 2023
1 parent fc72dfc commit 9fcdaa2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 10 deletions.
25 changes: 17 additions & 8 deletions Library/Homebrew/dependency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,23 @@ def to_formula
formula
end

def installed?
to_formula.latest_version_installed?
rescue FormulaUnavailableError
false
def installed?(minimum_version: nil)
formula = begin
to_formula
rescue FormulaUnavailableError
nil
end
return false unless formula

if minimum_version.present?
formula.any_version_installed? && (formula.any_installed_version.version >= minimum_version)
else
formula.latest_version_installed?
end
end

def satisfied?(inherited_options = [])
installed? && missing_options(inherited_options).empty?
def satisfied?(inherited_options = [], minimum_version: nil)
installed?(minimum_version: minimum_version) && missing_options(inherited_options).empty?
end

def missing_options(inherited_options)
Expand Down Expand Up @@ -239,8 +248,8 @@ def hash
[name, tags, bounds].hash
end

def installed?
use_macos_install? || super
def installed?(minimum_version: nil)
use_macos_install? || super(minimum_version: minimum_version)
end

sig { returns(T::Boolean) }
Expand Down
25 changes: 23 additions & 2 deletions Library/Homebrew/formula_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def initialize(
@requirement_messages = []
@poured_bottle = false
@start_time = nil
@bottle_tab_runtime_dependencies = {}

# Take the original formula instance, which might have been swapped from an API instance to a source instance
@formula = previously_fetched_formula if previously_fetched_formula
Expand Down Expand Up @@ -218,6 +219,7 @@ def prelude
end

Tab.clear_cache

verify_deps_exist unless ignore_deps?
forbidden_license_check

Expand Down Expand Up @@ -518,6 +520,9 @@ def check_conflicts
def compute_dependencies(use_cache: true)
@compute_dependencies = nil unless use_cache
@compute_dependencies ||= begin
# Needs to be done before expand_dependencies
fetch_bottle_tab if pour_bottle?

check_requirements(expand_requirements)
expand_dependencies
end
Expand Down Expand Up @@ -610,9 +615,11 @@ def expand_dependencies_for_formula(formula, inherited_options)
keep_build_test ||= dep.build? && !install_bottle_for?(dependent, build) &&
(formula.head? || !dependent.latest_version_installed?)

bottle_runtime_version = @bottle_tab_runtime_dependencies.dig(dep.name, "version")

if dep.prune_from_option?(build) || ((dep.build? || dep.test?) && !keep_build_test)
Dependency.prune
elsif dep.satisfied?(inherited_options[dep.name])
elsif dep.satisfied?(inherited_options[dep.name], minimum_version: bottle_runtime_version)
Dependency.skip
end
end
Expand Down Expand Up @@ -1197,6 +1204,20 @@ def previously_fetched_formula
end
end

sig { void }
def fetch_bottle_tab
@fetch_bottle_tab ||= begin
formula.fetch_bottle_tab
@bottle_tab_runtime_dependencies = formula.bottle_tab_attributes
.fetch("runtime_dependencies", [])
.index_by { |dep| dep["full_name"] }
.freeze
true
rescue DownloadError
@fetch_bottle_tab = true
end
end

sig { void }
def fetch
return if previously_fetched_formula
Expand All @@ -1208,7 +1229,7 @@ def fetch
oh1 "Fetching #{Formatter.identifier(formula.full_name)}".strip

if pour_bottle?(output_warning: true)
formula.fetch_bottle_tab
fetch_bottle_tab
else
@formula = Homebrew::API::Formula.source_download(formula) if formula.loaded_from_api?

Expand Down

0 comments on commit 9fcdaa2

Please sign in to comment.