class Build::Dependency::Chain
Attributes
dependencies[R]
@attr [Array<Depends>] The list of dependencies that needs to be satisfied.
providers[R]
@attr [Array] The available providers which will be used to satisfy he required dependencies.
selection[R]
@attr [Set<String>] Explicitly selected dependencies which will be used when resolving ambiguity.
Public Class Methods
expand(*args)
click to toggle source
An `UnresolvedDependencyError` will be thrown if there are any unresolved dependencies.
# File lib/build/dependency/chain.rb, line 29 def self.expand(*args) chain = self.new(*args) chain.freeze if chain.unresolved.size > 0 raise UnresolvedDependencyError.new(chain) end return chain end
new(dependencies, providers, selection = [])
click to toggle source
Calls superclass method
# File lib/build/dependency/chain.rb, line 41 def initialize(dependencies, providers, selection = []) super() @selection = ::Set.new(selection) @dependencies = dependencies.collect{|dependency| Depends[dependency]} @providers = providers expand_top end
Public Instance Methods
freeze()
click to toggle source
Calls superclass method
# File lib/build/dependency/chain.rb, line 60 def freeze return unless frozen? @selection.freeze @dependencies.freeze @providers.freeze super end
partial(provider)
click to toggle source
# File lib/build/dependency/partial_chain.rb, line 26 def partial(provider) PartialChain.expand(self, provider.dependencies) end
Protected Instance Methods
expand_dependency(dependency, parent)
click to toggle source
Resolve a dependency into one or more provisions.
# File lib/build/dependency/chain.rb, line 103 def expand_dependency(dependency, parent) # The job of this function is to take a dependency and turn it into 0 or more provisions. The dependency could be a normal fully-qualified name or a wildcard. It's not clear at which point pattern matching should affect dependency resolution, but it seems logical since it depends on the available provisions that it's done here. # Another benefit is that it introduces a fixed point of reference for expanding dependencies. When the resolver invokes this method, it can be assured that it will return the same result. if dependency.wildcard? return expand_wildcard(dependency, parent) end # Mostly, only one package will satisfy the dependency... viable_providers = @providers.select{|provider| provider.provides? dependency} # puts "** Found #{viable_providers.collect(&:name).join(', ')} viable providers." if viable_providers.size == 1 provider = viable_providers.first provision = provision_for(provider, dependency) # The best outcome, a specific provider was named: return [provision] elsif viable_providers.size > 1 # ... however in some cases (typically where aliases are being used) an explicit selection must be made for the build to work correctly. explicit_providers = filter_by_selection(viable_providers) # puts "** Filtering to #{explicit_providers.collect(&:name).join(', ')} explicit providers." if explicit_providers.size != 1 # If we were unable to select a single package, we may use the priority to limit the number of possible options: explicit_providers = viable_providers if explicit_providers.empty? explicit_providers = filter_by_priority(explicit_providers) end if explicit_providers.size == 0 # No provider was explicitly specified, thus we require explicit conflict resolution: @conflicts[dependency] = viable_providers elsif explicit_providers.size == 1 provider = explicit_providers.first provision = provision_for(provider, dependency) # The best outcome, a specific provider was named: return [provision] else # Multiple providers were explicitly mentioned that satisfy the dependency. @conflicts[dependency] = explicit_providers end end return [] end
expand_top()
click to toggle source
# File lib/build/dependency/chain.rb, line 72 def expand_top # puts "Expanding #{@dependencies.inspect}" expand_nested(@dependencies, TOP) end
expand_wildcard(dependency, parent)
click to toggle source
Given a dependency with wildcards, figure out all names that might match, and then expand them all individually.
# File lib/build/dependency/chain.rb, line 94 def expand_wildcard(dependency, parent) @providers.flat_map do |provider| provider.filter(dependency).flat_map do |name, provision| expand_dependency(Depends[name], parent) end end end
filter_by_priority(viable_providers)
click to toggle source
# File lib/build/dependency/chain.rb, line 78 def filter_by_priority(viable_providers) # Sort from highest priority to lowest priority: viable_providers = viable_providers.sort{|a,b| b.priority <=> a.priority} # The first item has the highest priority: highest_priority = viable_providers.first.priority # We compute all providers with the same highest priority (may be zero): return viable_providers.take_while{|provider| provider.priority == highest_priority} end
filter_by_selection(viable_providers)
click to toggle source
# File lib/build/dependency/chain.rb, line 89 def filter_by_selection(viable_providers) return viable_providers.select{|provider| @selection.include? provider.name} end
provision_for(provider, dependency)
click to toggle source
# File lib/build/dependency/chain.rb, line 152 def provision_for(provider, dependency) provider.provision_for(dependency) end