vop 0.3.1 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +34 -33
- data/README.md +184 -2
- data/bin/console +17 -0
- data/bin/setup +8 -0
- data/bin/vop.sh +6 -2
- data/exe/vop +3 -25
- data/lib/boot.rb +3 -0
- data/lib/core/meta/commands/new_command.rb +1 -0
- data/lib/core/meta/commands/new_plugin.rb +47 -0
- data/lib/core/meta/commands/search_gems_for_plugins.rb +38 -0
- data/lib/core/meta/commands/search_path.rb +6 -0
- data/lib/core/meta/commands/set.rb +12 -0
- data/lib/core/meta/commands/show.rb +6 -0
- data/lib/core/meta/commands/show_config.rb +9 -0
- data/lib/core/meta/commands/who_provides.rb +6 -0
- data/lib/core/meta/meta.plugin +1 -0
- data/lib/core/shell/commands/change_loglevel.rb +6 -0
- data/lib/{vop/plugins/core → core/shell}/commands/clear_context.rb +0 -0
- data/lib/core/shell/commands/edit.rb +12 -0
- data/lib/core/shell/commands/help.rb +49 -0
- data/lib/core/shell/commands/reset.rb +4 -0
- data/lib/{vop/plugins/core → core/shell}/commands/show_context.rb +0 -0
- data/lib/core/shell/commands/source.rb +21 -0
- data/lib/{vop/plugins/core/helpers/plugin_loader/plugin_syntax.rb → core/shell/shell.plugin} +0 -0
- data/lib/core/structure/commands/collect_contributions.rb +46 -0
- data/lib/core/structure/commands/disable_contributor.rb +16 -0
- data/lib/core/structure/commands/generate_entity_commands.rb +52 -0
- data/lib/core/structure/commands/generate_invalidation_commands.rb +26 -0
- data/lib/core/structure/commands/list_commands.rb +11 -0
- data/lib/core/structure/commands/list_contributors.rb +10 -0
- data/lib/core/structure/commands/list_entities.rb +3 -0
- data/lib/core/structure/commands/list_plugins.rb +3 -0
- data/lib/core/structure/commands/register_contributor.rb +14 -0
- data/lib/core/structure/structure.plugin +4 -0
- data/lib/vop/objects/chain.rb +25 -0
- data/lib/vop/objects/command.rb +86 -0
- data/lib/vop/objects/command_param.rb +39 -0
- data/lib/vop/objects/entities.rb +21 -0
- data/lib/vop/objects/entity.rb +75 -0
- data/lib/vop/objects/entity_definition.rb +33 -0
- data/lib/vop/objects/filter.rb +48 -0
- data/lib/vop/objects/plugin.rb +208 -0
- data/lib/vop/objects/request.rb +73 -0
- data/lib/vop/objects/response.rb +17 -0
- data/lib/vop/objects/thing_with_params.rb +17 -0
- data/lib/vop/{command_loader.rb → parts/command_loader.rb} +8 -12
- data/lib/vop/parts/dependency_resolver.rb +56 -0
- data/lib/vop/parts/entity_loader.rb +46 -0
- data/lib/vop/parts/executor.rb +155 -0
- data/lib/vop/parts/filter_loader.rb +41 -0
- data/lib/vop/parts/plugin_finder.rb +46 -0
- data/lib/vop/parts/plugin_loader.rb +72 -0
- data/lib/vop/shell/shell.rb +221 -0
- data/lib/vop/shell/shell_formatter.rb +110 -0
- data/lib/vop/shell/shell_input.rb +14 -0
- data/lib/vop/shell/shell_input_readline.rb +20 -0
- data/lib/vop/shell/shell_input_testable.rb +27 -0
- data/lib/vop/syntax/command_syntax.rb +90 -0
- data/lib/vop/syntax/entity_syntax.rb +35 -0
- data/lib/vop/syntax/filter_syntax.rb +11 -0
- data/lib/vop/syntax/plugin_syntax.rb +55 -0
- data/lib/vop/util/errors.rb +45 -0
- data/lib/vop/util/pluralizer.rb +26 -0
- data/lib/vop/util/worker.rb +24 -0
- data/lib/vop/version.rb +1 -1
- data/lib/vop/vop.rb +216 -0
- data/lib/vop.rb +16 -229
- data/vop.gemspec +18 -15
- metadata +95 -63
- data/bin/vop.rb +0 -28
- data/lib/vop/command.rb +0 -168
- data/lib/vop/entity.rb +0 -61
- data/lib/vop/loader.rb +0 -35
- data/lib/vop/plugin.rb +0 -141
- data/lib/vop/plugin_loader.rb +0 -88
- data/lib/vop/plugins/core/commands/collect_contributions.rb +0 -31
- data/lib/vop/plugins/core/commands/edit.rb +0 -12
- data/lib/vop/plugins/core/commands/help.rb +0 -38
- data/lib/vop/plugins/core/commands/identity.rb +0 -4
- data/lib/vop/plugins/core/commands/list_contributors.rb +0 -8
- data/lib/vop/plugins/core/commands/list_entities.rb +0 -3
- data/lib/vop/plugins/core/commands/pry.rb +0 -9
- data/lib/vop/plugins/core/commands/reset.rb +0 -5
- data/lib/vop/plugins/core/commands/source.rb +0 -5
- data/lib/vop/plugins/core/commands/system_call.rb +0 -5
- data/lib/vop/plugins/core/core.plugin +0 -4
- data/lib/vop/plugins/core/helpers/command_loader/command_syntax.rb +0 -45
- data/lib/vop/plugins/core/helpers/command_loader/contributions.rb +0 -28
- data/lib/vop/plugins/core/helpers/command_loader/entities.rb +0 -57
- data/lib/vop/plugins/core/helpers/helper.rb +0 -3
- data/lib/vop/plugins/meta/commands/add_search_path.rb +0 -6
- data/lib/vop/plugins/meta/commands/delete_plugin.rb +0 -13
- data/lib/vop/plugins/meta/commands/list_commands.rb +0 -17
- data/lib/vop/plugins/meta/commands/list_plugins.rb +0 -8
- data/lib/vop/plugins/meta/commands/new_command.rb +0 -14
- data/lib/vop/plugins/meta/commands/new_plugin.rb +0 -25
- data/lib/vop/plugins/meta/commands/show_search_path.rb +0 -3
- data/lib/vop/plugins/meta/commands/who_provides.rb +0 -5
- data/lib/vop/plugins/meta/meta.plugin +0 -1
- data/lib/vop/plugins/ssh/commands/scp.rb +0 -11
- data/lib/vop/plugins/ssh/commands/ssh.rb +0 -19
- data/lib/vop/plugins/ssh/ssh.plugin +0 -1
- data/lib/vop/shell/backend.rb +0 -28
- data/lib/vop/shell/base_shell.rb +0 -112
- data/lib/vop/shell/formatter.rb +0 -46
- data/lib/vop/shell/vop_shell_backend.rb +0 -257
- data/lib/vop/shell.rb +0 -52
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative "response"
|
2
|
+
require_relative "chain"
|
3
|
+
require_relative "../parts/executor"
|
4
|
+
|
5
|
+
module Vop
|
6
|
+
|
7
|
+
class Request
|
8
|
+
|
9
|
+
attr_reader :command_name, :param_values, :extra
|
10
|
+
attr_accessor :shell
|
11
|
+
|
12
|
+
def initialize(op, command_name, param_values = {}, extra = {})
|
13
|
+
@op = op
|
14
|
+
@command_name = command_name
|
15
|
+
raise "unknown command '#{command_name}'" if command.nil?
|
16
|
+
@param_values = param_values
|
17
|
+
@extra = extra
|
18
|
+
@shell = nil
|
19
|
+
|
20
|
+
@current_filter = nil
|
21
|
+
@filter_chain = @op.filter_chain.clone
|
22
|
+
end
|
23
|
+
|
24
|
+
def command
|
25
|
+
@op.commands[@command_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def cache_key
|
29
|
+
blacklist = %w|shell raw_params|
|
30
|
+
|
31
|
+
ex = Executor.new(@op)
|
32
|
+
prepared = ex.prepare_params(self)
|
33
|
+
|
34
|
+
param_string = prepared.map { |k,v|
|
35
|
+
next if blacklist.include? k
|
36
|
+
[k.to_s,v].join("=")
|
37
|
+
}.sort.compact.join(":")
|
38
|
+
"vop/request:#{command.name}:" + param_string + ":v1"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_json(op, json)
|
42
|
+
hash = JSON.parse(json)
|
43
|
+
self.new(op, hash["command"], hash["params"], hash["extra"])
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json
|
47
|
+
{
|
48
|
+
command: @command_name,
|
49
|
+
params: @param_values,
|
50
|
+
extra: @extra
|
51
|
+
}.to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
def next_filter
|
55
|
+
@chain.next()
|
56
|
+
end
|
57
|
+
|
58
|
+
def execute
|
59
|
+
result = nil
|
60
|
+
context = nil
|
61
|
+
|
62
|
+
# build a chain out of all filters + the command itself
|
63
|
+
filter_chain = @op.filter_chain.clone.map {
|
64
|
+
|filter_name| @op.filters[filter_name.split(".").first]
|
65
|
+
}
|
66
|
+
filter_chain << Executor.new(@op)
|
67
|
+
@chain = Chain.new(@op, filter_chain)
|
68
|
+
@chain.execute(self)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Vop
|
2
|
+
|
3
|
+
class Response
|
4
|
+
|
5
|
+
attr_reader :result, :context, :timestamp
|
6
|
+
attr_accessor :status
|
7
|
+
|
8
|
+
def initialize(result, context, timestamp = nil)
|
9
|
+
@result = result
|
10
|
+
@context = context
|
11
|
+
@timestamp = timestamp || Time.now
|
12
|
+
@status = "ok"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
require_relative "../syntax/command_syntax"
|
2
|
+
require_relative "../objects/command"
|
2
3
|
|
3
4
|
module Vop
|
4
5
|
|
@@ -8,24 +9,19 @@ module Vop
|
|
8
9
|
@plugin = plugin
|
9
10
|
@op = plugin.op
|
10
11
|
|
11
|
-
@commands =
|
12
|
+
@commands = []
|
12
13
|
|
13
|
-
# we need to load both the general helpers of the plugin because they are
|
14
|
-
# used inside commands as well as the helpers specific to the command_loader
|
15
14
|
@plugin.inject_helpers(self)
|
16
|
-
|
15
|
+
|
16
|
+
extend CommandSyntax
|
17
17
|
end
|
18
18
|
|
19
19
|
def new_command(name)
|
20
20
|
@command = Command.new(@plugin, name)
|
21
|
-
@commands
|
21
|
+
@commands << @command
|
22
22
|
@command
|
23
23
|
end
|
24
24
|
|
25
|
-
def run(&block)
|
26
|
-
@command.block = block
|
27
|
-
end
|
28
|
-
|
29
25
|
def read_sources(named_commands)
|
30
26
|
# reads a hash of <command_name> => <source string>
|
31
27
|
named_commands.each do |name, source|
|
@@ -34,8 +30,8 @@ module Vop
|
|
34
30
|
|
35
31
|
begin
|
36
32
|
self.instance_eval(source[:code], source[:file_name])
|
37
|
-
rescue
|
38
|
-
raise "problem loading
|
33
|
+
rescue Exception
|
34
|
+
raise Errors::CommandLoadError.new("problem loading command #{name}")
|
39
35
|
end
|
40
36
|
end
|
41
37
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Vop
|
2
|
+
|
3
|
+
class DependencyResolver
|
4
|
+
|
5
|
+
def initialize(op)
|
6
|
+
@op = op
|
7
|
+
end
|
8
|
+
|
9
|
+
def sort(plugins)
|
10
|
+
@plugins = {}
|
11
|
+
plugins.each do |plugin|
|
12
|
+
@plugins[plugin.name] = plugin
|
13
|
+
end
|
14
|
+
|
15
|
+
resolved = []
|
16
|
+
unresolved = []
|
17
|
+
|
18
|
+
root_plugin = Plugin.new(@op, "__root__", nil)
|
19
|
+
root_plugin.dependencies = @plugins.keys
|
20
|
+
|
21
|
+
$logger.debug "root dummy : #{root_plugin}"
|
22
|
+
|
23
|
+
resolve(root_plugin, resolved, unresolved)
|
24
|
+
resolved.delete_if { |x| x == root_plugin.name }
|
25
|
+
|
26
|
+
resolved.map { |x| @plugins[x] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def resolve(plugin, resolved, unresolved, level = 0)
|
30
|
+
$logger.debug "#{' ' * level}checking dependencies for #{plugin.name}"
|
31
|
+
unresolved << plugin.name
|
32
|
+
|
33
|
+
plugin.dependencies.each do |dep|
|
34
|
+
$logger.debug "#{' ' * level}resolving #{dep}"
|
35
|
+
already_loaded = @op.plugins.map(&:name).include? dep
|
36
|
+
unless already_loaded
|
37
|
+
unless resolved.include? dep
|
38
|
+
if unresolved.include? dep
|
39
|
+
raise ::Vop::Errors::RunningInCircles, "circular dependency #{plugin.name} -> #{dep}"
|
40
|
+
else
|
41
|
+
unless @plugins.has_key? dep
|
42
|
+
raise ::Vop::Errors::MissingPlugin, "dependency not met: #{plugin.name} depends on #{dep}"
|
43
|
+
end
|
44
|
+
dependency = @plugins[dep]
|
45
|
+
resolve(dependency, resolved, unresolved, level + 1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
resolved << plugin.name
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative "../syntax/entity_syntax"
|
2
|
+
require_relative "../objects/entity_definition"
|
3
|
+
|
4
|
+
module Vop
|
5
|
+
|
6
|
+
class EntityLoader
|
7
|
+
|
8
|
+
def initialize(plugin)
|
9
|
+
@plugin = plugin
|
10
|
+
@op = plugin.op
|
11
|
+
|
12
|
+
@loaded = []
|
13
|
+
|
14
|
+
@plugin.inject_helpers(self)
|
15
|
+
|
16
|
+
#@command = @entity
|
17
|
+
#extend CommandSyntax
|
18
|
+
extend EntitySyntax
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare(name)
|
22
|
+
@entity = EntityDefinition.new(@plugin, name)
|
23
|
+
@command = @entity
|
24
|
+
@loaded << @entity
|
25
|
+
@entity
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_sources(named_sources)
|
29
|
+
# reads a hash of <name> => <source string>
|
30
|
+
named_sources.each do |name, source|
|
31
|
+
|
32
|
+
prepare(name)
|
33
|
+
|
34
|
+
begin
|
35
|
+
self.instance_eval(source[:code], source[:file_name])
|
36
|
+
rescue SyntaxError => detail
|
37
|
+
raise Errors::EntityLoadError.new("problem loading entity #{name} : #{detail.message}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@loaded
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Vop
|
2
|
+
|
3
|
+
class Executor
|
4
|
+
|
5
|
+
def initialize(vop)
|
6
|
+
@op = vop
|
7
|
+
end
|
8
|
+
|
9
|
+
# accepts arguments as handed in by :define_method and prepares them
|
10
|
+
# into the +params+ structure expected by command blocks
|
11
|
+
def prepare_params(request)
|
12
|
+
(ruby_args, extra) = request.param_values, request.extra
|
13
|
+
result = {}
|
14
|
+
if ruby_args
|
15
|
+
if ruby_args.is_a? Hash
|
16
|
+
result = ruby_args
|
17
|
+
else
|
18
|
+
# if there is a default param, it can be passed to execute as "scalar"
|
19
|
+
# param, but it will be converted into a "normal" named param
|
20
|
+
dp = request.command.default_param
|
21
|
+
if dp
|
22
|
+
result = {
|
23
|
+
dp.name => ruby_args
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
if extra.keys.size > 0
|
30
|
+
extra.each do |k,v|
|
31
|
+
param = request.command.param(k)
|
32
|
+
# TODO actually, this is not always context - it's used from the entities as well
|
33
|
+
if param && param.wants_context
|
34
|
+
result[k] = extra[k]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# add in defaults (for all params that have not been specified)
|
40
|
+
request.command.params.each do |p|
|
41
|
+
param_name = p.name.to_sym
|
42
|
+
unless result.has_key? param_name
|
43
|
+
if p.options.has_key? :default
|
44
|
+
result[param_name] = p.options[:default]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
result.each do |k,v|
|
50
|
+
param = request.command.param(k.to_s)
|
51
|
+
if param.nil? && ! request.command.allows_extra
|
52
|
+
raise "no such param #{k.to_s} (in #{request.command.name})"
|
53
|
+
end
|
54
|
+
p = param && param.options
|
55
|
+
if p
|
56
|
+
# values are auto-boxed into an array if the param expects multiple values
|
57
|
+
if p[:multi] && ! v.is_a?(Array) then
|
58
|
+
v = [ v ]
|
59
|
+
# array values are auto-unboxed if the param does not want multi
|
60
|
+
elsif ! p[:multi] && v.is_a?(Array) && v.length == 1
|
61
|
+
v = v.first
|
62
|
+
end
|
63
|
+
|
64
|
+
# convert booleans
|
65
|
+
if p[:boolean] && ! v.nil?
|
66
|
+
unless [true, false].include? v
|
67
|
+
#$logger.debug("converting #{param.name} (#{v}) into boolean")
|
68
|
+
v = !! /[tT]rue|[yY]es|[oO]n/.match(v)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
result[k] = v
|
73
|
+
end
|
74
|
+
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
def prepare_payload(request, context, block_param_names)
|
79
|
+
payload = []
|
80
|
+
|
81
|
+
prepared = prepare_params(request)
|
82
|
+
param_names = request.command.params.map { |x| x.name }
|
83
|
+
|
84
|
+
block_param_names.each do |name|
|
85
|
+
param = nil
|
86
|
+
|
87
|
+
case name.to_s
|
88
|
+
when "params"
|
89
|
+
param = prepared
|
90
|
+
when "plugin"
|
91
|
+
param = request.command.plugin
|
92
|
+
when "command"
|
93
|
+
param = request.command
|
94
|
+
when "request"
|
95
|
+
param = request
|
96
|
+
when "context"
|
97
|
+
param = context
|
98
|
+
when "shell"
|
99
|
+
raise "shell not supported" if request.shell.nil?
|
100
|
+
param = request.shell
|
101
|
+
else
|
102
|
+
if prepared.has_key? name.to_s
|
103
|
+
param = prepared[name.to_s]
|
104
|
+
elsif prepared.has_key? name
|
105
|
+
param = prepared[name]
|
106
|
+
else
|
107
|
+
unless param_names.include? name.to_s
|
108
|
+
raise "unknown block param name : >>#{name}<<"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
unless param.nil?
|
114
|
+
command_param = request.command.param(name.to_s)
|
115
|
+
if command_param && command_param.options[:entity]
|
116
|
+
# auto-inflate entities
|
117
|
+
entity_list = @op.entities.values
|
118
|
+
entity = entity_list.select { |x| x.short_name == name.to_s }.first
|
119
|
+
|
120
|
+
unless entity.nil?
|
121
|
+
#$logger.debug "auto-inflating entity #{name.to_s} (#{param})"
|
122
|
+
|
123
|
+
list_command_name = entity.short_name.carefully_pluralize
|
124
|
+
the_list = @op.execute(list_command_name, {})
|
125
|
+
#$logger.debug "inflated entity list : #{the_list.size} entities"
|
126
|
+
param = the_list.select { |x| x[entity.key] == param }.first
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
payload << param
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
payload
|
135
|
+
end
|
136
|
+
|
137
|
+
def execute(request)
|
138
|
+
blacklist = %w|list_contributors collect_contributions machines rails_machines|
|
139
|
+
unless blacklist.include? request.command.short_name
|
140
|
+
$logger.debug "+++ #{request.command.short_name} (#{request.param_values}) +++"
|
141
|
+
end
|
142
|
+
command = request.command
|
143
|
+
|
144
|
+
context = {}
|
145
|
+
block_param_names = request.command.block.parameters.map { |x| x.last }
|
146
|
+
payload = prepare_payload(request, context, block_param_names)
|
147
|
+
result = command.execute(payload)
|
148
|
+
|
149
|
+
Response.new(result, context)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "../syntax/filter_syntax"
|
2
|
+
require_relative "../objects/filter"
|
3
|
+
|
4
|
+
module Vop
|
5
|
+
|
6
|
+
class FilterLoader
|
7
|
+
|
8
|
+
def initialize(plugin)
|
9
|
+
@plugin = plugin
|
10
|
+
@op = @plugin.op
|
11
|
+
|
12
|
+
@filters = []
|
13
|
+
|
14
|
+
@plugin.inject_helpers(self)
|
15
|
+
extend FilterSyntax
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_filter(name)
|
19
|
+
@filter = Filter.new(@plugin, name)
|
20
|
+
@filters << @filter
|
21
|
+
@filter
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_sources(named_sources)
|
25
|
+
# reads a hash of <name> => <source string>
|
26
|
+
named_sources.each do |name, source|
|
27
|
+
new_filter(name)
|
28
|
+
|
29
|
+
begin
|
30
|
+
self.instance_eval(source[:code], source[:file_name])
|
31
|
+
rescue => detail
|
32
|
+
raise Errors::LoadError.new("problem loading filter #{name}", detail)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
@filters
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module Vop
|
4
|
+
|
5
|
+
class PluginFinder
|
6
|
+
|
7
|
+
attr_reader :plugins, :templates
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
reset
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset
|
14
|
+
@plugins = []
|
15
|
+
@templates = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(paths)
|
19
|
+
reset
|
20
|
+
|
21
|
+
$logger.debug "scanning #{paths} for plugins..."
|
22
|
+
paths = [ paths ] unless paths.is_a? Array
|
23
|
+
|
24
|
+
if paths.size > 0
|
25
|
+
paths.each do |path|
|
26
|
+
begin
|
27
|
+
next unless File.exists? path
|
28
|
+
rescue => e
|
29
|
+
if e.message =~ /Fixnum/
|
30
|
+
$logger.warn "unexpected Fixnum path : #{path}"
|
31
|
+
end
|
32
|
+
raise e
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
@plugins += Dir.glob("#{path}/**/*.plugin").map { |x| Pathname.new(File.dirname(x)).realpath.to_s }
|
37
|
+
@templates += Dir.glob("#{path}/**/plugin.vop").map { |x| Pathname.new(x).realpath.to_s }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require_relative "../objects/plugin"
|
2
|
+
require_relative "../syntax/plugin_syntax"
|
3
|
+
require_relative "../util/errors"
|
4
|
+
|
5
|
+
module Vop
|
6
|
+
|
7
|
+
class PluginLoader
|
8
|
+
|
9
|
+
attr_reader :loaded
|
10
|
+
|
11
|
+
def initialize(op)
|
12
|
+
@op = op
|
13
|
+
|
14
|
+
extend PluginSyntax
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
@loaded = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_plugin(plugin_name, plugin_path, plugin_options = {})
|
22
|
+
@plugin = Plugin.new(@op, plugin_name, plugin_path, plugin_options)
|
23
|
+
@plugin
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_plugin(code, source_file = nil)
|
27
|
+
begin
|
28
|
+
instance_eval(code, source_file)
|
29
|
+
rescue => detail
|
30
|
+
$logger.warn "problem loading plugin #{@plugin.name} : #{detail.message}\n#{detail.backtrace.join("\n")}"
|
31
|
+
raise Errors::PluginLoadError.new(detail)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def load(found, plugin_options = {})
|
36
|
+
reset
|
37
|
+
|
38
|
+
(plugins, templates) = [found.plugins, found.templates]
|
39
|
+
|
40
|
+
plugins.each do |plugin_path|
|
41
|
+
name = File.basename(plugin_path)
|
42
|
+
|
43
|
+
$logger.debug "loading #{name} from #{plugin_path}"
|
44
|
+
plugin = new_plugin(name, plugin_path, plugin_options)
|
45
|
+
|
46
|
+
templates.each do |template|
|
47
|
+
template_path = File.dirname(template)
|
48
|
+
if plugin_path.start_with? template_path
|
49
|
+
$logger.debug " (applying template #{template_path})"
|
50
|
+
template_file = File.join(template_path, "plugin.vop")
|
51
|
+
code = File.read(template_file)
|
52
|
+
read_plugin(code, template_file)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
plugin_file = File.join(plugin_path, "#{name}.plugin")
|
57
|
+
next unless File.exists?(plugin_file)
|
58
|
+
$logger.debug "reading plugin '#{name}' from '#{plugin_file}'"
|
59
|
+
|
60
|
+
code = File.read(plugin_file)
|
61
|
+
read_plugin(code, plugin_file)
|
62
|
+
@loaded << @plugin
|
63
|
+
|
64
|
+
$logger.debug "loaded plugin #{@plugin.name}"
|
65
|
+
end
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|