Merge pull request #16152 from Bo98/runtime-dep-revision

Store and use revision in tab runtime dependencies
This commit is contained in:
Mike McQuaid 2023-11-10 19:31:23 +00:00 committed by GitHub
commit 5e47d3a4c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 18 deletions

View File

@ -46,7 +46,8 @@ class Dependency
formula formula
end end
def installed?(minimum_version: nil) sig { params(minimum_version: T.nilable(Version), minimum_revision: T.nilable(Integer)).returns(T::Boolean) }
def installed?(minimum_version: nil, minimum_revision: nil)
formula = begin formula = begin
to_formula to_formula
rescue FormulaUnavailableError rescue FormulaUnavailableError
@ -55,14 +56,29 @@ class Dependency
return false unless formula return false unless formula
if minimum_version.present? if minimum_version.present?
formula.any_version_installed? && (formula.any_installed_version.version >= minimum_version) installed_version = formula.any_installed_version
return false unless installed_version
# Tabs prior to 4.1.18 did not have revision or pkg_version fields.
# As a result, we have to be more conversative when we do not have
# a minimum revision from the tab and assume that if the formula has a
# the same version and a non-zero revision that it needs upgraded.
if minimum_revision.present?
minimum_pkg_version = PkgVersion.new(minimum_version, minimum_revision)
installed_version >= minimum_pkg_version
elsif installed_version.version == minimum_version
formula.revision.zero?
else
installed_version.version > minimum_version
end
else else
formula.latest_version_installed? formula.latest_version_installed?
end end
end end
def satisfied?(inherited_options = [], minimum_version: nil) def satisfied?(inherited_options = [], minimum_version: nil, minimum_revision: nil)
installed?(minimum_version: minimum_version) && missing_options(inherited_options).empty? installed?(minimum_version: minimum_version, minimum_revision: minimum_revision) &&
missing_options(inherited_options).empty?
end end
def missing_options(inherited_options) def missing_options(inherited_options)
@ -248,8 +264,9 @@ class UsesFromMacOSDependency < Dependency
[name, tags, bounds].hash [name, tags, bounds].hash
end end
def installed?(minimum_version: nil) sig { params(minimum_version: T.nilable(Version), minimum_revision: T.nilable(Integer)).returns(T::Boolean) }
use_macos_install? || super(minimum_version: minimum_version) def installed?(minimum_version: nil, minimum_revision: nil)
use_macos_install? || super(minimum_version: minimum_version, minimum_revision: minimum_revision)
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }

View File

@ -616,11 +616,14 @@ on_request: installed_on_request?, options: options)
keep_build_test ||= dep.build? && !install_bottle_for?(dependent, build) && keep_build_test ||= dep.build? && !install_bottle_for?(dependent, build) &&
(formula.head? || !dependent.latest_version_installed?) (formula.head? || !dependent.latest_version_installed?)
bottle_runtime_version = @bottle_tab_runtime_dependencies.dig(dep.name, "version") bottle_runtime_version = @bottle_tab_runtime_dependencies.dig(dep.name, "version").presence
bottle_runtime_version = Version.new(bottle_runtime_version) if bottle_runtime_version
bottle_runtime_revision = @bottle_tab_runtime_dependencies.dig(dep.name, "revision")
if dep.prune_from_option?(build) || ((dep.build? || dep.test?) && !keep_build_test) if dep.prune_from_option?(build) || ((dep.build? || dep.test?) && !keep_build_test)
Dependency.prune Dependency.prune
elsif dep.satisfied?(inherited_options[dep.name], minimum_version: bottle_runtime_version) elsif dep.satisfied?(inherited_options[dep.name], minimum_version: bottle_runtime_version,
minimum_revision: bottle_runtime_revision)
Dependency.skip Dependency.skip
end end
end end

View File

@ -226,6 +226,8 @@ class Tab
{ {
"full_name" => f.full_name, "full_name" => f.full_name,
"version" => f.version.to_s, "version" => f.version.to_s,
"revision" => f.revision,
"pkg_version" => f.pkg_version.to_s,
"declared_directly" => formula.deps.include?(dep), "declared_directly" => formula.deps.include?(dep),
} }
end end

View File

@ -141,7 +141,8 @@ describe Tab do
tab.homebrew_version = "1.1.6" tab.homebrew_version = "1.1.6"
tab.runtime_dependencies = runtime_deps_hash tab.runtime_dependencies = runtime_deps_hash
expect(tab.runtime_dependencies).to eql( expect(tab.runtime_dependencies).to eql(
[{ "full_name" => "foo", "version" => "1.0", "declared_directly" => false }], [{ "full_name" => "foo", "version" => "1.0", "revision" => 0, "pkg_version" => "1.0",
"declared_directly" => false }],
) )
end end
@ -255,6 +256,7 @@ describe Tab do
tap = Tap.new("user", "repo") tap = Tap.new("user", "repo")
from_tap = formula("from_tap", path: tap.path/"Formula/from_tap.rb") do from_tap = formula("from_tap", path: tap.path/"Formula/from_tap.rb") do
url "from_tap-1.0" url "from_tap-1.0"
revision 1
end end
stub_formula_loader from_tap stub_formula_loader from_tap
@ -266,8 +268,10 @@ describe Tab do
tab = described_class.create(f, compiler, stdlib) tab = described_class.create(f, compiler, stdlib)
runtime_dependencies = [ runtime_dependencies = [
{ "full_name" => "bar", "version" => "2.0", "declared_directly" => true }, { "full_name" => "bar", "version" => "2.0", "revision" => 0, "pkg_version" => "2.0",
{ "full_name" => "user/repo/from_tap", "version" => "1.0", "declared_directly" => true }, "declared_directly" => true },
{ "full_name" => "user/repo/from_tap", "version" => "1.0", "revision" => 1, "pkg_version" => "1.0_1",
"declared_directly" => true },
] ]
expect(tab.runtime_dependencies).to eq(runtime_dependencies) expect(tab.runtime_dependencies).to eq(runtime_dependencies)

View File

@ -72,17 +72,34 @@ module Homebrew
unless dry_run unless dry_run
fi.prelude fi.prelude
# Don't need to install this bottle if all the runtime dependencies # Don't need to install this bottle if all of the runtime
# are already satisfied. # dependencies have the same or newer version already installed.
next if dependents && fi.bottle_tab_runtime_dependencies.presence&.none? do |dependency, hash| next if dependents && fi.bottle_tab_runtime_dependencies.presence&.all? do |dependency, hash|
installed_version = begin dependency_formula = begin
Formula[dependency].any_installed_version Formula[dependency]
rescue FormulaUnavailableError rescue FormulaUnavailableError
nil nil
end end
next true unless installed_version next false if dependency_formula.nil?
Version.new(hash["version"]) > installed_version.version installed_version = dependency_formula.any_installed_version
next false unless installed_version
next false if hash["version"].blank?
# Tabs prior to 4.1.18 did not have revision or pkg_version fields.
# As a result, we have to be more conversative when we do not have
# a revision in the tab and assume that if the formula has a
# the same version and a non-zero revision that it needs upgraded.
tab_version = Version.new(hash["version"])
if hash["revision"].present?
tab_pkg_version = PkgVersion.new(tab_version, hash["revision"])
installed_version >= tab_pkg_version
elsif installed_version.version == tab_version
dependency_formula.revision.zero?
else
installed_version.version > tab_version
end
end end
fi.fetch fi.fetch