Class: Ruber::ComponentManager::DepsSolver

Inherits:
Object
  • Object
show all
Defined in:
lib/ruber/component_manager.rb

Overview

Helper class which contains the methods needed to find all the plugins needed

to satisfy the dependencies of a given set of plugins.

The difference between this class and PluginSorter is that the latter needs
to know all the plugins which should be loaded, while this class has the job of
finding out which ones need to be loaded.

Instance Method Summary collapse

Constructor Details

#initialize(to_load, availlable) ⇒ DepsSolver

Creates a new DepsSolver.

<i>to_load</i> is an array containing the PluginSpecification corresponding describing
the plugins to load, while <i>availlable</i> is an array containing the 
PluginSpecification which can be used to resolve dependencies.


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/ruber/component_manager.rb', line 201

def initialize to_load, availlable
  @to_load = to_load.map{|i| [i.name, i]}.to_h
  @availlable = availlable.map{|i| [i.name, i]}.to_h
  @loaded_features = to_load.inject({}) do |res, i|
    i.features.each{|f| (res[f] ||= []) << i}
    res
  end
  @availlable_plugins = availlable.map{|i| [i.name, i]}.to_h
  @availlable_features = availlable.inject({}) do |res, i|
    i.features.each{|f| (res[f] ||= []) << i}
    res
  end
  # @res is an array containing the result, that is the list of names of
  # the plugins to load to satisfy all dependencies.
  # @deps is a hash containing the reasons for which a given plugin should
  # be loaded. Each key is the name of a plugin, while each value is an array
  # containing the list of plugins directly depending on the key. If the key
  # is in the list of plugins to load (that is in the first argument passed
  # to the constructor), the array contains nil.
  @res = []
  @deps = Hash.new{|h, k| h[k] = []}
end

Instance Method Details

#solveObject

Tries to resolve the dependencies for the given plugins, returning an array

containing the plugins needed to satisfy all the dependencies. When a plugin
depends on a feature _f_, then _f_ is included in the list of needed plugins, 
together with its dependencies, unless another required plugin already provides
that feature.

If some dependencies can't be satisfied, UnresolvedDep is raised. If there are
circular dependencies, CircularDep is raised.


234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/ruber/component_manager.rb', line 234

def solve
  errors = {:missing => {}, :circular => []}
  @res = @to_load.values.inject([]) do |r, i| 
    @deps[i.name] << nil
    r + solve_for(i, errors, [])
  end
  if !errors[:missing].empty? then raise UnresolvedDep.new errors[:missing]
  elsif !errors[:circular].empty? then raise CircularDep.new errors[:circular]
  end
  remove_unneeded_deps
  @res
end