Class: Ruber::ComponentManager::PluginSorter

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

Overview

Helper class used to resolve dependencies among plugins. Most likely you don’t need to use it, but simply call Ruber::ComponentManager.sort_plugins.

Instance Method Summary collapse

Constructor Details

#initialize(pdfs, ignored = []) ⇒ PluginSorter

Creates a new PluginSorter. pdfs is an array of the plugin descriptions to sort. ignored is an array containing dependencies to be ignored(maybe because they’re already loaded). ignored can be either an array of symbols, where each symbol is the name of a feature, or an array of PluginSpecifications.

Note: pdfs should contain dependencies in terms of actual plugins, not of features.



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ruber/component_manager.rb', line 67

def initialize pdfs, ignored = []
  @pdfs = {}
  @plugins = {}
  pdfs.each do |i|
    @pdfs[i.name] = i
    @plugins[i.name] = i.deps
  end
  @ignored = ignored.map{|i| i.is_a?(OpenStruct) ? i.name : i}
  @ready = []
  @deps = {}
end

Instance Method Details

#sort_pluginsObject

Sorts the plugins associated with the object, according with their dependencies and returns an array containing the plugin descriptions sorted in dependence order, from the dependence to the dependent.

If some of the plugins have dependency which doesn’t correspond neither to another plugin nor to one of the plugins to ignore, Ruber::ComponentManager::UnresolvedDep will be raised.

If there’s a circular dependency among the plugins, Ruber::ComponentManager::CircularDep will be raised.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/ruber/component_manager.rb', line 91

def sort_plugins
  @plugins.each_value do |v|
    v.reject!{|d| @ignored.include? d}
  end
  unknown = find_unknown_deps
  raise ComponentManager::UnresolvedDep.new unknown unless unknown.empty?
  circular = @plugins.keys.inject([]){ |res, plug|  res + find_dep( plug ) }
  raise ComponentManager::CircularDep.new(circular.uniq) unless circular.empty?
  deps = @deps.reject{|k, v| v.nil? }
  res = []
  old_size = deps.size
  until deps.empty?
    ready = deps.select{|k, v| v.empty?}.map{|i| i[0]}.sort_by{|i| i.to_s}
    res += ready
    ready.each do |i|
      deps.each{|d| d[1].delete i}
      deps.delete i
    end
    raise "Circular deps (this shouldn't happen)" unless old_size > deps.size
    old_size = deps.size
  end
  res.map{|i| @pdfs[i]}
end