Class: Gem::Resolver
| Relationships & Source Files | |
| Namespace Children | |
| Classes: APISet,APISpecification,ActivationRequest,BestSet,ComposedSet,Conflict,CurrentSet,DependencyRequest,GitSet,GitSpecification,IndexSet,IndexSpecification,InstalledSpecification,InstallerSet,LocalSpecification,LockSet,LockSpecification,RequirementList,Set,SourceSet,SpecSpecification,Specification,Stats,VendorSet,VendorSpecification | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Instance Chain: | |
| Inherits: | Object | 
| Defined in: | lib/rubygems/resolver.rb | 
Overview
Given a set of Dependency objects as needed and a way to query the set of available specs via set, calculates a set of ActivationRequest objects which indicate all the specs that should be activated to meet the all the requirements.
Constant Summary
- 
    DEBUG_RESOLVER =
    # File 'lib/rubygems/resolver.rb', line 21If the DEBUG_RESOLVERenvironment variable is set then debugging mode is enabled for the resolver. This will display information about the state of the resolver while a set of dependencies is being resolved.!ENV["DEBUG_RESOLVER"].nil? 
- 
    SINGLE_POSSIBILITY_CONSTRAINT_PENALTY =
    private
    
 # File 'lib/rubygems/resolver.rb', line 2881_000_000
Class Method Summary
- 
    
      .compose_sets(*sets)  
    
    Combines setsinto aComposedSetthat allows specification lookup in a uniform manner.
- 
    
      .for_current_gems(needed)  
    
    Creates a Resolverthat queries only against the already installed gems for theneededdependencies.
- 
    
      .new(needed, set = nil)  ⇒ Resolver 
    
    constructor
    Create Resolver object which will resolve the tree starting with neededDependencyobjects.
Instance Attribute Summary
- #debug? ⇒ Boolean readonly
- 
    
      #development  
    
    rw
    Setto true if all development dependencies should be considered.
- 
    
      #development_shallow  
    
    rw
    Setto true if immediate development dependencies should be considered.
- 
    
      #ignore_dependencies  
    
    rw
    When true, no dependencies are looked up for requested gems. 
- 
    
      #skip_gems  
    
    rw
    Hash of gems to skip resolution. 
- #soft_missing rw
- 
    
      #stats  
    
    readonly
    Listof dependencies that could not be found in the configured sources.
Molinillo::UI - Included
| #debug? | Whether or not debug messages should be printed. | 
Instance Method Summary
- #allow_missing?(dependency) ⇒ Boolean
- #dependencies_for(specification)
- #name_for(dependency)
- #output
- #requirement_satisfied_by?(requirement, activated, spec) ⇒ Boolean
- 
    
      #resolve  
    
    Proceed with resolution! Returns an array of ActivationRequestobjects.
- #search_for(dependency)
- #sort_dependencies(dependencies, activated, conflicts)
- 
    
      #amount_constrained(dependency)  
    
    private
    returns an integer in (-infty, 0] a number closer to 0 means the dependency is less constraining. 
- 
    
      #activation_request(dep, possible)  
    
    Internal use only
    Creates an ActivationRequestfor the givendepand the lastpossiblespecification.
- #explain(stage, *data) Internal use only
- #explain_list(stage) Internal use only
- 
    
      #find_possible(dependency)  
    
    Internal use only
    Extracts the specifications that may be able to fulfill dependencyand returns those that match the local platform and all those that match.
- #requests(s, act, reqs = []) Internal use only
- 
    
      #select_local_platforms(specs)  
    
    Internal use only
    Returns the gems in specsthat match the local platform.
Molinillo::SpecificationProvider - Included
| #allow_missing? | Returns whether this dependency, which has no possible matching specifications, can safely be ignored. | 
| #dependencies_equal? | Determines whether two arrays of dependencies are equal, and thus can be grouped. | 
| #dependencies_for | Returns the dependencies of  | 
| #name_for | Returns the name for the given  | 
| #name_for_explicit_dependency_source, #name_for_locking_dependency_source, | |
| #requirement_satisfied_by? | Determines whether the given  | 
| #search_for | Search for the specifications that match the given dependency. | 
| #sort_dependencies | Sort dependencies so that the ones that are easiest to resolve are first. | 
Molinillo::UI - Included
| #after_resolution | Called after resolution ends (either successfully or with an error). | 
| #before_resolution | Called before resolution begins. | 
| #debug | Conveys debug information to the user. | 
| #indicate_progress | Called roughly every  | 
| #output | The  | 
| #progress_rate | How often progress should be conveyed to the user via  | 
Constructor Details
    .new(needed, set = nil)  ⇒ Resolver 
  
