Merge pull request #15566 from Bo98/dep-refactor
Refactor some dependency handling to fix various API dependency issues
This commit is contained in:
commit
a5a728a4df
@ -57,7 +57,7 @@ class Build
|
|||||||
build = effective_build_options_for(dependent)
|
build = effective_build_options_for(dependent)
|
||||||
if dep.prune_from_option?(build) ||
|
if dep.prune_from_option?(build) ||
|
||||||
dep.prune_if_build_and_not_dependent?(dependent, formula) ||
|
dep.prune_if_build_and_not_dependent?(dependent, formula) ||
|
||||||
(dep.test? && !dep.build?)
|
(dep.test? && !dep.build?) || dep.implicit?
|
||||||
Dependency.prune
|
Dependency.prune
|
||||||
elsif dep.build?
|
elsif dep.build?
|
||||||
Dependency.keep_but_prune_recursive_deps
|
Dependency.keep_but_prune_recursive_deps
|
||||||
|
|||||||
@ -191,6 +191,7 @@ module Homebrew
|
|||||||
str = "#{str} [test]" if dep.test?
|
str = "#{str} [test]" if dep.test?
|
||||||
str = "#{str} [optional]" if dep.optional?
|
str = "#{str} [optional]" if dep.optional?
|
||||||
str = "#{str} [recommended]" if dep.recommended?
|
str = "#{str} [recommended]" if dep.recommended?
|
||||||
|
str = "#{str} [implicit]" if dep.implicit?
|
||||||
end
|
end
|
||||||
|
|
||||||
str
|
str
|
||||||
|
|||||||
@ -9,7 +9,7 @@ require "options"
|
|||||||
module Dependable
|
module Dependable
|
||||||
# `:run` and `:linked` are no longer used but keep them here to avoid their
|
# `:run` and `:linked` are no longer used but keep them here to avoid their
|
||||||
# misuse in future.
|
# misuse in future.
|
||||||
RESERVED_TAGS = [:build, :optional, :recommended, :run, :test, :linked].freeze
|
RESERVED_TAGS = [:build, :optional, :recommended, :run, :test, :linked, :implicit].freeze
|
||||||
|
|
||||||
attr_reader :tags
|
attr_reader :tags
|
||||||
|
|
||||||
@ -29,6 +29,10 @@ module Dependable
|
|||||||
tags.include? :test
|
tags.include? :test
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def implicit?
|
||||||
|
tags.include? :implicit
|
||||||
|
end
|
||||||
|
|
||||||
def required?
|
def required?
|
||||||
!build? && !test? && !optional? && !recommended?
|
!build? && !test? && !optional? && !recommended?
|
||||||
end
|
end
|
||||||
|
|||||||
@ -33,6 +33,10 @@ class Dependencies < SimpleDelegator
|
|||||||
build + required + recommended
|
build + required + recommended
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dup_without_system_deps
|
||||||
|
self.class.new(*__getobj__.reject { |dep| dep.uses_from_macos? && dep.use_macos_install? })
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{__getobj__}>"
|
"#<#{self.class.name}: #{__getobj__}>"
|
||||||
|
|||||||
@ -56,11 +56,7 @@ module DependenciesHelpers
|
|||||||
|
|
||||||
# If a tap isn't installed, we can't find the dependencies of one of
|
# If a tap isn't installed, we can't find the dependencies of one of
|
||||||
# its formulae, and an exception will be thrown if we try.
|
# its formulae, and an exception will be thrown if we try.
|
||||||
if klass == Dependency &&
|
Dependency.keep_but_prune_recursive_deps if klass == Dependency && dep.tap && !dep.tap.installed?
|
||||||
dep.is_a?(TapDependency) &&
|
|
||||||
!dep.tap.installed?
|
|
||||||
Dependency.keep_but_prune_recursive_deps
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -11,18 +11,20 @@ class Dependency
|
|||||||
include Dependable
|
include Dependable
|
||||||
extend Cachable
|
extend Cachable
|
||||||
|
|
||||||
attr_reader :name, :env_proc, :option_names
|
attr_reader :name, :env_proc, :option_names, :tap
|
||||||
|
|
||||||
DEFAULT_ENV_PROC = proc {}.freeze
|
DEFAULT_ENV_PROC = proc {}.freeze
|
||||||
private_constant :DEFAULT_ENV_PROC
|
private_constant :DEFAULT_ENV_PROC
|
||||||
|
|
||||||
def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name])
|
def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name&.split("/")&.last])
|
||||||
raise ArgumentError, "Dependency must have a name!" unless name
|
raise ArgumentError, "Dependency must have a name!" unless name
|
||||||
|
|
||||||
@name = name
|
@name = name
|
||||||
@tags = tags
|
@tags = tags
|
||||||
@env_proc = env_proc
|
@env_proc = env_proc
|
||||||
@option_names = option_names
|
@option_names = option_names
|
||||||
|
|
||||||
|
@tap = Tap.fetch(Regexp.last_match(1), Regexp.last_match(2)) if name =~ HOMEBREW_TAP_FORMULA_REGEX
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
@ -46,6 +48,8 @@ class Dependency
|
|||||||
|
|
||||||
def installed?
|
def installed?
|
||||||
to_formula.latest_version_installed?
|
to_formula.latest_version_installed?
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def satisfied?(inherited_options = [])
|
def satisfied?(inherited_options = [])
|
||||||
@ -65,6 +69,11 @@ class Dependency
|
|||||||
env_proc&.call
|
env_proc&.call
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { overridable.returns(T::Boolean) }
|
||||||
|
def uses_from_macos?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
|
"#<#{self.class.name}: #{name.inspect} #{tags.inspect}>"
|
||||||
@ -169,7 +178,14 @@ class Dependency
|
|||||||
dep = deps.first
|
dep = deps.first
|
||||||
tags = merge_tags(deps)
|
tags = merge_tags(deps)
|
||||||
option_names = deps.flat_map(&:option_names).uniq
|
option_names = deps.flat_map(&:option_names).uniq
|
||||||
|
kwargs = {}
|
||||||
|
kwargs[:bounds] = dep.bounds if dep.uses_from_macos?
|
||||||
|
# TODO: simpify to just **kwargs when we require Ruby >= 2.7
|
||||||
|
if kwargs.empty?
|
||||||
dep.class.new(name, tags, dep.env_proc, option_names)
|
dep.class.new(name, tags, dep.env_proc, option_names)
|
||||||
|
else
|
||||||
|
dep.class.new(name, tags, dep.env_proc, option_names, **kwargs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -197,26 +213,52 @@ class Dependency
|
|||||||
end
|
end
|
||||||
|
|
||||||
def merge_temporality(deps)
|
def merge_temporality(deps)
|
||||||
# Means both build and runtime dependency.
|
new_tags = []
|
||||||
return [] unless deps.all?(&:build?)
|
new_tags << :build if deps.all?(&:build?)
|
||||||
|
new_tags << :implicit if deps.all?(&:implicit?)
|
||||||
[:build]
|
new_tags
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# A dependency on another Homebrew formula in a specific tap.
|
# A dependency that marked as "installed" on macOS
|
||||||
class TapDependency < Dependency
|
class UsesFromMacOSDependency < Dependency
|
||||||
attr_reader :tap
|
attr_reader :bounds
|
||||||
|
|
||||||
def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name.split("/").last])
|
def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name], bounds:)
|
||||||
@tap = Tap.fetch(name.rpartition("/").first)
|
|
||||||
super(name, tags, env_proc, option_names)
|
super(name, tags, env_proc, option_names)
|
||||||
|
|
||||||
|
@bounds = bounds
|
||||||
end
|
end
|
||||||
|
|
||||||
def installed?
|
def installed?
|
||||||
super
|
use_macos_install? || super
|
||||||
rescue FormulaUnavailableError
|
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
|
false
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@ -84,37 +84,37 @@ class DependencyCollector
|
|||||||
def git_dep_if_needed(tags)
|
def git_dep_if_needed(tags)
|
||||||
return if Utils::Git.available?
|
return if Utils::Git.available?
|
||||||
|
|
||||||
Dependency.new("git", tags)
|
Dependency.new("git", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
def curl_dep_if_needed(tags)
|
def curl_dep_if_needed(tags)
|
||||||
Dependency.new("curl", tags)
|
Dependency.new("curl", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
def subversion_dep_if_needed(tags)
|
def subversion_dep_if_needed(tags)
|
||||||
return if Utils::Svn.available?
|
return if Utils::Svn.available?
|
||||||
|
|
||||||
Dependency.new("subversion", tags)
|
Dependency.new("subversion", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
def cvs_dep_if_needed(tags)
|
def cvs_dep_if_needed(tags)
|
||||||
Dependency.new("cvs", tags) unless which("cvs")
|
Dependency.new("cvs", [*tags, :implicit]) unless which("cvs")
|
||||||
end
|
end
|
||||||
|
|
||||||
def xz_dep_if_needed(tags)
|
def xz_dep_if_needed(tags)
|
||||||
Dependency.new("xz", tags) unless which("xz")
|
Dependency.new("xz", [*tags, :implicit]) unless which("xz")
|
||||||
end
|
end
|
||||||
|
|
||||||
def zstd_dep_if_needed(tags)
|
def zstd_dep_if_needed(tags)
|
||||||
Dependency.new("zstd", tags) unless which("zstd")
|
Dependency.new("zstd", [*tags, :implicit]) unless which("zstd")
|
||||||
end
|
end
|
||||||
|
|
||||||
def unzip_dep_if_needed(tags)
|
def unzip_dep_if_needed(tags)
|
||||||
Dependency.new("unzip", tags) unless which("unzip")
|
Dependency.new("unzip", [*tags, :implicit]) unless which("unzip")
|
||||||
end
|
end
|
||||||
|
|
||||||
def bzip2_dep_if_needed(tags)
|
def bzip2_dep_if_needed(tags)
|
||||||
Dependency.new("bzip2", tags) unless which("bzip2")
|
Dependency.new("bzip2", [*tags, :implicit]) unless which("bzip2")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.tar_needs_xz_dependency?
|
def self.tar_needs_xz_dependency?
|
||||||
@ -127,6 +127,8 @@ class DependencyCollector
|
|||||||
def init_global_dep_tree_if_needed!; end
|
def init_global_dep_tree_if_needed!; end
|
||||||
|
|
||||||
def parse_spec(spec, tags)
|
def parse_spec(spec, tags)
|
||||||
|
raise ArgumentError, "Implicit dependencies cannot be manually specified" if tags.include?(:implicit)
|
||||||
|
|
||||||
case spec
|
case spec
|
||||||
when String
|
when String
|
||||||
parse_string_spec(spec, tags)
|
parse_string_spec(spec, tags)
|
||||||
@ -144,12 +146,8 @@ class DependencyCollector
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse_string_spec(spec, tags)
|
def parse_string_spec(spec, tags)
|
||||||
if spec.match?(HOMEBREW_TAP_FORMULA_REGEX)
|
|
||||||
TapDependency.new(spec, tags)
|
|
||||||
else
|
|
||||||
Dependency.new(spec, tags)
|
Dependency.new(spec, tags)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def parse_symbol_spec(spec, tags)
|
def parse_symbol_spec(spec, tags)
|
||||||
# When modifying this list of supported requirements, consider
|
# When modifying this list of supported requirements, consider
|
||||||
@ -188,11 +186,11 @@ class DependencyCollector
|
|||||||
elsif strategy <= SubversionDownloadStrategy
|
elsif strategy <= SubversionDownloadStrategy
|
||||||
subversion_dep_if_needed(tags)
|
subversion_dep_if_needed(tags)
|
||||||
elsif strategy <= MercurialDownloadStrategy
|
elsif strategy <= MercurialDownloadStrategy
|
||||||
Dependency.new("mercurial", tags)
|
Dependency.new("mercurial", [*tags, :implicit])
|
||||||
elsif strategy <= FossilDownloadStrategy
|
elsif strategy <= FossilDownloadStrategy
|
||||||
Dependency.new("fossil", tags)
|
Dependency.new("fossil", [*tags, :implicit])
|
||||||
elsif strategy <= BazaarDownloadStrategy
|
elsif strategy <= BazaarDownloadStrategy
|
||||||
Dependency.new("breezy", tags)
|
Dependency.new("breezy", [*tags, :implicit])
|
||||||
elsif strategy <= CVSDownloadStrategy
|
elsif strategy <= CVSDownloadStrategy
|
||||||
cvs_dep_if_needed(tags)
|
cvs_dep_if_needed(tags)
|
||||||
elsif strategy < AbstractDownloadStrategy
|
elsif strategy < AbstractDownloadStrategy
|
||||||
@ -208,10 +206,10 @@ class DependencyCollector
|
|||||||
when ".zst" then zstd_dep_if_needed(tags)
|
when ".zst" then zstd_dep_if_needed(tags)
|
||||||
when ".zip" then unzip_dep_if_needed(tags)
|
when ".zip" then unzip_dep_if_needed(tags)
|
||||||
when ".bz2" then bzip2_dep_if_needed(tags)
|
when ".bz2" then bzip2_dep_if_needed(tags)
|
||||||
when ".lha", ".lzh" then Dependency.new("lha", tags)
|
when ".lha", ".lzh" then Dependency.new("lha", [*tags, :implicit])
|
||||||
when ".lz" then Dependency.new("lzip", tags)
|
when ".lz" then Dependency.new("lzip", [*tags, :implicit])
|
||||||
when ".rar" then Dependency.new("libarchive", tags)
|
when ".rar" then Dependency.new("libarchive", [*tags, :implicit])
|
||||||
when ".7z" then Dependency.new("p7zip", tags)
|
when ".7z" then Dependency.new("p7zip", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class DependencyCollector
|
|||||||
return if global_dep_tree[GCC]&.intersect?(related_formula_names)
|
return if global_dep_tree[GCC]&.intersect?(related_formula_names)
|
||||||
return unless formula_for(GCC)
|
return unless formula_for(GCC)
|
||||||
|
|
||||||
Dependency.new(GCC)
|
Dependency.new(GCC, [:implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
||||||
@ -28,7 +28,7 @@ class DependencyCollector
|
|||||||
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names)
|
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names)
|
||||||
return unless formula_for(GLIBC)
|
return unless formula_for(GLIBC)
|
||||||
|
|
||||||
Dependency.new(GLIBC)
|
Dependency.new(GLIBC, [:implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -8,11 +8,11 @@ class DependencyCollector
|
|||||||
def git_dep_if_needed(tags); end
|
def git_dep_if_needed(tags); end
|
||||||
|
|
||||||
def subversion_dep_if_needed(tags)
|
def subversion_dep_if_needed(tags)
|
||||||
Dependency.new("subversion", tags)
|
Dependency.new("subversion", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
def cvs_dep_if_needed(tags)
|
def cvs_dep_if_needed(tags)
|
||||||
Dependency.new("cvs", tags)
|
Dependency.new("cvs", [*tags, :implicit])
|
||||||
end
|
end
|
||||||
|
|
||||||
def xz_dep_if_needed(tags); end
|
def xz_dep_if_needed(tags); end
|
||||||
|
|||||||
@ -210,8 +210,9 @@ class Formula
|
|||||||
@full_name = full_name_with_optional_tap(name)
|
@full_name = full_name_with_optional_tap(name)
|
||||||
@full_alias_name = full_name_with_optional_tap(@alias_name)
|
@full_alias_name = full_name_with_optional_tap(@alias_name)
|
||||||
|
|
||||||
spec_eval :stable
|
self.class.spec_syms.each do |sym|
|
||||||
spec_eval :head
|
spec_eval sym
|
||||||
|
end
|
||||||
|
|
||||||
@active_spec = determine_active_spec(spec)
|
@active_spec = determine_active_spec(spec)
|
||||||
@active_spec_sym = if head?
|
@active_spec_sym = if head?
|
||||||
@ -533,6 +534,9 @@ class Formula
|
|||||||
# The {Dependency}s for the currently active {SoftwareSpec}.
|
# The {Dependency}s for the currently active {SoftwareSpec}.
|
||||||
delegate deps: :active_spec
|
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}.
|
# Dependencies provided by macOS for the currently active {SoftwareSpec}.
|
||||||
delegate uses_from_macos_elements: :active_spec
|
delegate uses_from_macos_elements: :active_spec
|
||||||
|
|
||||||
@ -2111,9 +2115,31 @@ class Formula
|
|||||||
Checksum.new(Digest::SHA256.file(path).hexdigest) if path.exist?
|
Checksum.new(Digest::SHA256.file(path).hexdigest) if path.exist?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_spec_dependables(dependables)
|
||||||
|
# We have a hash of specs names (stable/head) to dependency lists.
|
||||||
|
# Merge all of the dependency lists together, removing any duplicates.
|
||||||
|
all_dependables = [].union(*dependables.values.map(&:to_a))
|
||||||
|
|
||||||
|
all_dependables.map do |dependable|
|
||||||
|
{
|
||||||
|
dependable: dependable,
|
||||||
|
# Now find the list of specs each dependency was a part of.
|
||||||
|
specs: dependables.map { |spec, spec_deps| spec if spec_deps&.include?(dependable) }.compact,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private :merge_spec_dependables
|
||||||
|
|
||||||
# @private
|
# @private
|
||||||
def to_hash
|
def to_hash
|
||||||
dependencies = deps
|
# Create a hash of spec names (stable/head) to the list of dependencies under each
|
||||||
|
dependencies = self.class.spec_syms.to_h do |sym|
|
||||||
|
[sym, send(sym)&.declared_deps]
|
||||||
|
end
|
||||||
|
dependencies.transform_values! { |deps| deps&.reject(&:implicit?) } # Remove all implicit deps from all lists
|
||||||
|
requirements = self.class.spec_syms.to_h do |sym|
|
||||||
|
[sym, send(sym)&.requirements]
|
||||||
|
end
|
||||||
|
|
||||||
hsh = {
|
hsh = {
|
||||||
"name" => name,
|
"name" => name,
|
||||||
@ -2138,25 +2164,13 @@ class Formula
|
|||||||
"keg_only" => keg_only?,
|
"keg_only" => keg_only?,
|
||||||
"keg_only_reason" => keg_only_reason&.to_hash,
|
"keg_only_reason" => keg_only_reason&.to_hash,
|
||||||
"options" => [],
|
"options" => [],
|
||||||
"build_dependencies" => dependencies.select(&:build?)
|
"build_dependencies" => [],
|
||||||
.map(&:name)
|
"dependencies" => [],
|
||||||
.uniq,
|
"test_dependencies" => [],
|
||||||
"dependencies" => dependencies.reject(&:optional?)
|
"recommended_dependencies" => [],
|
||||||
.reject(&:recommended?)
|
"optional_dependencies" => [],
|
||||||
.reject(&:build?)
|
"uses_from_macos" => [],
|
||||||
.reject(&:test?)
|
"uses_from_macos_bounds" => [],
|
||||||
.map(&:name)
|
|
||||||
.uniq,
|
|
||||||
"test_dependencies" => dependencies.select(&:test?)
|
|
||||||
.map(&:name)
|
|
||||||
.uniq,
|
|
||||||
"recommended_dependencies" => dependencies.select(&:recommended?)
|
|
||||||
.map(&:name)
|
|
||||||
.uniq,
|
|
||||||
"optional_dependencies" => dependencies.select(&:optional?)
|
|
||||||
.map(&:name)
|
|
||||||
.uniq,
|
|
||||||
"uses_from_macos" => uses_from_macos_elements.uniq,
|
|
||||||
"requirements" => [],
|
"requirements" => [],
|
||||||
"conflicts_with" => conflicts.map(&:name),
|
"conflicts_with" => conflicts.map(&:name),
|
||||||
"conflicts_with_reasons" => conflicts.map(&:reason),
|
"conflicts_with_reasons" => conflicts.map(&:reason),
|
||||||
@ -2201,7 +2215,56 @@ class Formula
|
|||||||
{ "option" => opt.flag, "description" => opt.description }
|
{ "option" => opt.flag, "description" => opt.description }
|
||||||
end
|
end
|
||||||
|
|
||||||
hsh["requirements"] = requirements.map do |req|
|
dependencies.each do |spec_sym, spec_deps|
|
||||||
|
next if spec_deps.nil?
|
||||||
|
|
||||||
|
dep_hash = if spec_sym == :stable
|
||||||
|
hsh
|
||||||
|
else
|
||||||
|
next if spec_deps == dependencies[:stable]
|
||||||
|
|
||||||
|
hsh["#{spec_sym}_dependencies"] ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
|
dep_hash["build_dependencies"] = spec_deps.select(&:build?)
|
||||||
|
.reject(&:uses_from_macos?)
|
||||||
|
.map(&:name)
|
||||||
|
.uniq
|
||||||
|
dep_hash["dependencies"] = spec_deps.reject(&:optional?)
|
||||||
|
.reject(&:recommended?)
|
||||||
|
.reject(&:build?)
|
||||||
|
.reject(&:test?)
|
||||||
|
.reject(&:uses_from_macos?)
|
||||||
|
.map(&:name)
|
||||||
|
.uniq
|
||||||
|
dep_hash["test_dependencies"] = spec_deps.select(&:test?)
|
||||||
|
.reject(&:uses_from_macos?)
|
||||||
|
.map(&:name)
|
||||||
|
.uniq
|
||||||
|
dep_hash["recommended_dependencies"] = spec_deps.select(&:recommended?)
|
||||||
|
.reject(&:uses_from_macos?)
|
||||||
|
.map(&:name)
|
||||||
|
.uniq
|
||||||
|
dep_hash["optional_dependencies"] = spec_deps.select(&:optional?)
|
||||||
|
.reject(&:uses_from_macos?)
|
||||||
|
.map(&:name)
|
||||||
|
.uniq
|
||||||
|
|
||||||
|
uses_from_macos_deps = spec_deps.select(&:uses_from_macos?).uniq
|
||||||
|
dep_hash["uses_from_macos"] = uses_from_macos_deps.map do |dep|
|
||||||
|
if dep.tags.length >= 2
|
||||||
|
{ dep.name => dep.tags }
|
||||||
|
elsif dep.tags.present?
|
||||||
|
{ dep.name => dep.tags.first }
|
||||||
|
else
|
||||||
|
dep.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dep_hash["uses_from_macos_bounds"] = uses_from_macos_deps.map(&:bounds)
|
||||||
|
end
|
||||||
|
|
||||||
|
hsh["requirements"] = merge_spec_dependables(requirements).map do |data|
|
||||||
|
req = data[:dependable]
|
||||||
req_name = req.name.dup
|
req_name = req.name.dup
|
||||||
req_name.prepend("maximum_") if req.try(:comparator) == "<="
|
req_name.prepend("maximum_") if req.try(:comparator) == "<="
|
||||||
{
|
{
|
||||||
@ -2210,6 +2273,7 @@ class Formula
|
|||||||
"download" => req.download,
|
"download" => req.download,
|
||||||
"version" => req.try(:version) || req.try(:arch),
|
"version" => req.try(:version) || req.try(:arch),
|
||||||
"contexts" => req.tags,
|
"contexts" => req.tags,
|
||||||
|
"specs" => data[:specs],
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2909,10 +2973,17 @@ class Formula
|
|||||||
# <pre>version_scheme 1</pre>
|
# <pre>version_scheme 1</pre>
|
||||||
attr_rw :version_scheme
|
attr_rw :version_scheme
|
||||||
|
|
||||||
|
# @private
|
||||||
|
def spec_syms
|
||||||
|
[:stable, :head].freeze
|
||||||
|
end
|
||||||
|
|
||||||
# A list of the {.stable} and {.head} {SoftwareSpec}s.
|
# A list of the {.stable} and {.head} {SoftwareSpec}s.
|
||||||
# @private
|
# @private
|
||||||
def specs
|
def specs
|
||||||
[stable, head].freeze
|
spec_syms.map do |sym|
|
||||||
|
send(sym)
|
||||||
|
end.freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!attribute [w] url
|
# @!attribute [w] url
|
||||||
|
|||||||
@ -254,7 +254,7 @@ module Homebrew
|
|||||||
@specs.each do |spec|
|
@specs.each do |spec|
|
||||||
# Check for things we don't like to depend on.
|
# Check for things we don't like to depend on.
|
||||||
# We allow non-Homebrew installs whenever possible.
|
# We allow non-Homebrew installs whenever possible.
|
||||||
spec.deps.each do |dep|
|
spec.declared_deps.each do |dep|
|
||||||
begin
|
begin
|
||||||
dep_f = dep.to_formula
|
dep_f = dep.to_formula
|
||||||
rescue TapFormulaUnavailableError
|
rescue TapFormulaUnavailableError
|
||||||
@ -323,7 +323,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
# we want to allow uses_from_macos for aliases but not bare dependencies
|
# 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}'."
|
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -156,6 +156,79 @@ module Formulary
|
|||||||
dep.keys.first
|
dep.keys.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
requirements = {}
|
||||||
|
json_formula["requirements"].map do |req|
|
||||||
|
req_name = req["name"].to_sym
|
||||||
|
next if API_SUPPORTED_REQUIREMENTS.exclude?(req_name)
|
||||||
|
|
||||||
|
req_version = case req_name
|
||||||
|
when :arch
|
||||||
|
req["version"]&.to_sym
|
||||||
|
when :macos, :maximum_macos
|
||||||
|
MacOSVersion::SYMBOLS.key(req["version"])
|
||||||
|
else
|
||||||
|
req["version"]
|
||||||
|
end
|
||||||
|
|
||||||
|
req_tags = []
|
||||||
|
req_tags << req_version if req_version.present?
|
||||||
|
req_tags += req["contexts"].map do |tag|
|
||||||
|
case tag
|
||||||
|
when String
|
||||||
|
tag.to_sym
|
||||||
|
when Hash
|
||||||
|
tag.deep_transform_keys(&:to_sym)
|
||||||
|
else
|
||||||
|
tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
spec_hash = req_tags.empty? ? req_name : { req_name => req_tags }
|
||||||
|
|
||||||
|
specs = req["specs"]
|
||||||
|
specs ||= ["stable", "head"] # backwards compatibility
|
||||||
|
specs.each do |spec|
|
||||||
|
requirements[spec.to_sym] ||= []
|
||||||
|
requirements[spec.to_sym] << spec_hash
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
add_deps = lambda do |spec|
|
||||||
|
T.bind(self, SoftwareSpec)
|
||||||
|
|
||||||
|
dep_json = json_formula.fetch("#{spec}_dependencies", json_formula)
|
||||||
|
|
||||||
|
dep_json["dependencies"].each do |dep|
|
||||||
|
# Backwards compatibility check - uses_from_macos used to be a part of dependencies on Linux
|
||||||
|
next if !json_formula.key?("uses_from_macos_bounds") && uses_from_macos_names.include?(dep) &&
|
||||||
|
!Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
||||||
|
|
||||||
|
depends_on dep
|
||||||
|
end
|
||||||
|
|
||||||
|
[:build, :test, :recommended, :optional].each do |type|
|
||||||
|
dep_json["#{type}_dependencies"].each do |dep|
|
||||||
|
# Backwards compatibility check - uses_from_macos used to be a part of dependencies on Linux
|
||||||
|
next if !json_formula.key?("uses_from_macos_bounds") && uses_from_macos_names.include?(dep) &&
|
||||||
|
!Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
||||||
|
|
||||||
|
depends_on dep => type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dep_json["uses_from_macos"].each_with_index do |dep, index|
|
||||||
|
bounds = dep_json.fetch("uses_from_macos_bounds", [])[index] || {}
|
||||||
|
bounds.deep_transform_keys!(&:to_sym)
|
||||||
|
bounds.deep_transform_values! { |val| val.is_a?(String) ? val.to_sym : val }
|
||||||
|
|
||||||
|
if dep.is_a?(Hash)
|
||||||
|
uses_from_macos dep.deep_transform_values(&:to_sym).merge(bounds)
|
||||||
|
else
|
||||||
|
uses_from_macos dep, bounds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
klass = Class.new(::Formula) do
|
klass = Class.new(::Formula) do
|
||||||
@loaded_from_api = true
|
@loaded_from_api = true
|
||||||
|
|
||||||
@ -171,11 +244,26 @@ module Formulary
|
|||||||
url urls_stable["url"], **url_spec
|
url urls_stable["url"], **url_spec
|
||||||
version json_formula["versions"]["stable"]
|
version json_formula["versions"]["stable"]
|
||||||
sha256 urls_stable["checksum"] if urls_stable["checksum"].present?
|
sha256 urls_stable["checksum"] if urls_stable["checksum"].present?
|
||||||
|
|
||||||
|
instance_exec(:stable, &add_deps)
|
||||||
|
|
||||||
|
requirements[:stable]&.each do |req|
|
||||||
|
depends_on req
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (urls_head = json_formula["urls"]["head"].presence)
|
if (urls_head = json_formula["urls"]["head"].presence)
|
||||||
head urls_head["url"], branch: urls_head["branch"]
|
head do
|
||||||
|
url_spec = { branch: urls_head["branch"] }.compact
|
||||||
|
url urls_head["url"], **url_spec
|
||||||
|
|
||||||
|
instance_exec(:head, &add_deps)
|
||||||
|
|
||||||
|
requirements[:head]&.each do |req|
|
||||||
|
depends_on req
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bottles_stable = json_formula["bottle"]["stable"].presence)
|
if (bottles_stable = json_formula["bottle"]["stable"].presence)
|
||||||
@ -208,54 +296,6 @@ module Formulary
|
|||||||
disable! date: disable_date, because: reason
|
disable! date: disable_date, because: reason
|
||||||
end
|
end
|
||||||
|
|
||||||
json_formula["dependencies"].each do |dep|
|
|
||||||
next if uses_from_macos_names.include?(dep) && !Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
|
||||||
|
|
||||||
depends_on dep
|
|
||||||
end
|
|
||||||
|
|
||||||
[:build, :test, :recommended, :optional].each do |type|
|
|
||||||
json_formula["#{type}_dependencies"].each do |dep|
|
|
||||||
next if uses_from_macos_names.include?(dep) && !Homebrew::SimulateSystem.simulating_or_running_on_macos?
|
|
||||||
|
|
||||||
depends_on dep => type
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
json_formula["uses_from_macos"].each do |dep|
|
|
||||||
dep = dep.deep_transform_values(&:to_sym) if dep.is_a?(Hash)
|
|
||||||
uses_from_macos dep
|
|
||||||
end
|
|
||||||
|
|
||||||
json_formula["requirements"].each do |req|
|
|
||||||
req_name = req["name"].to_sym
|
|
||||||
next if API_SUPPORTED_REQUIREMENTS.exclude?(req_name)
|
|
||||||
|
|
||||||
req_version = case req_name
|
|
||||||
when :arch
|
|
||||||
req["version"]&.to_sym
|
|
||||||
when :macos, :maximum_macos
|
|
||||||
MacOSVersion::SYMBOLS.key(req["version"])
|
|
||||||
else
|
|
||||||
req["version"]
|
|
||||||
end
|
|
||||||
|
|
||||||
req_tags = []
|
|
||||||
req_tags << req_version if req_version.present?
|
|
||||||
req_tags += req["contexts"].map do |tag|
|
|
||||||
case tag
|
|
||||||
when String
|
|
||||||
tag.to_sym
|
|
||||||
when Hash
|
|
||||||
tag.deep_transform_keys(&:to_sym)
|
|
||||||
else
|
|
||||||
tag
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
depends_on req_name => req_tags
|
|
||||||
end
|
|
||||||
|
|
||||||
json_formula["conflicts_with"].each_with_index do |conflict, index|
|
json_formula["conflicts_with"].each_with_index do |conflict, index|
|
||||||
conflicts_with conflict, because: json_formula.dig("conflicts_with_reasons", index)
|
conflicts_with conflict, because: json_formula.dig("conflicts_with_reasons", index)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -11,10 +11,13 @@ module Language
|
|||||||
module_function
|
module_function
|
||||||
|
|
||||||
def detected_perl_shebang(formula = self)
|
def detected_perl_shebang(formula = self)
|
||||||
perl_path = if formula.deps.map(&:name).include? "perl"
|
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"
|
Formula["perl"].opt_bin/"perl"
|
||||||
elsif formula.uses_from_macos_names.include? "perl"
|
else
|
||||||
"/usr/bin/perl#{MacOS.preferred_perl_version}"
|
"/usr/bin/perl#{MacOS.preferred_perl_version}"
|
||||||
|
end
|
||||||
else
|
else
|
||||||
raise ShebangDetectionError.new("Perl", "formula does not depend on Perl")
|
raise ShebangDetectionError.new("Perl", "formula does not depend on Perl")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -24,8 +24,7 @@ class SoftwareSpec
|
|||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
attr_reader :name, :full_name, :owner, :build, :resources, :patches, :options, :deprecated_flags,
|
attr_reader :name, :full_name, :owner, :build, :resources, :patches, :options, :deprecated_flags,
|
||||||
:deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures,
|
:deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures
|
||||||
:uses_from_macos_elements
|
|
||||||
|
|
||||||
def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name,
|
def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name,
|
||||||
:cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
|
:cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
|
||||||
@ -195,28 +194,34 @@ class SoftwareSpec
|
|||||||
deps = [bounds.shift].to_h
|
deps = [bounds.shift].to_h
|
||||||
end
|
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
|
@uses_from_macos_elements << deps
|
||||||
|
|
||||||
# Check whether macOS is new enough for dependency to not be required.
|
depends_on UsesFromMacOSDependency.new(spec, Array(tags), bounds: bounds)
|
||||||
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
|
end
|
||||||
|
|
||||||
depends_on deps
|
# @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
|
end
|
||||||
|
# rubocop:enable Style/TrivialAccessors
|
||||||
|
|
||||||
|
# @deprecated
|
||||||
def uses_from_macos_names
|
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 }
|
uses_from_macos_elements.flat_map { |e| e.is_a?(Hash) ? e.keys : e }
|
||||||
end
|
end
|
||||||
|
|
||||||
def deps
|
def deps
|
||||||
|
dependency_collector.deps.dup_without_system_deps
|
||||||
|
end
|
||||||
|
|
||||||
|
def declared_deps
|
||||||
dependency_collector.deps
|
dependency_collector.deps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -52,13 +52,13 @@ describe DependencyCollector do
|
|||||||
it "creates a resource dependency from a CVS URL" do
|
it "creates a resource dependency from a CVS URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url(":pserver:anonymous:@brew.sh:/cvsroot/foo/bar", using: :cvs)
|
resource.url(":pserver:anonymous:@brew.sh:/cvsroot/foo/bar", using: :cvs)
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("cvs", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("cvs", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.7z' URL" do
|
it "creates a resource dependency from a '.7z' URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("https://brew.sh/foo.7z")
|
resource.url("https://brew.sh/foo.7z")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("p7zip", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("p7zip", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.gz' URL" do
|
it "creates a resource dependency from a '.gz' URL" do
|
||||||
@ -70,25 +70,25 @@ describe DependencyCollector do
|
|||||||
it "creates a resource dependency from a '.lz' URL" do
|
it "creates a resource dependency from a '.lz' URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("https://brew.sh/foo.lz")
|
resource.url("https://brew.sh/foo.lz")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("lzip", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("lzip", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.lha' URL" do
|
it "creates a resource dependency from a '.lha' URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("https://brew.sh/foo.lha")
|
resource.url("https://brew.sh/foo.lha")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("lha", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("lha", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.lzh' URL" do
|
it "creates a resource dependency from a '.lzh' URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("https://brew.sh/foo.lzh")
|
resource.url("https://brew.sh/foo.lzh")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("lha", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("lha", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.rar' URL" do
|
it "creates a resource dependency from a '.rar' URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("https://brew.sh/foo.rar")
|
resource.url("https://brew.sh/foo.rar")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("libarchive", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("libarchive", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises a TypeError for unknown classes" do
|
it "raises a TypeError for unknown classes" do
|
||||||
|
|||||||
@ -100,15 +100,20 @@ describe Dependency do
|
|||||||
expect(foo1).not_to eql(foo3)
|
expect(foo1).not_to eql(foo3)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe TapDependency do
|
describe "#tap" do
|
||||||
subject(:dependency) { described_class.new("foo/bar/dog") }
|
it "returns a tap passed a fully-qualified name" do
|
||||||
|
dependency = described_class.new("foo/bar/dog")
|
||||||
specify "#tap" do
|
|
||||||
expect(dependency.tap).to eq(Tap.new("foo", "bar"))
|
expect(dependency.tap).to eq(Tap.new("foo", "bar"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns no tap passed a simple name" do
|
||||||
|
dependency = described_class.new("dog")
|
||||||
|
expect(dependency.tap).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
specify "#option_names" do
|
specify "#option_names" do
|
||||||
|
dependency = described_class.new("foo/bar/dog")
|
||||||
expect(dependency.option_names).to eq(%w[dog])
|
expect(dependency.option_names).to eq(%w[dog])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|||||||
@ -340,6 +340,7 @@ describe Formulary do
|
|||||||
expect(formula).to be_a(Formula)
|
expect(formula).to be_a(Formula)
|
||||||
|
|
||||||
expect(formula.keg_only_reason.reason).to eq :provided_by_macos
|
expect(formula.keg_only_reason.reason).to eq :provided_by_macos
|
||||||
|
expect(formula.declared_deps.count).to eq 6
|
||||||
if OS.mac?
|
if OS.mac?
|
||||||
expect(formula.deps.count).to eq 5
|
expect(formula.deps.count).to eq 5
|
||||||
else
|
else
|
||||||
@ -398,6 +399,7 @@ describe Formulary do
|
|||||||
|
|
||||||
formula = described_class.factory(formula_name)
|
formula = described_class.factory(formula_name)
|
||||||
expect(formula).to be_a(Formula)
|
expect(formula).to be_a(Formula)
|
||||||
|
expect(formula.declared_deps.count).to eq 7
|
||||||
expect(formula.deps.count).to eq 6
|
expect(formula.deps.count).to eq 6
|
||||||
expect(formula.deps.map(&:name).include?("variations_dep")).to be true
|
expect(formula.deps.map(&:name).include?("variations_dep")).to be true
|
||||||
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be false
|
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)
|
formula = described_class.factory(formula_name)
|
||||||
expect(formula).to be_a(Formula)
|
expect(formula).to be_a(Formula)
|
||||||
|
expect(formula.declared_deps.count).to eq 6
|
||||||
expect(formula.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
|
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be true
|
||||||
end
|
end
|
||||||
@ -419,6 +422,7 @@ describe Formulary do
|
|||||||
|
|
||||||
formula = described_class.factory(formula_name)
|
formula = described_class.factory(formula_name)
|
||||||
expect(formula).to be_a(Formula)
|
expect(formula).to be_a(Formula)
|
||||||
|
expect(formula.declared_deps.count).to eq 6
|
||||||
expect(formula.deps.count).to eq 5
|
expect(formula.deps.count).to eq 5
|
||||||
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be true
|
expect(formula.deps.map(&:name).include?("uses_from_macos_dep")).to be true
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,19 +14,19 @@ describe DependencyCollector do
|
|||||||
it "creates a resource dependency from a '.xz' URL" do
|
it "creates a resource dependency from a '.xz' URL" do
|
||||||
resource.url("https://brew.sh/foo.xz")
|
resource.url("https://brew.sh/foo.xz")
|
||||||
allow_any_instance_of(Object).to receive(:which).with("xz")
|
allow_any_instance_of(Object).to receive(:which).with("xz")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("xz", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("xz", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.zip' URL" do
|
it "creates a resource dependency from a '.zip' URL" do
|
||||||
resource.url("https://brew.sh/foo.zip")
|
resource.url("https://brew.sh/foo.zip")
|
||||||
allow_any_instance_of(Object).to receive(:which).with("unzip")
|
allow_any_instance_of(Object).to receive(:which).with("unzip")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("unzip", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("unzip", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a resource dependency from a '.bz2' URL" do
|
it "creates a resource dependency from a '.bz2' URL" do
|
||||||
resource.url("https://brew.sh/foo.tar.bz2")
|
resource.url("https://brew.sh/foo.tar.bz2")
|
||||||
allow_any_instance_of(Object).to receive(:which).with("bzip2")
|
allow_any_instance_of(Object).to receive(:which).with("bzip2")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("bzip2", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("bzip2", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,6 @@ describe DependencyCollector do
|
|||||||
specify "Resource dependency from a Subversion URL" do
|
specify "Resource dependency from a Subversion URL" do
|
||||||
resource = Resource.new
|
resource = Resource.new
|
||||||
resource.url("svn://brew.sh/foo/bar")
|
resource.url("svn://brew.sh/foo/bar")
|
||||||
expect(collector.add(resource)).to eq(Dependency.new("subversion", [:build, :test]))
|
expect(collector.add(resource)).to eq(Dependency.new("subversion", [:build, :test, :implicit]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -19,19 +19,27 @@ describe Formula do
|
|||||||
|
|
||||||
expect(f.class.stable.deps).to be_empty
|
expect(f.class.stable.deps).to be_empty
|
||||||
expect(f.class.head.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.stable.uses_from_macos_elements.first).to eq("foo")
|
||||||
expect(f.class.head.uses_from_macos_elements.first).to eq("foo")
|
expect(f.class.head.uses_from_macos_elements.first).to eq("foo")
|
||||||
end
|
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
|
f = formula "foo" do
|
||||||
url "foo-1.0"
|
url "foo-1.0"
|
||||||
|
|
||||||
uses_from_macos("foo", since: :high_sierra)
|
uses_from_macos("foo", since: :high_sierra)
|
||||||
end
|
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.stable.deps.first.name).to eq("foo")
|
||||||
expect(f.class.head.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.stable.uses_from_macos_elements).to eq(["foo"])
|
||||||
expect(f.class.head.uses_from_macos_elements).to eq(["foo"])
|
expect(f.class.head.uses_from_macos_elements).to eq(["foo"])
|
||||||
end
|
end
|
||||||
|
|||||||
@ -139,37 +139,59 @@ describe SoftwareSpec do
|
|||||||
it "allows specifying dependencies" do
|
it "allows specifying dependencies" do
|
||||||
spec.uses_from_macos("foo")
|
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.name).to eq("foo")
|
||||||
|
expect(spec.deps.first).to be_uses_from_macos
|
||||||
|
expect(spec.deps.first).not_to be_use_macos_install
|
||||||
end
|
end
|
||||||
|
|
||||||
it "works with tags" do
|
it "works with tags" do
|
||||||
spec.uses_from_macos("foo" => :build)
|
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.name).to eq("foo")
|
||||||
expect(spec.deps.first.tags).to include(:build)
|
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
|
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"
|
ENV["HOMEBREW_SIMULATE_MACOS_ON_LINUX"] = "1"
|
||||||
spec.uses_from_macos("foo")
|
spec.uses_from_macos("foo")
|
||||||
|
|
||||||
expect(spec.deps).to be_empty
|
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
|
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"
|
ENV["HOMEBREW_SIMULATE_MACOS_ON_LINUX"] = "1"
|
||||||
spec.uses_from_macos("foo" => :build)
|
spec.uses_from_macos("foo" => :build)
|
||||||
|
|
||||||
expect(spec.deps).to be_empty
|
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
|
end
|
||||||
|
|
||||||
it "ignores OS version specifications" do
|
it "ignores OS version specifications" do
|
||||||
spec.uses_from_macos("foo", since: :mojave)
|
spec.uses_from_macos("foo", since: :mojave)
|
||||||
spec.uses_from_macos("bar" => :build, :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.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.name).to eq("bar")
|
||||||
expect(spec.deps.last.tags).to include(:build)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -183,30 +205,54 @@ describe SoftwareSpec do
|
|||||||
spec.uses_from_macos("foo", since: :el_capitan)
|
spec.uses_from_macos("foo", since: :el_capitan)
|
||||||
|
|
||||||
expect(spec.deps).to be_empty
|
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")
|
expect(spec.uses_from_macos_elements.first).to eq("foo")
|
||||||
end
|
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)
|
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.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"])
|
expect(spec.uses_from_macos_elements).to eq(["foo"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "works with tags" do
|
it "works with tags" do
|
||||||
spec.uses_from_macos("foo" => :build, :since => :high_sierra)
|
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
|
dep = spec.deps.first
|
||||||
|
|
||||||
expect(dep.name).to eq("foo")
|
expect(dep.name).to eq("foo")
|
||||||
expect(dep.tags).to include(:build)
|
expect(dep.tags).to include(:build)
|
||||||
|
expect(dep.first).to be_uses_from_macos
|
||||||
|
expect(dep.first).not_to be_use_macos_install
|
||||||
end
|
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("foo")
|
||||||
spec.uses_from_macos("bar" => :build)
|
spec.uses_from_macos("bar" => :build)
|
||||||
|
|
||||||
expect(spec.deps).to be_empty
|
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
|
end
|
||||||
|
|
||||||
it "raises an error if passing invalid OS versions" do
|
it "raises an error if passing invalid OS versions" do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user