vop 0.3.5 → 0.3.6
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 +5 -5
- data/.github/workflows/ci.yml +39 -0
- data/.ruby-version +1 -0
- data/Gemfile.lock +34 -47
- data/README.md +118 -16
- data/bin/sidekiq.sh +10 -0
- data/exe/vop +2 -2
- data/lib/core/cache/cache.plugin +0 -0
- data/lib/core/cache/commands/invalidate_cache.rb +9 -0
- data/lib/core/{structure → meta}/commands/list_commands.rb +2 -1
- data/lib/core/meta/commands/list_filters.rb +3 -0
- data/lib/core/meta/commands/list_plugins.rb +3 -0
- data/lib/core/meta/commands/new_plugin.rb +3 -7
- data/lib/core/shell/commands/detail.rb +21 -0
- data/lib/core/shell/commands/edit.rb +5 -2
- data/lib/core/shell/commands/help.rb +1 -1
- data/lib/core/shell/commands/source.rb +10 -4
- data/lib/core/structure/commands/collect_contributions.rb +8 -2
- data/lib/core/structure/commands/generate_entity_commands.rb +19 -10
- data/lib/core/structure/commands/generate_invalidation_commands.rb +19 -9
- data/lib/core/structure/commands/list_contribution_targets.rb +9 -0
- data/lib/core/structure/commands/list_contributors.rb +1 -1
- data/lib/core/structure/structure.plugin +1 -1
- data/lib/vop/objects/chain.rb +6 -3
- data/lib/vop/objects/command.rb +14 -5
- data/lib/vop/objects/command_param.rb +22 -0
- data/lib/vop/objects/entities.rb +8 -8
- data/lib/vop/objects/entity.rb +57 -16
- data/lib/vop/objects/entity_definition.rb +22 -0
- data/lib/vop/objects/plugin.rb +46 -4
- data/lib/vop/objects/request.rb +9 -5
- data/lib/vop/parts/dependency_resolver.rb +0 -4
- data/lib/vop/parts/entity_loader.rb +0 -3
- data/lib/vop/parts/executor.rb +33 -8
- data/lib/vop/parts/plugin_finder.rb +6 -16
- data/lib/vop/search_path.rb +12 -0
- data/lib/vop/shell/shell.rb +134 -87
- data/lib/vop/shell/shell_formatter.rb +32 -17
- data/lib/vop/shell/shell_input_readline.rb +3 -0
- data/lib/vop/shell/shell_input_testable.rb +9 -3
- data/lib/vop/syntax/command_syntax.rb +22 -17
- data/lib/vop/syntax/entity_syntax.rb +21 -6
- data/lib/vop/syntax/plugin_syntax.rb +6 -0
- data/lib/vop/util/pluralizer.rb +9 -1
- data/lib/vop/version.rb +1 -1
- data/lib/vop/vop.rb +70 -44
- data/lib/vop.rb +11 -1
- data/vop.gemspec +8 -6
- metadata +103 -28
- data/lib/core/meta/commands/search_gems_for_plugins.rb +0 -38
- data/lib/core/meta/commands/search_path.rb +0 -6
- data/lib/core/structure/commands/list_plugins.rb +0 -3
- data/lib/vop/util/worker.rb +0 -24
data/lib/vop/shell/shell.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require "readline"
|
2
1
|
require_relative "shell_formatter"
|
3
2
|
require_relative "shell_input"
|
4
3
|
require_relative "shell_input_readline"
|
@@ -8,6 +7,7 @@ module Vop
|
|
8
7
|
class Shell
|
9
8
|
|
10
9
|
attr_reader :context
|
10
|
+
attr_reader :last_response
|
11
11
|
|
12
12
|
def initialize(op, input = nil)
|
13
13
|
@op = op
|
@@ -15,7 +15,7 @@ module Vop
|
|
15
15
|
|
16
16
|
@formatter = ShellFormatter.new
|
17
17
|
|
18
|
-
#
|
18
|
+
# override for testing
|
19
19
|
if input.nil?
|
20
20
|
input = ShellInputReadline.new(method(:tab_completion))
|
21
21
|
end
|
@@ -45,43 +45,48 @@ module Vop
|
|
45
45
|
puts
|
46
46
|
print @prompt
|
47
47
|
else
|
48
|
-
puts "\
|
48
|
+
puts "\n"
|
49
49
|
exit
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def mix_arguments_and_context
|
54
|
-
result = @arguments
|
53
|
+
def mix_arguments_and_context(command = nil, arguments = nil)
|
54
|
+
result = arguments || @arguments
|
55
55
|
@context.each do |k,v|
|
56
|
-
|
57
|
-
if
|
58
|
-
|
56
|
+
cmd = command || @command
|
57
|
+
if cmd
|
58
|
+
param = (cmd).param(k)
|
59
|
+
if param && param.wants_context
|
60
|
+
result[k] = @context[k]
|
61
|
+
end
|
59
62
|
end
|
60
63
|
end
|
61
64
|
result
|
62
65
|
end
|
63
66
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
missing_mandatory_params = @command.mandatory_params.delete_if do |param|
|
68
|
-
@arguments.keys.include?(param.name) ||
|
67
|
+
def missing_mandatory_params(command = @command, arguments = @arguments)
|
68
|
+
command.mandatory_params.delete_if do |param|
|
69
|
+
arguments.keys.include?(param.name) ||
|
69
70
|
(@context.keys.include?(param.name) && param.wants_context)
|
70
71
|
end
|
72
|
+
end
|
71
73
|
|
72
|
-
|
73
|
-
$logger.debug "missing params : #{missing_mandatory_params.map(&:name)}"
|
74
|
-
end
|
75
|
-
|
74
|
+
def maybe_execute
|
76
75
|
if missing_mandatory_params.size > 0
|
77
76
|
@missing_params = missing_mandatory_params
|
78
77
|
@prompt = "#{@command.short_name}.#{@missing_params.first.name} ? "
|
79
78
|
else
|
80
79
|
begin
|
81
|
-
request =
|
80
|
+
request = @op.prepare_request(@command.short_name, @arguments, @context, @command.short_name)
|
82
81
|
request.shell = self
|
83
82
|
response = @op.execute_request(request)
|
84
83
|
|
84
|
+
# log the last response for the "detail" command
|
85
|
+
unless @command.short_name == "detail"
|
86
|
+
@last_response = response
|
87
|
+
end
|
88
|
+
|
89
|
+
# mix context changes from the response into the local context
|
85
90
|
@context.merge! response.context
|
86
91
|
|
87
92
|
display_type = @formatter.analyze(request, response)
|
@@ -95,65 +100,92 @@ module Vop
|
|
95
100
|
end
|
96
101
|
|
97
102
|
def accept_param(line)
|
98
|
-
|
99
|
-
|
100
|
-
|
103
|
+
unless line.nil?
|
104
|
+
current_param = @missing_params.shift
|
105
|
+
$logger.debug "value for param #{current_param.name} : #{line}"
|
106
|
+
@arguments[current_param.name] = line
|
101
107
|
|
102
|
-
|
108
|
+
maybe_execute
|
109
|
+
end
|
103
110
|
end
|
104
111
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
112
|
+
def is_special?(command)
|
113
|
+
command.start_with?('$') || command.start_with?('@') || command.end_with?('?')
|
114
|
+
end
|
115
|
+
|
116
|
+
def handle_special(command)
|
117
|
+
if command.start_with?('$')
|
118
|
+
if command.start_with?('$vop')
|
119
|
+
puts "executing #{command}"
|
120
|
+
puts eval command
|
121
|
+
else
|
122
|
+
puts "unknown $-command #{command} - try '$vop' maybe?"
|
123
|
+
end
|
124
|
+
elsif command.start_with?('@')
|
125
|
+
if command.start_with?('@op')
|
126
|
+
puts "executing #{command}"
|
127
|
+
puts eval command
|
128
|
+
else
|
129
|
+
puts "unknown @-command #{command} - try '@op' maybe?"
|
118
130
|
end
|
119
131
|
end
|
120
|
-
result
|
121
132
|
end
|
122
133
|
|
123
|
-
def
|
134
|
+
def parse(command_line)
|
124
135
|
(command, *args) = command_line.split
|
125
136
|
|
137
|
+
arguments = {}
|
126
138
|
if command
|
127
139
|
$logger.debug "command : #{command}, args : #{args}"
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
|
141
|
+
if command.end_with?("??")
|
142
|
+
target_command = command[0..-3]
|
143
|
+
command = "source"
|
144
|
+
arguments["name"] = target_command
|
145
|
+
elsif command.end_with?("?")
|
146
|
+
target_command = command[0..-2]
|
147
|
+
command = "help"
|
148
|
+
arguments["name"] = target_command
|
149
|
+
end
|
150
|
+
|
151
|
+
known_commands = @op.commands.keys
|
152
|
+
if known_commands.include? command
|
153
|
+
cmd = @op.commands[command]
|
154
|
+
|
155
|
+
unless args.empty? || is_special?(command)
|
156
|
+
args.each do |token|
|
157
|
+
if token.include? "="
|
158
|
+
(key, value) = token.split("=")
|
159
|
+
arguments[key] = value
|
160
|
+
else
|
161
|
+
default_param = cmd.default_param(mix_arguments_and_context)
|
162
|
+
if default_param
|
163
|
+
arguments[default_param.name] = args
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
141
167
|
end
|
168
|
+
[command, cmd, arguments]
|
142
169
|
else
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
170
|
+
[command, nil, arguments]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
148
174
|
|
175
|
+
def parse_and_execute(command_line)
|
176
|
+
command, cmd, arguments = parse(command_line)
|
177
|
+
|
178
|
+
if command
|
179
|
+
$logger.debug "command : #{command}, args : #{arguments}"
|
180
|
+
if is_special?(command)
|
181
|
+
handle_special(command_line)
|
182
|
+
else
|
149
183
|
if command == "exit"
|
150
184
|
@input.exit
|
151
185
|
else
|
152
|
-
|
153
|
-
|
154
|
-
@
|
155
|
-
@arguments = parse_command_line(args)
|
156
|
-
|
186
|
+
if cmd
|
187
|
+
@command = cmd
|
188
|
+
@arguments = arguments
|
157
189
|
maybe_execute
|
158
190
|
else
|
159
191
|
puts "unknown command '#{command}'"
|
@@ -161,47 +193,62 @@ module Vop
|
|
161
193
|
end
|
162
194
|
end
|
163
195
|
end
|
164
|
-
|
165
196
|
end
|
166
197
|
|
167
|
-
def
|
168
|
-
|
198
|
+
def complete_for_command(s)
|
199
|
+
current_param = @missing_params.first
|
200
|
+
if current_param && current_param.options.has_key?(:lookup)
|
201
|
+
begin
|
202
|
+
lookup_block = current_param.options[:lookup]
|
169
203
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
# the lookup block might want the previously collected params as input
|
177
|
-
lookups = if lookup_block.arity > 0
|
178
|
-
params_for_lookup = mix_arguments_and_context
|
179
|
-
lookup_block.call(params_for_lookup)
|
180
|
-
else
|
181
|
-
lookup_block.call()
|
182
|
-
end
|
183
|
-
rescue => detail
|
184
|
-
$logger.error "problem loading lookup values for #{current_param.name} : #{detail.message}"
|
204
|
+
# the lookup block might want the previously collected params as input
|
205
|
+
lookups = if lookup_block&.arity > 0
|
206
|
+
params_for_lookup = mix_arguments_and_context
|
207
|
+
lookup_block.call(params_for_lookup)
|
208
|
+
else
|
209
|
+
lookup_block.call()
|
185
210
|
end
|
211
|
+
lookups.grep /^#{Regexp.escape(s)}/
|
212
|
+
rescue => detail
|
213
|
+
$logger.error "problem loading lookup values for #{current_param.name} : #{detail.message}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def complete_command_line(s)
|
219
|
+
potential_command, potential_cmd, potential_args = parse(s)
|
220
|
+
#$logger.debug "? >>#{potential_cmd}<< (#{potential_args}) [#{Readline.line_buffer}]"
|
221
|
+
if potential_cmd
|
222
|
+
default_param = potential_cmd.default_param
|
223
|
+
if default_param
|
224
|
+
lookups = default_param.lookup(mix_arguments_and_context)
|
225
|
+
lookups
|
226
|
+
.grep(/^#{Regexp.escape(s.split.last)}/)
|
227
|
+
.map do |lookup|
|
228
|
+
"#{potential_command} #{lookup}"
|
229
|
+
end
|
186
230
|
end
|
187
231
|
else
|
188
|
-
lookups = @op.commands.keys.sort
|
232
|
+
lookups = @op.commands.keys.sort.grep /^#{Regexp.escape(s)}/
|
189
233
|
end
|
190
234
|
|
191
|
-
lookups.grep /^#{Regexp.escape(s)}/
|
192
235
|
end
|
193
236
|
|
194
|
-
def
|
195
|
-
|
196
|
-
|
237
|
+
def tab_completion(s)
|
238
|
+
if @command
|
239
|
+
complete_for_command(s)
|
240
|
+
else
|
241
|
+
complete_command_line(s)
|
242
|
+
end
|
243
|
+
end
|
197
244
|
|
198
|
-
|
245
|
+
def do_it(command_line = nil)
|
246
|
+
if command_line && command_line != ""
|
199
247
|
parse_and_execute(command_line)
|
200
248
|
else
|
201
249
|
while line = @input.read(@prompt)
|
202
|
-
#while line = Readline.readline(@prompt, true)
|
203
250
|
if @command
|
204
|
-
# if a command has already been selected,
|
251
|
+
# if a command has already been selected, ask for missing params
|
205
252
|
accept_param(line)
|
206
253
|
else
|
207
254
|
# otherwise input is treated as regular command line (command + args)
|
@@ -213,7 +260,7 @@ module Vop
|
|
213
260
|
|
214
261
|
def self.run(op = nil, command_line = nil)
|
215
262
|
if op.nil?
|
216
|
-
op = Vop.new
|
263
|
+
op = Vop.new(origin: "shell:#{Process.pid}@#{`hostname`.strip}")
|
217
264
|
end
|
218
265
|
self.new(op).do_it(command_line)
|
219
266
|
end
|
@@ -35,10 +35,11 @@ module Vop
|
|
35
35
|
command = request.command
|
36
36
|
show_options = command.show_options
|
37
37
|
|
38
|
-
|
38
|
+
case display_type
|
39
39
|
when :table
|
40
40
|
columns_to_display =
|
41
41
|
if show_options[:columns]
|
42
|
+
# TODO validate all columns exist?
|
42
43
|
show_options[:columns]
|
43
44
|
else
|
44
45
|
# TODO this is not optimal - what if the second row has more keys than the first?
|
@@ -54,8 +55,9 @@ module Vop
|
|
54
55
|
data.each do |row|
|
55
56
|
values = [ ]
|
56
57
|
columns_to_display.each do |key|
|
57
|
-
|
58
|
-
|
58
|
+
potential_value = row[key.to_s] || row[key.to_sym]
|
59
|
+
values << potential_value
|
60
|
+
end unless row.nil?
|
59
61
|
rearranged << values
|
60
62
|
end
|
61
63
|
|
@@ -79,18 +81,33 @@ module Vop
|
|
79
81
|
"#{k} : #{v}"
|
80
82
|
end.join("\n")
|
81
83
|
when :entity_list
|
82
|
-
data.sort_by { |e| e.id }
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
84
|
+
sorted = data.sort_by { |e| e.id }
|
85
|
+
|
86
|
+
columns = if show_options[:columns]
|
87
|
+
show_options[:columns]
|
88
|
+
else
|
89
|
+
blacklisted_keys = %w|name params plugin_name|
|
90
|
+
all_keys = sorted.map { |x| x.data.keys }.flatten.uniq
|
91
|
+
all_keys.delete_if { |x| blacklisted_keys.include? x }
|
92
|
+
end
|
93
|
+
|
94
|
+
headers = [ sorted.first.key ] + columns
|
95
|
+
|
96
|
+
rows = sorted.map do |entity|
|
97
|
+
row = [ entity.id ]
|
98
|
+
|
99
|
+
columns.each do |column|
|
100
|
+
value = entity.data[column] || ""
|
101
|
+
row << (value.respond_to?(to_s) ? value.to_s[0..49] : value)
|
102
|
+
end
|
103
|
+
|
104
|
+
row
|
105
|
+
end
|
106
|
+
|
107
|
+
Terminal::Table.new(
|
108
|
+
rows: rows,
|
109
|
+
headings: headers
|
110
|
+
)
|
94
111
|
when :entity
|
95
112
|
entity = data
|
96
113
|
"[#{entity.type}] #{entity.id}"
|
@@ -101,8 +118,6 @@ module Vop
|
|
101
118
|
else
|
102
119
|
raise "unknown display type #{display_type}"
|
103
120
|
end
|
104
|
-
|
105
|
-
result
|
106
121
|
end
|
107
122
|
|
108
123
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "readline"
|
2
|
+
|
1
3
|
module Vop
|
2
4
|
|
3
5
|
class ShellInputReadline
|
@@ -5,6 +7,7 @@ module Vop
|
|
5
7
|
def initialize(completion_method)
|
6
8
|
Readline.completion_append_character = ""
|
7
9
|
Readline.completion_proc = completion_method
|
10
|
+
Readline.completer_word_break_characters = "\t\n\"\\'\`@$><=;|&{(" # default, but without space
|
8
11
|
end
|
9
12
|
|
10
13
|
def read(prompt)
|
@@ -3,17 +3,23 @@ module Vop
|
|
3
3
|
class TestableShellInput
|
4
4
|
|
5
5
|
attr_accessor :answers
|
6
|
-
attr_reader :exit
|
6
|
+
attr_reader :exit, :prompt
|
7
|
+
attr_accessor :fail_if_out_of_answers
|
7
8
|
|
8
9
|
def initialize
|
9
10
|
@answers = []
|
10
11
|
@exit = false
|
12
|
+
@prompt = nil
|
13
|
+
@fail_if_out_of_answers = true
|
11
14
|
end
|
12
15
|
|
13
16
|
def read(prompt)
|
17
|
+
@prompt = prompt
|
14
18
|
answer = @answers.shift
|
15
|
-
if answer.nil?
|
16
|
-
|
19
|
+
if answer.nil? && @fail_if_out_of_answers
|
20
|
+
unless @exit
|
21
|
+
raise "no more pre-defined answers (asked for '#{prompt}')"
|
22
|
+
end
|
17
23
|
end
|
18
24
|
answer
|
19
25
|
end
|
@@ -2,24 +2,17 @@ module Vop
|
|
2
2
|
|
3
3
|
module CommandSyntax
|
4
4
|
|
5
|
-
def run(&block)
|
6
|
-
@command.block = block
|
7
|
-
end
|
8
|
-
|
9
5
|
def description(s)
|
10
6
|
@command.description = s
|
11
7
|
end
|
12
8
|
|
13
|
-
def
|
14
|
-
|
15
|
-
options = {
|
16
|
-
description: options
|
17
|
-
}
|
18
|
-
end
|
19
|
-
options
|
9
|
+
def run(&block)
|
10
|
+
@command.block = block
|
20
11
|
end
|
21
12
|
|
22
|
-
def param(name, options = {})
|
13
|
+
def param(name, options = {}, more_options = {})
|
14
|
+
options = resolve_options_string(options).merge(more_options)
|
15
|
+
|
23
16
|
if name.is_a? Symbol
|
24
17
|
key = "name" # default for select_machine
|
25
18
|
entity = @op.entities.values.select { |x| x.short_name == name.to_s }.first
|
@@ -38,18 +31,15 @@ module Vop
|
|
38
31
|
name = name.to_s
|
39
32
|
end
|
40
33
|
|
41
|
-
options = resolve_options_string(options)
|
42
|
-
|
43
34
|
@command.add_param(name, options)
|
44
35
|
end
|
45
36
|
|
46
|
-
def param!(name, options = {})
|
47
|
-
options = resolve_options_string(options)
|
37
|
+
def param!(name, options = {}, more_options = {})
|
38
|
+
options = resolve_options_string(options).merge(more_options)
|
48
39
|
options.merge! mandatory: true
|
49
40
|
param(name, options)
|
50
41
|
end
|
51
42
|
|
52
|
-
# TODO does not really work yet
|
53
43
|
def block_param(name = "block", options = {})
|
54
44
|
options.merge! block: true
|
55
45
|
param(name, options)
|
@@ -69,6 +59,10 @@ module Vop
|
|
69
59
|
@command.allows_extra = true
|
70
60
|
end
|
71
61
|
|
62
|
+
def dont_log
|
63
|
+
@command.dont_log = true
|
64
|
+
end
|
65
|
+
|
72
66
|
def show(options = {})
|
73
67
|
@command.show_options[:columns] = options.delete(:columns)
|
74
68
|
@command.show_options[:display_type] = options.delete(:display_type)
|
@@ -89,6 +83,17 @@ module Vop
|
|
89
83
|
@command.invalidation_block = block
|
90
84
|
end
|
91
85
|
|
86
|
+
private
|
87
|
+
|
88
|
+
def resolve_options_string(options)
|
89
|
+
if options.is_a? String
|
90
|
+
options = {
|
91
|
+
description: options
|
92
|
+
}
|
93
|
+
end
|
94
|
+
options
|
95
|
+
end
|
96
|
+
|
92
97
|
end
|
93
98
|
|
94
99
|
end
|
@@ -2,18 +2,20 @@ module Vop
|
|
2
2
|
|
3
3
|
module EntitySyntax
|
4
4
|
|
5
|
+
def description(s)
|
6
|
+
@entity.description = s
|
7
|
+
end
|
8
|
+
|
5
9
|
def key(key)
|
6
10
|
@entity.key = key
|
7
11
|
end
|
8
12
|
|
9
13
|
def entity(options = { key: "name" }, &block)
|
10
|
-
|
11
|
-
run(&block)
|
12
|
-
end
|
14
|
+
run(&block)
|
13
15
|
end
|
14
16
|
|
15
17
|
def run(&block)
|
16
|
-
@entity.block = block
|
18
|
+
@entity.block = block if block
|
17
19
|
end
|
18
20
|
|
19
21
|
def on(other_entity)
|
@@ -26,8 +28,21 @@ module Vop
|
|
26
28
|
|
27
29
|
raise "unknown keyword #{options.keys.first}" if options.keys.length > 0
|
28
30
|
|
29
|
-
@entity.show_options[:columns] = column_options
|
30
|
-
@entity.show_options[:display_type] = display_type
|
31
|
+
@entity.show_options[:columns] = column_options if column_options
|
32
|
+
@entity.show_options[:display_type] = display_type if display_type
|
33
|
+
end
|
34
|
+
|
35
|
+
def invalidate(&block)
|
36
|
+
@entity.invalidation_block = block
|
37
|
+
end
|
38
|
+
|
39
|
+
def contribute(options, &block)
|
40
|
+
raise "missing option 'to'" unless options.has_key?(:to)
|
41
|
+
@op.register_contributor(
|
42
|
+
command_name: options[:to],
|
43
|
+
contributor: @entity.name.to_s.carefully_pluralize
|
44
|
+
)
|
45
|
+
run(&block)
|
31
46
|
end
|
32
47
|
|
33
48
|
end
|
@@ -42,6 +42,12 @@ module Vop
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
# TODO: support version requirements
|
46
|
+
def depends_on_gem(gem, **options)
|
47
|
+
$logger.debug "plugin #{@plugin.name} depends on gem #{gem}"
|
48
|
+
@plugin.external_dependencies[:gem] << [gem, options]
|
49
|
+
end
|
50
|
+
|
45
51
|
def on(hook_sym, &block)
|
46
52
|
@plugin.hook(hook_sym, &block)
|
47
53
|
end
|
data/lib/vop/util/pluralizer.rb
CHANGED
@@ -2,7 +2,7 @@ begin
|
|
2
2
|
require "active_support/inflector"
|
3
3
|
rescue Exception => e
|
4
4
|
message = "active_support inflector cannot be loaded - pluralization results may deviate : #{e.message}"
|
5
|
-
puts message
|
5
|
+
#puts message
|
6
6
|
end
|
7
7
|
|
8
8
|
module Vop
|
@@ -19,6 +19,14 @@ module Vop
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def carefully_singularize
|
23
|
+
begin
|
24
|
+
self.singularize
|
25
|
+
rescue
|
26
|
+
"#{self[0..-2]}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
end
|
23
31
|
|
24
32
|
end
|
data/lib/vop/version.rb
CHANGED