
Expand requirements recursively while applying the same optional? and recommended? filters that dependencies are run through. Options generated by requirements are now checked against the correct list of requirements, eliminating the temporary "best guess" logic in the installer.
160 lines
3.8 KiB
Ruby
160 lines
3.8 KiB
Ruby
require 'dependable'
|
|
require 'build_environment'
|
|
|
|
# A base class for non-formula requirements needed by formulae.
|
|
# A "fatal" requirement is one that will fail the build if it is not present.
|
|
# By default, Requirements are non-fatal.
|
|
class Requirement
|
|
include Dependable
|
|
extend BuildEnvironmentDSL
|
|
|
|
attr_reader :tags, :name
|
|
|
|
def initialize(*tags)
|
|
@tags = tags.flatten.compact
|
|
@tags << :build if self.class.build
|
|
end
|
|
|
|
# The message to show when the requirement is not met.
|
|
def message; "" end
|
|
|
|
# Overriding #satisfied? is deprepcated.
|
|
# Pass a block or boolean to the satisfied DSL method instead.
|
|
def satisfied?
|
|
result = self.class.satisfy.yielder do |proc|
|
|
instance_eval(&proc)
|
|
end
|
|
|
|
infer_env_modification(result)
|
|
!!result
|
|
end
|
|
|
|
# Overriding #fatal? is deprecated.
|
|
# Pass a boolean to the fatal DSL method instead.
|
|
def fatal?
|
|
self.class.fatal || false
|
|
end
|
|
|
|
# Overriding #modify_build_environment is deprecated.
|
|
# Pass a block to the the env DSL method instead.
|
|
def modify_build_environment
|
|
satisfied? and env.modify_build_environment(self)
|
|
end
|
|
|
|
def env
|
|
@env ||= self.class.env
|
|
end
|
|
|
|
def eql?(other)
|
|
instance_of?(other.class) && hash == other.hash
|
|
end
|
|
|
|
def hash
|
|
[name, *tags].hash
|
|
end
|
|
|
|
private
|
|
|
|
def infer_env_modification(o)
|
|
case o
|
|
when Pathname
|
|
self.class.env do
|
|
unless ENV["PATH"].split(":").include?(o.parent.to_s)
|
|
append("PATH", o.parent, ":")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
class << self
|
|
def fatal(val=nil)
|
|
val.nil? ? @fatal : @fatal = val
|
|
end
|
|
|
|
def build(val=nil)
|
|
val.nil? ? @build : @build = val
|
|
end
|
|
|
|
def satisfy(options={}, &block)
|
|
@satisfied ||= Requirement::Satisfier.new(options, &block)
|
|
end
|
|
end
|
|
|
|
class Satisfier
|
|
def initialize(options={}, &block)
|
|
case options
|
|
when Hash
|
|
@options = { :build_env => true }
|
|
@options.merge!(options)
|
|
else
|
|
@satisfied = options
|
|
end
|
|
@proc = block
|
|
end
|
|
|
|
def yielder
|
|
if instance_variable_defined?(:@satisfied)
|
|
@satisfied
|
|
elsif @options[:build_env]
|
|
require 'superenv'
|
|
ENV.with_build_environment do
|
|
ENV.userpaths!
|
|
yield @proc
|
|
end
|
|
else
|
|
yield @proc
|
|
end
|
|
end
|
|
end
|
|
|
|
# Expand the requirements of dependent recursively, optionally yielding
|
|
# [dependent, req] pairs to allow callers to apply arbitrary filters to
|
|
# the list.
|
|
# The default filter, which is applied when a block is not given, omits
|
|
# optionals and recommendeds based on what the dependent has asked for.
|
|
def self.expand(dependent, &block)
|
|
reqs = ComparableSet.new
|
|
|
|
formulae = dependent.recursive_dependencies.map(&:to_formula)
|
|
formulae.unshift(dependent)
|
|
|
|
formulae.map(&:requirements).each do |requirements|
|
|
requirements.each do |req|
|
|
prune = catch(:prune) do
|
|
if block_given?
|
|
yield dependent, req
|
|
elsif req.optional? || req.recommended?
|
|
Requirement.prune unless dependent.build.with?(req.name)
|
|
end
|
|
end
|
|
|
|
next if prune
|
|
|
|
reqs << req
|
|
end
|
|
end
|
|
|
|
# We special case handling of X11Dependency and its subclasses to
|
|
# ensure the correct dependencies are present in the final list.
|
|
# If an X11Dependency is present after filtering, we eliminate
|
|
# all X11Dependency::Proxy objects from the list. If there aren't
|
|
# any X11Dependency objects, then we eliminate all but one of the
|
|
# proxy objects.
|
|
proxy = unless reqs.any? { |r| r.instance_of?(X11Dependency) }
|
|
reqs.find { |r| r.kind_of?(X11Dependency::Proxy) }
|
|
end
|
|
|
|
reqs.reject! do |r|
|
|
r.kind_of?(X11Dependency::Proxy)
|
|
end
|
|
|
|
reqs << proxy unless proxy.nil?
|
|
reqs
|
|
end
|
|
|
|
# Used to prune requirements when calling expand with a block.
|
|
def self.prune
|
|
throw(:prune, true)
|
|
end
|
|
end
|