Class: PluginManager
- Inherits:
-
Object
show all
- Defined in:
- lib/plugin_manager.rb,
lib/plugin_manager/plugin.rb,
lib/plugin_manager/plugin_definition.rb,
lib/plugin_manager/definition_builder.rb
Defined Under Namespace
Classes: DefinitionBuilder, Dependency, Plugin, PluginDefinition
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(output = STDOUT) ⇒ PluginManager
Returns a new instance of PluginManager.
22
23
24
25
26
27
28
29
30
|
# File 'lib/plugin_manager.rb', line 22
def initialize(output = STDOUT)
@plugins = []
@unloaded_plugins = []
@loaded_plugins = []
@unreadable_definitions = []
@plugins_with_errors = []
@disabled_plugins = []
@output = output
end
|
Class Attribute Details
.current ⇒ Object
Returns the value of attribute current.
19
20
21
|
# File 'lib/plugin_manager.rb', line 19
def current
@current
end
|
Instance Attribute Details
#disabled_plugins ⇒ Object
A subset of the plugins that have been requested to be disabled.
41
42
43
44
45
46
|
# File 'lib/plugin_manager.rb', line 41
def disabled_plugins
plugins.find_all do |pd|
@disabled_plugins.include?(pd.name) &&
derivative_plugins_for(pd).all? {|der| @disabled_plugins.include? der.name}
end
end
|
#loaded_plugins ⇒ Object
Returns the value of attribute loaded_plugins.
9
10
11
|
# File 'lib/plugin_manager.rb', line 9
def loaded_plugins
@loaded_plugins
end
|
#output ⇒ Object
Returns the value of attribute output.
9
10
11
|
# File 'lib/plugin_manager.rb', line 9
def output
@output
end
|
#plugins_with_errors ⇒ Object
Returns the value of attribute plugins_with_errors.
9
10
11
|
# File 'lib/plugin_manager.rb', line 9
def plugins_with_errors
@plugins_with_errors
end
|
#unloaded_plugins ⇒ Object
Returns the value of attribute unloaded_plugins.
9
10
11
|
# File 'lib/plugin_manager.rb', line 9
def unloaded_plugins
@unloaded_plugins
end
|
#unreadable_definitions ⇒ Object
Returns the value of attribute unreadable_definitions.
9
10
11
|
# File 'lib/plugin_manager.rb', line 9
def unreadable_definitions
@unreadable_definitions
end
|
Class Method Details
.compare_version(required, got) ⇒ Object
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# File 'lib/plugin_manager.rb', line 237
def self.compare_version(required, got)
got = got.gsub(/(\.0)+$/, "")
required.split(",").all? do |req|
req = req.strip
req = req.gsub(/(\.0)+$/, "")
if md = req.match(/^(=|>|>=|<|<=|!=)?([\d\.]*)$/)
case md[1]
when ">"
got > md[2]
when ">="
got >= md[2]
when "<"
got < md[2]
when "<="
got <= md[2]
when "="
md[2] == got
when "!="
md[2] != got
end
else
@output.puts "don't recognize version string: #{required.inspect}"
end
end
end
|
Instance Method Details
#add_definition_files(definition_files) ⇒ Object
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# File 'lib/plugin_manager.rb', line 112
def add_definition_files(definition_files)
definition_files.each do |file|
begin
PluginManager.current = self
definition = instance_eval(File.read(file))
PluginManager.current = nil
definition.definition_file = File.expand_path(file)
if already_with_that_name = @plugins.detect {|pl| pl.name == definition.name }
if already_with_that_name.version.to_f < definition.version.to_f
@unloaded_plugins.delete(already_with_that_name)
@plugins.delete(already_with_that_name)
@unloaded_plugins << definition
@plugins << definition
end
else
@unloaded_plugins << definition
@plugins << definition
end
rescue Object => e
@output.puts "Unreadable plugin definition: #{file}"
@output.puts " " + e.message
@output.puts e.backtrace.map {|l| " " + l }
@unreadable_definitions << file
nil
end
end
@plugins = @plugins.sort_by {|pl| pl.name }
@unloaded_plugins = @unloaded_plugins.sort_by {|pl| pl.name }
end
|
#add_gem_plugin_source ⇒ Object
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
# File 'lib/plugin_manager.rb', line 84
def add_gem_plugin_source
all_gem_names = Gem::SourceIndex.from_installed_gems.map {|n, _| n}
redcar_plugin_gem_names = all_gem_names.select {|n| n =~ /^redcar-/}
definition_files = redcar_plugin_gem_names.map do |gem_name|
[gem_name, Gem.source_index.specification(gem_name).full_gem_path + "/plugin.rb"]
end
definition_files = definition_files.select do |name, definition_file|
File.exist?(definition_file)
end
if definition_files.any?
gem_names = definition_files.map {|n, _| n }
@output.puts "[PluginManager] found gem plugins #{gem_names.inspect}" if ENV["PLUGIN_DEBUG"]
end
add_definition_files(definition_files.map {|_, f| f})
end
|
#add_plugin_source(directory) ⇒ Object
105
106
107
108
109
110
|
# File 'lib/plugin_manager.rb', line 105
def add_plugin_source(directory)
definition_files = Dir[File.join(File.expand_path(directory), "*", "plugin.rb")]
definition_files.reject! {|f| plugins.any? {|pl| pl.definition_file == File.expand_path(f) } }
add_definition_files(definition_files)
end
|
#derivative_plugins_for(plugin) ⇒ Object
Returns all plugins that are dependent on the given plugin
49
50
51
52
53
|
# File 'lib/plugin_manager.rb', line 49
def derivative_plugins_for(plugin)
plugins.find_all do |pd|
pd.dependencies.any? {|dep| dep.required_name == plugin.name}
end
end
|
#expand_dependencies(dependency_array) ⇒ Object
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/plugin_manager.rb', line 200
def expand_dependencies(dependency_array)
previous_length = dependency_array.length
new_dependency_array = dependency_array.map do |dep|
if pl = latest_version_by_name(dep.required_name)
[dep, pl.dependencies]
else
raise "couldn't find a plugin called #{dep.required_name}"
end
end.flatten.compact.uniq
if new_dependency_array.length > previous_length
expand_dependencies(new_dependency_array)
else
new_dependency_array
end
end
|
#latest_version_by_name(name) ⇒ Object
172
173
174
|
# File 'lib/plugin_manager.rb', line 172
def latest_version_by_name(name)
@plugins.select {|pl| pl.name == name }.sort_by {|pl| pl.version }.last
end
|
#load(*plugin_names) ⇒ Object
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/plugin_manager.rb', line 143
def load(*plugin_names)
@unloaded_plugins -= disabled_plugins
if plugin_names.empty?
return load_maximal
else
target_dependencies = plugin_names.map do |n|
unless result = latest_version_by_name(n)
raise "can't find plugin named #{n}"
end
Dependency.new(self, n, ">0")
end
end
remaining_to_load = remove_already_loaded_dependencies(expand_dependencies(target_dependencies))
while remaining_to_load.length > 0
previous_length = remaining_to_load.length
if plugin = next_to_load(remaining_to_load)
load_plugin(plugin)
remaining_to_load = remaining_to_load.reject {|dep| dep.required_name == plugin.name }
else
puts "no plugin to load from #{remaining_to_load.inspect}"
return
end
new_length = remaining_to_load.length
end
end
|
#load_maximal ⇒ Object
193
194
195
196
197
198
|
# File 'lib/plugin_manager.rb', line 193
def load_maximal
while ready_plugin = @unloaded_plugins.detect {|pl| pl.dependencies.all? {|dep| dep.satisfied? }}
load_plugin(ready_plugin)
end
@load_observer = nil end
|
#load_plugin(plugin) ⇒ Object
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
# File 'lib/plugin_manager.rb', line 176
def load_plugin(plugin)
begin
@output.puts "[PluginManager] loading #{plugin.name}" if ENV["PLUGIN_DEBUG"]
plugin.load
if @load_observer
@load_observer.call(plugin)
end
@loaded_plugins << plugin
rescue Object => e
@output.puts "Error loading plugin: #{plugin.inspect}"
@output.puts " " + e.message
@output.puts e.backtrace.map {|l| " " + l }
@plugins_with_errors << plugin
end
@unloaded_plugins.delete(plugin)
end
|
#next_to_load(dependency_array) ⇒ Object
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
# File 'lib/plugin_manager.rb', line 222
def next_to_load(dependency_array)
hash = Hash.new {|h,k| h[k] = []}
dependency_array.each {|dep| hash[dep.required_name] << dep.required_version}
hash.each do |name, version_requirements|
if candidate_for_loading = unloaded_plugins.detect {|pl| pl.name == name}
all_requirements_met = version_requirements.all? do |version_requirement|
PluginManager.compare_version(version_requirement, candidate_for_loading.version)
end
all_candidate_deps_met = candidate_for_loading.dependencies.all? {|dep| dep.satisfied?}
return candidate_for_loading if all_requirements_met and all_candidate_deps_met
end
end
nil
end
|
#objects_implementing(method_name) ⇒ Object
59
60
61
|
# File 'lib/plugin_manager.rb', line 59
def objects_implementing(method_name)
plugin_objects.select {|obj| obj.respond_to?(method_name) }
end
|
#on_load(&block) ⇒ Object
32
33
34
|
# File 'lib/plugin_manager.rb', line 32
def on_load(&block)
@load_observer = block
end
|
#plugin_objects ⇒ Object
55
56
57
|
# File 'lib/plugin_manager.rb', line 55
def plugin_objects
@loaded_plugins.map {|definition| definition.object}
end
|
#plugins ⇒ Object
36
37
38
|
# File 'lib/plugin_manager.rb', line 36
def plugins
@plugins
end
|
#remove_already_loaded_dependencies(dependency_array) ⇒ Object
216
217
218
219
220
|
# File 'lib/plugin_manager.rb', line 216
def remove_already_loaded_dependencies(dependency_array)
dependency_array.reject do |dep|
loaded_plugins.map(&:name).include?(dep.required_name)
end
end
|