mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Introduce UsesFromMacOSDependency
Add Formula#declared_deps and SoftwareSpec#declared_deps
This commit is contained in:
parent
53d513695a
commit
d1b923f314
@ -33,6 +33,10 @@ class Dependencies < SimpleDelegator
|
||||
build + required + recommended
|
||||
end
|
||||
|
||||
def dup_without_system_deps
|
||||
self.class.new(*__getobj__.reject { |dep| dep.uses_from_macos? && dep.use_macos_install? })
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def inspect
|
||||
"#<#{self.class.name}: #{__getobj__}>"
|
||||
|
@ -69,6 +69,11 @@ class Dependency
|
||||
env_proc&.call
|
||||
end
|
||||
|
||||
sig { overridable.returns(T::Boolean) }
|
||||
def uses_from_macos?
|
||||
false
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def inspect
|
||||
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
|
||||
@ -173,7 +178,9 @@ class Dependency
|
||||
dep = deps.first
|
||||
tags = merge_tags(deps)
|
||||
option_names = deps.flat_map(&:option_names).uniq
|
||||
dep.class.new(name, tags, dep.env_proc, option_names)
|
||||
kwargs = {}
|
||||
kwargs[:bounds] = dep.bounds if dep.uses_from_macos?
|
||||
dep.class.new(name, tags, dep.env_proc, option_names, **kwargs)
|
||||
end
|
||||
end
|
||||
|
||||
@ -208,3 +215,45 @@ class Dependency
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# A dependency that marked as "installed" on macOS
|
||||
class UsesFromMacOSDependency < Dependency
|
||||
attr_reader :bounds
|
||||
|
||||
def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name], bounds:)
|
||||
super(name, tags, env_proc, option_names)
|
||||
|
||||
@bounds = bounds
|
||||
end
|
||||
|
||||
def installed?
|
||||
use_macos_install? || super
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def use_macos_install?
|
||||
# Check whether macOS is new enough for dependency to not be required.
|
||||
if Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
||||
# Assume the oldest macOS version when simulating a generic macOS version
|
||||
return true if Homebrew::SimulateSystem.current_os == :macos && !bounds.key?(:since)
|
||||
|
||||
if Homebrew::SimulateSystem.current_os != :macos
|
||||
current_os = MacOSVersion.from_symbol(Homebrew::SimulateSystem.current_os)
|
||||
since_os = MacOSVersion.from_symbol(bounds[:since]) if bounds.key?(:since)
|
||||
return true if current_os >= since_os
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
sig { override.returns(T::Boolean) }
|
||||
def uses_from_macos?
|
||||
true
|
||||
end
|
||||
|
||||
sig { override.params(formula: Formula).returns(T.self_type) }
|
||||
def dup_with_formula_name(formula)
|
||||
self.class.new(formula.full_name.to_s, tags, env_proc, option_names, bounds: bounds)
|
||||
end
|
||||
end
|
||||
|
@ -533,6 +533,9 @@ class Formula
|
||||
# The {Dependency}s for the currently active {SoftwareSpec}.
|
||||
delegate deps: :active_spec
|
||||
|
||||
# The declared {Dependency}s for the currently active {SoftwareSpec} (i.e. including those provided by macOS)
|
||||
delegate declared_deps: :active_spec
|
||||
|
||||
# Dependencies provided by macOS for the currently active {SoftwareSpec}.
|
||||
delegate uses_from_macos_elements: :active_spec
|
||||
|
||||
|
@ -254,7 +254,7 @@ module Homebrew
|
||||
@specs.each do |spec|
|
||||
# Check for things we don't like to depend on.
|
||||
# We allow non-Homebrew installs whenever possible.
|
||||
spec.deps.each do |dep|
|
||||
spec.declared_deps.each do |dep|
|
||||
begin
|
||||
dep_f = dep.to_formula
|
||||
rescue TapFormulaUnavailableError
|
||||
@ -323,7 +323,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
# we want to allow uses_from_macos for aliases but not bare dependencies
|
||||
if self.class.aliases.include?(dep.name) && spec.uses_from_macos_names.exclude?(dep.name)
|
||||
if self.class.aliases.include?(dep.name) && !dep.uses_from_macos?
|
||||
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
|
||||
end
|
||||
|
||||
|
@ -11,10 +11,13 @@ module Language
|
||||
module_function
|
||||
|
||||
def detected_perl_shebang(formula = self)
|
||||
perl_path = if formula.deps.map(&:name).include? "perl"
|
||||
Formula["perl"].opt_bin/"perl"
|
||||
elsif formula.uses_from_macos_names.include? "perl"
|
||||
"/usr/bin/perl#{MacOS.preferred_perl_version}"
|
||||
perl_deps = formula.declared_deps.select { |dep| dep.name == "perl" }
|
||||
perl_path = if perl_deps.present?
|
||||
if perl_deps.any? { |dep| !dep.uses_from_macos? || !dep.use_macos_install? }
|
||||
Formula["perl"].opt_bin/"perl"
|
||||
else
|
||||
"/usr/bin/perl#{MacOS.preferred_perl_version}"
|
||||
end
|
||||
else
|
||||
raise ShebangDetectionError.new("Perl", "formula does not depend on Perl")
|
||||
end
|
||||
|
@ -24,8 +24,7 @@ class SoftwareSpec
|
||||
}.freeze
|
||||
|
||||
attr_reader :name, :full_name, :owner, :build, :resources, :patches, :options, :deprecated_flags,
|
||||
:deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures,
|
||||
:uses_from_macos_elements
|
||||
:deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures
|
||||
|
||||
def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name,
|
||||
:cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
|
||||
@ -195,28 +194,34 @@ class SoftwareSpec
|
||||
deps = [bounds.shift].to_h
|
||||
end
|
||||
|
||||
spec, tags = deps.is_a?(Hash) ? deps.first : deps
|
||||
raise TypeError, "Dependency name must be a string!" unless spec.is_a?(String)
|
||||
|
||||
@uses_from_macos_elements << deps
|
||||
|
||||
# Check whether macOS is new enough for dependency to not be required.
|
||||
if Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
||||
# Assume the oldest macOS version when simulating a generic macOS version
|
||||
return if Homebrew::SimulateSystem.current_os == :macos && !bounds.key?(:since)
|
||||
|
||||
if Homebrew::SimulateSystem.current_os != :macos
|
||||
current_os = MacOSVersion.from_symbol(Homebrew::SimulateSystem.current_os)
|
||||
since_os = MacOSVersion.from_symbol(bounds[:since]) if bounds.key?(:since)
|
||||
return if current_os >= since_os
|
||||
end
|
||||
end
|
||||
|
||||
depends_on deps
|
||||
depends_on UsesFromMacOSDependency.new(spec, Array(tags), bounds: bounds)
|
||||
end
|
||||
|
||||
# @deprecated
|
||||
# rubocop:disable Style/TrivialAccessors
|
||||
def uses_from_macos_elements
|
||||
# TODO: remove all @uses_from_macos_elements when disabling or removing this method
|
||||
# odeprecated "#uses_from_macos_elements", "#declared_deps"
|
||||
@uses_from_macos_elements
|
||||
end
|
||||
# rubocop:enable Style/TrivialAccessors
|
||||
|
||||
# @deprecated
|
||||
def uses_from_macos_names
|
||||
# odeprecated "#uses_from_macos_names", "#declared_deps"
|
||||
uses_from_macos_elements.flat_map { |e| e.is_a?(Hash) ? e.keys : e }
|
||||
end
|
||||
|
||||
def deps
|
||||
dependency_collector.deps.dup_without_system_deps
|
||||
end
|
||||
|
||||
def declared_deps
|
||||
dependency_collector.deps
|
||||
end
|
||||
|
||||
|
@ -340,6 +340,7 @@ describe Formulary do
|
||||
expect(formula).to be_a(Formula)
|
||||
|
||||
expect(formula.keg_only_reason.reason).to eq :provided_by_macos
|
||||
expect(formula.declared_deps.count).to eq 6
|
||||
if OS.mac?
|
||||
expect(formula.deps.count).to eq 5
|
||||
else
|
||||
@ -398,6 +399,7 @@ describe Formulary do
|
||||
|
||||
formula = described_class.factory(formula_name)
|
||||
expect(formula).to be_a(Formula)
|
||||
expect(formula.declared_deps.count).to eq 7
|
||||
expect(formula.deps.count).to eq 6
|
||||
expect(formula.deps.map(&:name).include?("variations_dep")).to be true
|
||||
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be false
|
||||
@ -409,6 +411,7 @@ describe Formulary do
|
||||
|
||||
formula = described_class.factory(formula_name)
|
||||
expect(formula).to be_a(Formula)
|
||||
expect(formula.declared_deps.count).to eq 6
|
||||
expect(formula.deps.count).to eq 6
|
||||
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be true
|
||||
end
|
||||
@ -419,6 +422,7 @@ describe Formulary do
|
||||
|
||||
formula = described_class.factory(formula_name)
|
||||
expect(formula).to be_a(Formula)
|
||||
expect(formula.declared_deps.count).to eq 6
|
||||
expect(formula.deps.count).to eq 5
|
||||
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be true
|
||||
end
|
||||
|
@ -19,19 +19,27 @@ describe Formula do
|
||||
|
||||
expect(f.class.stable.deps).to be_empty
|
||||
expect(f.class.head.deps).to be_empty
|
||||
expect(f.class.stable.declared_deps).not_to be_empty
|
||||
expect(f.class.head.declared_deps).not_to be_empty
|
||||
expect(f.class.stable.declared_deps.first.name).to eq("foo")
|
||||
expect(f.class.head.declared_deps.first.name).to eq("foo")
|
||||
expect(f.class.stable.uses_from_macos_elements.first).to eq("foo")
|
||||
expect(f.class.head.uses_from_macos_elements.first).to eq("foo")
|
||||
end
|
||||
|
||||
it "doesn't add a macOS dependency to any spec if the OS version doesn't meet requirements" do
|
||||
it "adds a dependency to any spec if the OS version doesn't meet requirements" do
|
||||
f = formula "foo" do
|
||||
url "foo-1.0"
|
||||
|
||||
uses_from_macos("foo", since: :high_sierra)
|
||||
end
|
||||
|
||||
expect(f.class.stable.deps).not_to be_empty
|
||||
expect(f.class.head.deps).not_to be_empty
|
||||
expect(f.class.stable.deps.first.name).to eq("foo")
|
||||
expect(f.class.head.deps.first.name).to eq("foo")
|
||||
expect(f.class.stable.declared_deps).not_to be_empty
|
||||
expect(f.class.head.declared_deps).not_to be_empty
|
||||
expect(f.class.stable.uses_from_macos_elements).to eq(["foo"])
|
||||
expect(f.class.head.uses_from_macos_elements).to eq(["foo"])
|
||||
end
|
||||
|
@ -139,37 +139,59 @@ describe SoftwareSpec do
|
||||
it "allows specifying dependencies" do
|
||||
spec.uses_from_macos("foo")
|
||||
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
expect(spec.deps).not_to be_empty
|
||||
expect(spec.deps.first.name).to eq("foo")
|
||||
expect(spec.deps.first).to be_uses_from_macos
|
||||
expect(spec.deps.first).not_to be_use_macos_install
|
||||
end
|
||||
|
||||
it "works with tags" do
|
||||
spec.uses_from_macos("foo" => :build)
|
||||
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
expect(spec.deps).not_to be_empty
|
||||
expect(spec.deps.first.name).to eq("foo")
|
||||
expect(spec.deps.first.tags).to include(:build)
|
||||
expect(spec.deps.first).to be_uses_from_macos
|
||||
expect(spec.deps.first).not_to be_use_macos_install
|
||||
end
|
||||
|
||||
it "ignores dependencies with HOMEBREW_SIMULATE_MACOS_ON_LINUX" do
|
||||
it "handles dependencies with HOMEBREW_SIMULATE_MACOS_ON_LINUX" do
|
||||
ENV["HOMEBREW_SIMULATE_MACOS_ON_LINUX"] = "1"
|
||||
spec.uses_from_macos("foo")
|
||||
|
||||
expect(spec.deps).to be_empty
|
||||
expect(spec.declared_deps.first.name).to eq("foo")
|
||||
expect(spec.declared_deps.first.tags).to be_empty
|
||||
expect(spec.declared_deps.first).to be_uses_from_macos
|
||||
expect(spec.declared_deps.first).to be_use_macos_install
|
||||
end
|
||||
|
||||
it "ignores dependencies with tags with HOMEBREW_SIMULATE_MACOS_ON_LINUX" do
|
||||
it "handles dependencies with tags with HOMEBREW_SIMULATE_MACOS_ON_LINUX" do
|
||||
ENV["HOMEBREW_SIMULATE_MACOS_ON_LINUX"] = "1"
|
||||
spec.uses_from_macos("foo" => :build)
|
||||
|
||||
expect(spec.deps).to be_empty
|
||||
expect(spec.declared_deps.first.name).to eq("foo")
|
||||
expect(spec.declared_deps.first.tags).to include(:build)
|
||||
expect(spec.declared_deps.first).to be_uses_from_macos
|
||||
expect(spec.declared_deps.first).to be_use_macos_install
|
||||
end
|
||||
|
||||
it "ignores OS version specifications" do
|
||||
spec.uses_from_macos("foo", since: :mojave)
|
||||
spec.uses_from_macos("bar" => :build, :since => :mojave)
|
||||
|
||||
expect(spec.deps.count).to eq 2
|
||||
expect(spec.deps.first.name).to eq("foo")
|
||||
expect(spec.deps.first).to be_uses_from_macos
|
||||
expect(spec.deps.first).not_to be_use_macos_install
|
||||
expect(spec.deps.last.name).to eq("bar")
|
||||
expect(spec.deps.last.tags).to include(:build)
|
||||
expect(spec.deps.last).to be_uses_from_macos
|
||||
expect(spec.deps.last).not_to be_use_macos_install
|
||||
expect(spec.declared_deps.count).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
@ -183,30 +205,54 @@ describe SoftwareSpec do
|
||||
spec.uses_from_macos("foo", since: :el_capitan)
|
||||
|
||||
expect(spec.deps).to be_empty
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
expect(spec.declared_deps.first).to be_uses_from_macos
|
||||
expect(spec.declared_deps.first).to be_use_macos_install
|
||||
expect(spec.uses_from_macos_elements.first).to eq("foo")
|
||||
end
|
||||
|
||||
it "doesn't add a macOS dependency if the OS version doesn't meet requirements" do
|
||||
it "add a macOS dependency if the OS version doesn't meet requirements" do
|
||||
spec.uses_from_macos("foo", since: :high_sierra)
|
||||
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
expect(spec.deps).not_to be_empty
|
||||
expect(spec.deps.first.name).to eq("foo")
|
||||
expect(spec.deps.first).to be_uses_from_macos
|
||||
expect(spec.deps.first).not_to be_use_macos_install
|
||||
expect(spec.uses_from_macos_elements).to eq(["foo"])
|
||||
end
|
||||
|
||||
it "works with tags" do
|
||||
spec.uses_from_macos("foo" => :build, :since => :high_sierra)
|
||||
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
expect(spec.deps).not_to be_empty
|
||||
|
||||
dep = spec.deps.first
|
||||
|
||||
expect(dep.name).to eq("foo")
|
||||
expect(dep.tags).to include(:build)
|
||||
expect(dep.first).to be_uses_from_macos
|
||||
expect(dep.first).not_to be_use_macos_install
|
||||
end
|
||||
|
||||
it "doesn't add a dependency if no OS version is specified" do
|
||||
it "doesn't add an effective dependency if no OS version is specified" do
|
||||
spec.uses_from_macos("foo")
|
||||
spec.uses_from_macos("bar" => :build)
|
||||
|
||||
expect(spec.deps).to be_empty
|
||||
expect(spec.declared_deps).not_to be_empty
|
||||
|
||||
dep = spec.declared_deps.first
|
||||
expect(dep.name).to eq("foo")
|
||||
expect(dep.first).to be_uses_from_macos
|
||||
expect(dep.first).to be_use_macos_install
|
||||
|
||||
dep = spec.declared_deps.last
|
||||
expect(dep.name).to eq("bar")
|
||||
expect(dep.tags).to include(:build)
|
||||
expect(dep.first).to be_uses_from_macos
|
||||
expect(dep.first).to be_use_macos_install
|
||||
end
|
||||
|
||||
it "raises an error if passing invalid OS versions" do
|
||||
|
Loading…
x
Reference in New Issue
Block a user