vop 0.3.0

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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +50 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +66 -0
  5. data/README.md +2 -0
  6. data/Rakefile +6 -0
  7. data/bin/vop.rb +28 -0
  8. data/bin/vop.sh +4 -0
  9. data/exe/vop +28 -0
  10. data/lib/vop.rb +242 -0
  11. data/lib/vop/command.rb +168 -0
  12. data/lib/vop/command_loader.rb +47 -0
  13. data/lib/vop/entity.rb +61 -0
  14. data/lib/vop/loader.rb +35 -0
  15. data/lib/vop/plugin.rb +141 -0
  16. data/lib/vop/plugin_loader.rb +88 -0
  17. data/lib/vop/plugins/core/commands/clear_context.rb +3 -0
  18. data/lib/vop/plugins/core/commands/collect_contributions.rb +31 -0
  19. data/lib/vop/plugins/core/commands/edit.rb +12 -0
  20. data/lib/vop/plugins/core/commands/help.rb +38 -0
  21. data/lib/vop/plugins/core/commands/identity.rb +4 -0
  22. data/lib/vop/plugins/core/commands/list_contributors.rb +8 -0
  23. data/lib/vop/plugins/core/commands/list_entities.rb +3 -0
  24. data/lib/vop/plugins/core/commands/pry.rb +9 -0
  25. data/lib/vop/plugins/core/commands/reset.rb +5 -0
  26. data/lib/vop/plugins/core/commands/show_context.rb +3 -0
  27. data/lib/vop/plugins/core/commands/source.rb +5 -0
  28. data/lib/vop/plugins/core/commands/system_call.rb +5 -0
  29. data/lib/vop/plugins/core/core.plugin +4 -0
  30. data/lib/vop/plugins/core/helpers/command_loader/command_syntax.rb +45 -0
  31. data/lib/vop/plugins/core/helpers/command_loader/contributions.rb +28 -0
  32. data/lib/vop/plugins/core/helpers/command_loader/entities.rb +57 -0
  33. data/lib/vop/plugins/core/helpers/helper.rb +3 -0
  34. data/lib/vop/plugins/core/helpers/plugin_loader/plugin_syntax.rb +0 -0
  35. data/lib/vop/plugins/meta/commands/add_search_path.rb +6 -0
  36. data/lib/vop/plugins/meta/commands/delete_plugin.rb +13 -0
  37. data/lib/vop/plugins/meta/commands/list_commands.rb +17 -0
  38. data/lib/vop/plugins/meta/commands/list_plugins.rb +8 -0
  39. data/lib/vop/plugins/meta/commands/new_command.rb +14 -0
  40. data/lib/vop/plugins/meta/commands/new_plugin.rb +25 -0
  41. data/lib/vop/plugins/meta/commands/show_search_path.rb +3 -0
  42. data/lib/vop/plugins/meta/commands/who_provides.rb +5 -0
  43. data/lib/vop/plugins/meta/meta.plugin +1 -0
  44. data/lib/vop/plugins/ssh/commands/scp.rb +11 -0
  45. data/lib/vop/plugins/ssh/commands/ssh.rb +19 -0
  46. data/lib/vop/plugins/ssh/ssh.plugin +1 -0
  47. data/lib/vop/shell.rb +52 -0
  48. data/lib/vop/shell/backend.rb +28 -0
  49. data/lib/vop/shell/base_shell.rb +112 -0
  50. data/lib/vop/shell/formatter.rb +46 -0
  51. data/lib/vop/shell/vop_shell_backend.rb +257 -0
  52. data/lib/vop/version.rb +3 -0
  53. data/vop.gemspec +31 -0
  54. metadata +223 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b5225000e9764e0e3a47151ecfbbd7cd02d58e58