Create Resolver object which will resolve the tree starting with needed Dependency objects.
set is an object that provides where to look for specifications to satisfy the Dependencies. This defaults to Resolver::IndexSet, which will query rubygems.org.
Class Method Details
.compose_sets(*sets)
Combines sets into a Resolver::ComposedSet that allows specification lookup in a uniform manner.  If one of the sets is itself a Resolver::ComposedSet its sets are flattened into the result Resolver::ComposedSet.
# File 'lib/rubygems/resolver.rb', line 59
def self.compose_sets(*sets) sets.compact! sets = sets.map do |set| case set when Gem::Resolver::BestSet then set when Gem::Resolver::ComposedSet then set.sets else set end end.flatten case sets.length when 0 then raise ArgumentError, "one set in the composition must be non-nil" when 1 then sets.first else Gem::Resolver::ComposedSet.new(*sets) end end
.for_current_gems(needed)
Creates a Resolver that queries only against the already installed gems for the needed dependencies.
# File 'lib/rubygems/resolver.rb', line 87
def self.for_current_gems(needed) new needed, Gem::Resolver::CurrentSet.new end
Instance Attribute Details
    #debug?  ⇒ Boolean  (readonly)
  
  [ GitHub ]
# File 'lib/rubygems/resolver.rb', line 176
def debug? DEBUG_RESOLVER end
#development (rw)
Resolver::Set to true if all development dependencies should be considered.
# File 'lib/rubygems/resolver.rb', line 26
attr_accessor :development
#development_shallow (rw)
Resolver::Set to true if immediate development dependencies should be considered.
# File 'lib/rubygems/resolver.rb', line 31
attr_accessor :development_shallow
#ignore_dependencies (rw)
When true, no dependencies are looked up for requested gems.
# File 'lib/rubygems/resolver.rb', line 36
attr_accessor :ignore_dependencies
#skip_gems (rw)
Hash of gems to skip resolution. Keyed by gem name, with arrays of gem specifications as values.
# File 'lib/rubygems/resolver.rb', line 47
attr_accessor :skip_gems
#soft_missing (rw)
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 52
attr_accessor :soft_missing
#stats (readonly)
List of dependencies that could not be found in the configured sources.
# File 'lib/rubygems/resolver.rb', line 41
attr_reader :stats
Instance Method Details
#activation_request(dep, possible)
Creates an Resolver::ActivationRequest for the given dep and the last possible specification.
Returns the Resolver::Specification and the Resolver::ActivationRequest
# File 'lib/rubygems/resolver.rb', line 135
def activation_request(dep, possible) # :nodoc: spec = possible.pop explain :activate, [spec.full_name, possible.size] explain :possible, possible activation_request = Gem::Resolver::ActivationRequest.new spec, dep, possible [spec, activation_request] end
    #allow_missing?(dependency)  ⇒ Boolean 
  
