vop 0.3.1 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|