Skip to Content Skip to Search

Given a set of Gem::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.

Namespace
Methods
A
C
D
F
N
O
R
S
Included Modules

Constants

DEBUG_RESOLVER = !ENV["DEBUG_RESOLVER"].nil?
 

If the DEBUG_RESOLVER environment 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.

Attributes

[RW] development

Set to true if all development dependencies should be considered.

[RW] development_shallow

Set to true if immediate development dependencies should be considered.

[RW] ignore_dependencies

When true, no dependencies are looked up for requested gems.

[RW] skip_gems

Hash of gems to skip resolution. Keyed by gem name, with arrays of gem specifications as values.

[RW] soft_missing
[R] stats

List of dependencies that could not be found in the configured sources.

Class Public methods

compose_sets(*sets)

Combines sets into a ComposedSet that allows specification lookup in a uniform manner. If one of the sets is itself a ComposedSet its sets are flattened into the result ComposedSet.

# File ruby/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 ruby/lib/rubygems/resolver.rb, line 87
def self.for_current_gems(needed)
  new needed, Gem::Resolver::CurrentSet.new
end

new(needed, set = nil)

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 IndexSet, which will query rubygems.org.

# File ruby/lib/rubygems/resolver.rb, line 99
def initialize(needed, set = nil)
  @set = set || Gem::Resolver::IndexSet.new
  @needed = needed

  @development         = false
  @development_shallow = false
  @ignore_dependencies = false
  @skip_gems           = {}
  @soft_missing        = false
  @stats               = Gem::Resolver::Stats.new
end

Instance Public methods

allow_missing?(dependency)

# File ruby/lib/rubygems/resolver.rb, line 271
def allow_missing?(dependency)
  @soft_missing
end

debug?()

# File ruby/lib/rubygems/resolver.rb, line 176
def debug?
  DEBUG_RESOLVER
end

dependencies_for(specification)

# File ruby/lib/rubygems/resolver.rb, line 252
def dependencies_for(specification)
  return [] if @ignore_dependencies
  spec = specification.spec
  requests(spec, specification)
end

name_for(dependency)

# File ruby/lib/rubygems/resolver.rb, line 267
def name_for(dependency)
  dependency.name
end

output()

# File ruby/lib/rubygems/resolver.rb, line 172
def output
  @output ||= debug? ? $stdout : File.open(IO::NULL, "w")
end

requirement_satisfied_by?(requirement, activated, spec)

# File ruby/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 ActivationRequest objects.

# File ruby/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)

# File ruby/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

sort_dependencies(dependencies, activated, conflicts)

# File ruby/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