123456789_123456789_123456789_123456789_123456789_

Class: Gem::Resolver

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 =

    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.

    # File 'lib/rubygems/resolver.rb', line 24
    !ENV['DEBUG_RESOLVER'].nil?

Class Method Summary

Instance Attribute Summary

Resolver::Molinillo::UI - Included

#debug?

Whether or not debug messages should be printed.

Instance Method Summary

Resolver::Molinillo::SpecificationProvider - Included

#allow_missing?

Returns whether this dependency, which has no possible matching specifications, can safely be ignored.

#dependencies_for

Returns the dependencies of specification.

#name_for

Returns the name for the given dependency.

#name_for_explicit_dependency_source, #name_for_locking_dependency_source,
#requirement_satisfied_by?

Determines whether the given requirement is satisfied by the given spec, in the context of the current activated dependency graph.

#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.

Resolver::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 #progress_rate, this method should convey progress to the user.

#output

The IO object that should be used to print output.

#progress_rate

How often progress should be conveyed to the user via #indicate_progress, in seconds.

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.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 105

def initialize needed, set = nil
  @set = set || Gem::Resolver::IndexSet.new
  @needed = needed

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

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.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 65

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.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 93

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 180

def debug?
  DEBUG_RESOLVER
end

#development (rw)

Resolver::Set to true if all development dependencies should be considered.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 29

attr_accessor :development

#development_shallow (rw)

Resolver::Set to true if immediate development dependencies should be considered.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 34

attr_accessor :development_shallow

#ignore_dependencies (rw)

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

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 39

attr_accessor :ignore_dependencies

#missing (readonly)

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

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 44

attr_reader :missing

#skip_gems (rw)

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

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 52

attr_accessor :skip_gems

#soft_missing (rw)

When a missing dependency, don't stop. Just go on and record what was missing.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 58

attr_accessor :soft_missing

#stats (readonly)

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 46

attr_reader :stats

Instance Method Details

#allow_missing?(dependency) ⇒ Boolean

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 254

def allow_missing?(dependency)
  @missing << dependency
  @soft_missing
end

#dependencies_for(specification)

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 240

def dependencies_for(specification)
  return [] if @ignore_dependencies
  spec = specification.spec
  requests(spec, specification)
end

#name_for(dependency)

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 250

def name_for(dependency)
  dependency.name
end

#output

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 176

def output
  @output ||= debug? ? $stdout : File.open(Gem::Util::NULL_DEVICE, 'w')
end

#requirement_satisfied_by?(requirement, activated, spec) ⇒ Boolean

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 246

def requirement_satisfied_by?(requirement, activated, spec)
  requirement.matches_spec? spec
end

#resolve

Proceed with resolution! Returns an array of Resolver::ActivationRequest objects.

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 189

def resolve
  locking_dg = Molinillo::DependencyGraph.new
  Molinillo::Resolver.new(self, self).resolve(@needed.map { |d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact
rescue 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 @output and !debug?
end

#search_for(dependency)

[ GitHub ]

  
# File 'lib/rubygems/resolver.rb', line 228

def search_for(dependency)
  possibles, all = find_possible(dependency)
  if !@soft_missing && possibles.empty?
    @missing << dependency
    exc = Gem::UnsatisfiableDependencyError.new dependency, all
    exc.errors = @set.errors
    raise exc
  end
  possibles.sort_by { |s| [s.source, s.version, s.platform.to_s == Gem::Platform.local.to_s ? 1 : 0] }.
    map { |s| ActivationRequest.new s, dependency, [] }
end