# File 'lib/rubygems/resolver.rb', line 271
def allow_missing?(dependency) @soft_missing end
#amount_constrained(dependency) (private)
returns an integer in (-infty, 0] a number closer to 0 means the dependency is less constraining
dependencies w/ 0 or 1 possibilities (ignoring version requirements) are given very negative values, so they always sort first, before dependencies that are unconstrained
# File 'lib/rubygems/resolver.rb', line 297
def amount_constrained(dependency) @amount_constrained ||= {} @amount_constrained[dependency.name] ||= begin name_dependency = Gem::Dependency.new(dependency.name) dependency_request_for_name = Gem::Resolver::DependencyRequest.new(name_dependency, dependency.requester) all = @set.find_all(dependency_request_for_name).size if all <= 1 all - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY else search = search_for(dependency).size search - all end end end
#dependencies_for(specification)
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 252
def dependencies_for(specification) return [] if @ignore_dependencies spec = specification.spec requests(spec, specification) end
#explain(stage, *data)
# File 'lib/rubygems/resolver.rb', line 111
def explain(stage, *data) # :nodoc: return unless DEBUG_RESOLVER d = data.map(&:pretty_inspect).join(", ") $stderr.printf "%10s %s\n", stage.to_s.upcase, d end
#explain_list(stage)
# File 'lib/rubygems/resolver.rb', line 118
def explain_list(stage) # :nodoc: return unless DEBUG_RESOLVER data = yield $stderr.printf "%10s (%d entries)\n", stage.to_s.upcase, data.size unless data.empty? require "pp" PP.pp data, $stderr end end
#find_possible(dependency)
Extracts the specifications that may be able to fulfill dependency and returns those that match the local platform and all those that match.
# File 'lib/rubygems/resolver.rb', line 198
def find_possible(dependency) # :nodoc: all = @set.find_all dependency if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty? matching = all.select do |api_spec| skip_dep_gems.any? {|s| api_spec.version == s.version } end all = matching unless matching.empty? end matching_platform = select_local_platforms all [matching_platform, all] end
#name_for(dependency)
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 267
def name_for(dependency) dependency.name end
#output
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 172
def output @output ||= debug? ? $stdout : File.open(IO::NULL, "w") end
#requests(s, act, reqs = [])
# File 'lib/rubygems/resolver.rb', line 147
def requests(s, act, reqs=[]) # :nodoc: return reqs if @ignore_dependencies s.fetch_development_dependencies if @development s.dependencies.reverse_each do |d| next if d.type == :development && !@development next if d.type == :development && @development_shallow && act.development? next if d.type == :development && @development_shallow && act.parent reqs << Gem::Resolver::DependencyRequest.new(d, act) @stats.requirement! end @set.prefetch reqs @stats.record_requirements reqs reqs end
    #requirement_satisfied_by?(requirement, activated, spec)  ⇒ Boolean 
  
# File 'lib/rubygems/resolver.rb', line 258
def requirement_satisfied_by?(requirement, activated, spec) matches_spec = requirement.matches_spec? spec return matches_spec if @soft_missing matches_spec && spec.spec.required_ruby_version.satisfied_by?(Gem.ruby_version) && spec.spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version) end
#resolve
Proceed with resolution! Returns an array of Resolver::ActivationRequest objects.
# File 'lib/rubygems/resolver.rb', line 185
def resolve Gem::Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.map(&:payload).compact rescue Gem::Molinillo::VersionConflict => e conflict = e.conflicts.values.first raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement) ensure @output.close if defined?(@output) && !debug? end
#search_for(dependency)
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 223
def search_for(dependency) possibles, all = find_possible(dependency) if !@soft_missing && possibles.empty? exc = Gem::UnsatisfiableDependencyError.new dependency, all exc.errors = @set.errors raise exc end groups = Hash.new {|hash, key| hash[key] = [] } # create groups & sources in the same loop sources = possibles.map do |spec| source = spec.source groups[source] << spec source end.uniq.reverse activation_requests = [] sources.each do |source| groups[source]. sort_by {|spec| [spec.version, spec.platform =~ Gem::Platform.local ? 1 : 0] }. # rubocop:disable Performance/RegexpMatch map {|spec| ActivationRequest.new spec, dependency }. each {|activation_request| activation_requests << activation_request } end activation_requests end
#select_local_platforms(specs)
Returns the gems in specs that match the local platform.
# File 'lib/rubygems/resolver.rb', line 217
def select_local_platforms(specs) # :nodoc: specs.select do |spec| Gem::Platform.installable? spec end end
#sort_dependencies(dependencies, activated, conflicts)
[ GitHub ]# File 'lib/rubygems/resolver.rb', line 275
def sort_dependencies(dependencies, activated, conflicts) dependencies.sort_by.with_index do |dependency, i| name = name_for(dependency) [ activated.vertex_named(name).payload ? 0 : 1, amount_constrained(dependency), conflicts[name] ? 0 : 1, activated.vertex_named(name).payload ? 0 : search_for(dependency).count, i, # for stable sort ] end end