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.
15
16
17
18
19
20
21
22
|
# File 'lib/plugin_manager.rb', line 15
def initialize(output = STDOUT)
@plugins = []
@unloaded_plugins = []
@loaded_plugins = []
@unreadable_definitions = []
@plugins_with_errors = []
@output = output
end
|
Class Attribute Details
.current ⇒ Object
Returns the value of attribute current.
12
13
14
|
# File 'lib/plugin_manager.rb', line 12
def current
@current
end
|
Instance Attribute Details
#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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
# File 'lib/plugin_manager.rb', line 204
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/plugin_manager.rb', line 89
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/plugin_manager.rb', line 61
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
82
83
84
85
86
87
|
# File 'lib/plugin_manager.rb', line 82
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
|
#expand_dependencies(dependency_array) ⇒ Object
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# File 'lib/plugin_manager.rb', line 173
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
dep
end
end.flatten.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
145
146
147
|
# File 'lib/plugin_manager.rb', line 145
def latest_version_by_name(name)
@plugins.select {|pl| pl.name == name }.sort_by {|pl| pl.version }.last
end
|
#load(*plugin_names) ⇒ Object
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/plugin_manager.rb', line 120
def load(*plugin_names)
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 = 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
166
167
168
169
170
171
|
# File 'lib/plugin_manager.rb', line 166
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'lib/plugin_manager.rb', line 149
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
# File 'lib/plugin_manager.rb', line 189
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
36
37
38
|
# File 'lib/plugin_manager.rb', line 36
def objects_implementing(method_name)
plugin_objects.select {|obj| obj.respond_to?(method_name) }
end
|
#on_load(&block) ⇒ Object
24
25
26
|
# File 'lib/plugin_manager.rb', line 24
def on_load(&block)
@load_observer = block
end
|
#plugin_objects ⇒ Object
32
33
34
|
# File 'lib/plugin_manager.rb', line 32
def plugin_objects
@loaded_plugins.map {|definition| definition.object}
end
|
#plugins ⇒ Object
28
29
30
|
# File 'lib/plugin_manager.rb', line 28
def plugins
@plugins
end
|