4
+ data.tar.gz: 26bd6366f5abff2a055feb239d6f85e4aa1ddefd
5
+ SHA512:
6
+ metadata.gz: 40e2acbd8735da52baafb4c01a6df32b514573d8c8cb4490401132c199554a370c687e69a041f167363b25f7865f44e9f4e58bc2d1717243a8d0d3153165d60e
7
+ data.tar.gz: dfde831a155f30531cec4396eff46870ba9ba22fc622c3f9a9087732276187993c99a1dea045c3b0a42d0d15a1435ad5dff0dcbc0f1812ecb034e48beeb8066d
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ vop (0.3.0)
5
+ activesupport
6
+ docopt
7
+ net-scp
8
+ net-ssh
9
+ pry
10
+ terminal-table
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ activesupport (5.0.0.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (~> 0.7)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ coderay (1.1.1)
21
+ concurrent-ruby (1.0.2)
22
+ diff-lcs (1.2.5)
23
+ docopt (0.5.0)
24
+ i18n (0.7.0)
25
+ method_source (0.8.2)
26
+ minitest (5.10.1)
27
+ net-scp (1.2.1)
28
+ net-ssh (>= 2.6.5)
29
+ net-ssh (3.2.0)
30
+ pry (0.10.3)
31
+ coderay (~> 1.1.0)
32
+ method_source (~> 0.8.1)
33
+ slop (~> 3.4)
34
+ rake (11.3.0)
35
+ rspec (3.4.0)
36
+ rspec-core (~> 3.4.0)
37
+ rspec-expectations (~> 3.4.0)
38
+ rspec-mocks (~> 3.4.0)
39
+ rspec-core (3.4.1)
40
+ rspec-support (~> 3.4.0)
41
+ rspec-expectations (3.4.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.4.0)
44
+ rspec-mocks (3.4.0)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.4.0)
47
+ rspec-support (3.4.1)
48
+ slop (3.6.0)
49
+ terminal-table (1.7.3)
50
+ unicode-display_width (~> 1.1.1)
51
+ thread_safe (0.3.5)
52
+ tzinfo (1.2.2)
53
+ thread_safe (~> 0.1)
54
+ unicode-display_width (1.1.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ bundler (~> 1.10)
61
+ rake
62
+ rspec
63
+ vop!
64
+
65
+ BUNDLED WITH
66
+ 1.10.6
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # vop
2
+ new and improved, now with twice the vitamins!
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/vop.rb ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $: << File.join(Pathname.new(File.join(File.dirname(__FILE__), '..')).realpath, 'lib')
6
+
7
+ require 'vop/shell'
8
+ require 'docopt'
9
+ require 'pp'
10
+
11
+ begin
12
+ shell = Vop::Shell::setup()
13
+ if shell.options["--execute"]
14
+ last_response = shell.execute(shell.options["--execute"])
15
+ else
16
+ last_response = shell.run_cli
17
+ end
18
+
19
+ # TODO exit_status = last_response && last_response.status == Vop.Status::OK ? 0 : 1
20
+ exit 0
21
+ rescue => detail
22
+ if detail.is_a? Docopt::Exit
23
+ puts detail.message
24
+ else
25
+ $stderr.puts "error : #{detail.message}\n#{detail.backtrace[0..9].join("\n")}"
26
+ exit 42
27
+ end
28
+ end
data/bin/vop.sh ADDED
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+
3
+ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
4
+ ruby $DIR/vop.rb $*
data/exe/vop ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $: << File.join(Pathname.new(File.join(File.dirname(__FILE__), '..')).realpath, 'lib')
6
+
7
+ require 'vop/shell'
8
+ require 'docopt'
9
+ require 'pp'
10
+
11
+ begin
12
+ shell = Vop::Shell::setup()
13
+ if shell.options["--execute"]
14
+ last_response = shell.execute(shell.options["--execute"])
15
+ else
16
+ last_response = shell.run_cli
17
+ end
18
+
19
+ # TODO exit_status = last_response && last_response.status == Vop.Status::OK ? 0 : 1
20
+ exit 0
21
+ rescue => detail
22
+ if detail.is_a? Docopt::Exit
23
+ puts detail.message
24
+ else
25
+ $stderr.puts "error : #{detail.message}\n#{detail.backtrace[0..9].join("\n")}"
26
+ exit 42
27
+ end
28
+ end
data/lib/vop.rb ADDED
@@ -0,0 +1,242 @@
1
+ require 'pp'
2
+ require 'logger'
3
+ require 'pathname'
4
+
5
+ require 'vop/version'
6
+ require 'vop/plugin_loader'
7
+ require 'active_support/inflector'
8
+
9
+ module Vop
10
+
11
+ VOP_ROOT = Pathname.new(File.join(File.dirname(__FILE__), '..')).realpath
12
+ CORE_PLUGIN_PATH = Pathname.new(File.join(File.dirname(__FILE__), 'vop', 'plugins')).realpath
13
+ #CONFIG_PATH = '/etc/vop'
14
+ #PLUGIN_CONFIG_PATH = File.join(CONFIG_PATH, 'plugins.d')
15
+
16
+ class Vop
17
+
18
+ DEFAULTS = {
19
+ :search_path => [
20
+ File.join(VOP_ROOT, '..', 'plugins/standard'),
21
+ File.join(VOP_ROOT, '..', 'plugins/extended')
22
+ ],
23
+ :command_dir_name => 'commands',
24
+ :plugin_config => {
25
+
26
+ }
27
+ }
28
+
29
+ attr_reader :config
30
+
31
+ attr_reader :plugins
32
+ attr_reader :commands
33
+
34
+ def initialize(options = {})
35
+ at_exit {
36
+ self.shutdown
37
+ }
38
+
39
+ @version = ::Vop::VERSION
40
+
41
+ @config = DEFAULTS
42
+ @config.merge! options
43
+
44
+ $logger = Logger.new(STDOUT)
45
+ $logger.level = options['--verbose'] ? Logger::DEBUG : Logger::INFO
46
+
47
+ _reset
48
+
49
+ $logger.info "virtualop (#{@version}) init complete."
50
+ $logger.info "hello."
51
+ end
52
+
53
+ def _pry
54
+ binding.pry
55
+ end
56
+
57
+ def _reset
58
+ $logger.debug "loading..."
59
+
60
+ load_plugins
61
+
62
+ $logger.info "loaded #{@commands.size} commands from #{@plugins.size} plugins"
63
+ end
64
+
65
+ def _search_path
66
+ [ CORE_PLUGIN_PATH ] + config[:search_path]
67
+ end
68
+
69
+ def inspect
70
+ chunk_size = 25
71
+ plugin_string = @plugins.keys.sort[0..chunk_size-1].join(' ')
72
+ if @plugins.length > chunk_size
73
+ plugin_string += " + #{@plugins.length - chunk_size} more"
74
+ end
75
+ "vop #{@version} (#{plugin_string})"
76
+ end
77
+
78
+ def eat(command)
79
+ @commands[command.short_name] = command
80
+
81
+ self.class.send(:define_method, command.short_name) do |*args|
82
+ ruby_args = args.length > 0 ? args[0] : {}
83
+ self.execute(command.short_name, ruby_args)
84
+ end
85
+ end
86
+
87
+ def load_plugins
88
+ @plugins = {}
89
+ @commands = {}
90
+ @hooks = Hash.new { |h,k| h[k] = [] }
91
+
92
+ # step 1 : read plugins from all existing source dirs
93
+ candidates = _search_path
94
+ search_path = candidates.select { |path| File.exists? path }
95
+ search_path.each do |path|
96
+ PluginLoader.read(self, path)
97
+ end
98
+
99
+ # step 2 : activate plugins (in the right order)
100
+ ordered_plugins.each do |plugin|
101
+ plugin.init
102
+ end
103
+
104
+ # step 3 : expand entities
105
+ @plugins['core'].state[:entities].each do |entity|
106
+ entity_name = entity[:name]
107
+ entity_command = @commands[entity_name]
108
+ list_command_name = "list_#{entity_name.pluralize(42)}"
109
+ $logger.debug "generating #{list_command_name}"
110
+ list_command = Command.new(entity_command.plugin, list_command_name)
111
+
112
+ if entity[:options][:on]
113
+ list_command.params << {
114
+ :name => entity[:options][:on],
115
+ :multi => false,
116
+ :mandatory => true,
117
+ :default_param => true
118
+ }
119
+ end
120
+ list_command.block = entity_command.param(entity[:key])[:lookup]
121
+ eat(list_command)
122
+ # TODO add pseudo source code so that `source <list_command_name>` works
123
+ end
124
+
125
+ # TODO add pre-flight hook so that plugins can attach logic to execute here
126
+ end
127
+
128
+ def resolve(plugin, resolved, unresolved, level = 0)
129
+ unresolved << plugin.name
130
+
131
+ plugin.dependencies.each do |dep|
132
+ unless resolved.include? dep
133
+ if unresolved.include? dep
134
+ raise "running in circles #{plugin.name} -> #{dep}"
135
+ else
136
+ unless @plugins.has_key? dep
137
+ raise "missing dependency: #{plugin.name} depends on #{dep}"
138
+ end
139
+ dependency = @plugins[dep]
140
+ resolve(dependency, resolved, unresolved, level + 1)
141
+ end
142
+ end
143
+ end
144
+ resolved << plugin.name
145
+ end
146
+
147
+ def ordered_plugins
148
+ root_plugin = Plugin.new(self, '__root__', nil)
149
+ @plugins.values.each do |plugin|
150
+ root_plugin.dependencies << plugin.name
151
+ end
152
+ resolved = []
153
+ unresolved = []
154
+
155
+ resolve(root_plugin, resolved, unresolved)
156
+ resolved.delete_if { |x| x == root_plugin.name }
157
+
158
+ resolved.map { |x| @plugins[x] }
159
+ end
160
+
161
+ def command(name)
162
+ unless commands.has_key?(name)
163
+ raise "no such command : #{name}"
164
+ end
165
+
166
+ commands[name]
167
+ end
168
+
169
+ def core
170
+ @plugins['core']
171
+ end
172
+
173
+ def hook(name, plugin_name)
174
+ @hooks[name] << plugin_name
175
+ end
176
+
177
+ def call_hook(name, *payload)
178
+ @hooks[name].each do |plugin_name, block|
179
+ @plugins[plugin_name].call_hook(name, payload)
180
+ end
181
+ end
182
+
183
+ def before_execute(request)
184
+ #puts ">> #{request.command_name} #{request.param_values.keys}"
185
+ call_hook :before_execute, request
186
+ end
187
+
188
+ def after_execute(request, response)
189
+ #puts "<< #{request.command_name} #{response.result}"
190
+ call_hook :after_execute, request, response
191
+ end
192
+
193
+ def execute(command_name, param_values, extra = {})
194
+ request = Request.new(command_name, param_values, extra)
195
+ before_execute(request)
196
+
197
+ (result, context) = execute_command(command_name, param_values, extra)
198
+
199
+ response = Response.new(result, context)
200
+ after_execute(request, response)
201
+
202
+ result
203
+ end
204
+
205
+ def execute_command(command_name, param_values, extra = {})
206
+ $logger.debug "+++ #{command_name} +++"
207
+ command = @commands[command_name]
208
+
209
+ command.execute(param_values, extra)
210
+ end
211
+
212
+ def shutdown()
213
+ $logger.debug "shutting down..."
214
+ end
215
+
216
+ end
217
+
218
+ class Request
219
+
220
+ attr_reader :command_name, :param_values
221
+
222
+ def initialize(command_name, param_values, extra = {})
223
+ @command_name = command_name
224
+ @param_values = param_values
225
+ # fuck extra
226
+ end
227
+
228
+ end
229
+
230
+ class Response
231
+
232
+ attr_reader :result
233
+
234
+ def initialize(result, context)
235
+ @result = result
236
+ @context = context
237
+ end
238
+
239
+ end
240
+
241
+
242
+ end