overman 0.0.1 → 0.87.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -0
  3. data/bin/foreman-runner +41 -0
  4. data/bin/overman +7 -0
  5. data/data/example/Procfile +4 -0
  6. data/data/example/Procfile.without_colon +2 -0
  7. data/data/example/error +7 -0
  8. data/data/example/log/neverdie.log +4 -0
  9. data/data/example/spawnee +14 -0
  10. data/data/example/spawner +7 -0
  11. data/data/example/ticker +14 -0
  12. data/data/example/utf8 +11 -0
  13. data/data/export/bluepill/master.pill.erb +28 -0
  14. data/data/export/daemon/master.conf.erb +14 -0
  15. data/data/export/daemon/process.conf.erb +8 -0
  16. data/data/export/daemon/process_master.conf.erb +2 -0
  17. data/data/export/launchd/launchd.plist.erb +33 -0
  18. data/data/export/runit/log/run.erb +7 -0
  19. data/data/export/runit/run.erb +4 -0
  20. data/data/export/supervisord/app.conf.erb +31 -0
  21. data/data/export/systemd/master.target.erb +5 -0
  22. data/data/export/systemd/process.service.erb +21 -0
  23. data/data/export/upstart/master.conf.erb +2 -0
  24. data/data/export/upstart/process.conf.erb +15 -0
  25. data/data/export/upstart/process_master.conf.erb +2 -0
  26. data/lib/foreman/cli.rb +162 -0
  27. data/lib/foreman/distribution.rb +9 -0
  28. data/lib/foreman/engine/cli.rb +105 -0
  29. data/lib/foreman/engine.rb +494 -0
  30. data/lib/foreman/env.rb +29 -0
  31. data/lib/foreman/export/base.rb +171 -0
  32. data/lib/foreman/export/bluepill.rb +12 -0
  33. data/lib/foreman/export/daemon.rb +28 -0
  34. data/lib/foreman/export/inittab.rb +42 -0
  35. data/lib/foreman/export/launchd.rb +22 -0
  36. data/lib/foreman/export/runit.rb +34 -0
  37. data/lib/foreman/export/supervisord.rb +16 -0
  38. data/lib/foreman/export/systemd.rb +34 -0
  39. data/lib/foreman/export/upstart.rb +46 -0
  40. data/lib/foreman/export.rb +36 -0
  41. data/lib/foreman/helpers.rb +45 -0
  42. data/lib/foreman/process.rb +81 -0
  43. data/lib/foreman/procfile.rb +94 -0
  44. data/lib/foreman/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  45. data/lib/foreman/vendor/thor/lib/thor/actions/create_link.rb +59 -0
  46. data/lib/foreman/vendor/thor/lib/thor/actions/directory.rb +118 -0
  47. data/lib/foreman/vendor/thor/lib/thor/actions/empty_directory.rb +135 -0
  48. data/lib/foreman/vendor/thor/lib/thor/actions/file_manipulation.rb +327 -0
  49. data/lib/foreman/vendor/thor/lib/thor/actions/inject_into_file.rb +103 -0
  50. data/lib/foreman/vendor/thor/lib/thor/actions.rb +318 -0
  51. data/lib/foreman/vendor/thor/lib/thor/base.rb +656 -0
  52. data/lib/foreman/vendor/thor/lib/thor/command.rb +133 -0
  53. data/lib/foreman/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +85 -0
  54. data/lib/foreman/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
  55. data/lib/foreman/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
  56. data/lib/foreman/vendor/thor/lib/thor/error.rb +32 -0
  57. data/lib/foreman/vendor/thor/lib/thor/group.rb +281 -0
  58. data/lib/foreman/vendor/thor/lib/thor/invocation.rb +177 -0
  59. data/lib/foreman/vendor/thor/lib/thor/line_editor/basic.rb +35 -0
  60. data/lib/foreman/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  61. data/lib/foreman/vendor/thor/lib/thor/line_editor.rb +17 -0
  62. data/lib/foreman/vendor/thor/lib/thor/parser/argument.rb +70 -0
  63. data/lib/foreman/vendor/thor/lib/thor/parser/arguments.rb +175 -0
  64. data/lib/foreman/vendor/thor/lib/thor/parser/option.rb +146 -0
  65. data/lib/foreman/vendor/thor/lib/thor/parser/options.rb +220 -0
  66. data/lib/foreman/vendor/thor/lib/thor/parser.rb +4 -0
  67. data/lib/foreman/vendor/thor/lib/thor/rake_compat.rb +71 -0
  68. data/lib/foreman/vendor/thor/lib/thor/runner.rb +322 -0
  69. data/lib/foreman/vendor/thor/lib/thor/shell/basic.rb +436 -0
  70. data/lib/foreman/vendor/thor/lib/thor/shell/color.rb +149 -0
  71. data/lib/foreman/vendor/thor/lib/thor/shell/html.rb +126 -0
  72. data/lib/foreman/vendor/thor/lib/thor/shell.rb +81 -0
  73. data/lib/foreman/vendor/thor/lib/thor/util.rb +268 -0
  74. data/lib/foreman/vendor/thor/lib/thor/version.rb +3 -0
  75. data/lib/foreman/vendor/thor/lib/thor.rb +492 -0
  76. data/lib/foreman/version.rb +5 -0
  77. data/lib/foreman.rb +17 -0
  78. data/man/overman.1 +284 -0
  79. data/spec/foreman/cli_spec.rb +111 -0
  80. data/spec/foreman/engine_spec.rb +114 -0
  81. data/spec/foreman/export/base_spec.rb +19 -0
  82. data/spec/foreman/export/bluepill_spec.rb +37 -0
  83. data/spec/foreman/export/daemon_spec.rb +97 -0
  84. data/spec/foreman/export/inittab_spec.rb +40 -0
  85. data/spec/foreman/export/launchd_spec.rb +31 -0
  86. data/spec/foreman/export/runit_spec.rb +36 -0
  87. data/spec/foreman/export/supervisord_spec.rb +38 -0
  88. data/spec/foreman/export/systemd_spec.rb +155 -0
  89. data/spec/foreman/export/upstart_spec.rb +118 -0
  90. data/spec/foreman/export_spec.rb +24 -0
  91. data/spec/foreman/helpers_spec.rb +26 -0
  92. data/spec/foreman/process_spec.rb +71 -0
  93. data/spec/foreman/procfile_spec.rb +57 -0
  94. data/spec/foreman_spec.rb +16 -0
  95. data/spec/helper_spec.rb +19 -0
  96. data/spec/resources/Procfile +5 -0
  97. data/spec/resources/Procfile.bad +2 -0
  98. data/spec/resources/bin/echo +2 -0
  99. data/spec/resources/bin/env +2 -0
  100. data/spec/resources/bin/test +2 -0
  101. data/spec/resources/bin/utf8 +2 -0
  102. data/spec/resources/export/bluepill/app-concurrency.pill +49 -0
  103. data/spec/resources/export/bluepill/app.pill +81 -0
  104. data/spec/resources/export/daemon/app-alpha-1.conf +7 -0
  105. data/spec/resources/export/daemon/app-alpha-2.conf +7 -0
  106. data/spec/resources/export/daemon/app-alpha.conf +2 -0
  107. data/spec/resources/export/daemon/app-bravo-1.conf +7 -0
  108. data/spec/resources/export/daemon/app-bravo.conf +2 -0
  109. data/spec/resources/export/daemon/app.conf +14 -0
  110. data/spec/resources/export/inittab/inittab.concurrency +4 -0
  111. data/spec/resources/export/inittab/inittab.default +6 -0
  112. data/spec/resources/export/launchd/launchd-a.default +29 -0
  113. data/spec/resources/export/launchd/launchd-b.default +29 -0
  114. data/spec/resources/export/launchd/launchd-c.default +30 -0
  115. data/spec/resources/export/runit/app-alpha-1/log/run +7 -0
  116. data/spec/resources/export/runit/app-alpha-1/run +4 -0
  117. data/spec/resources/export/runit/app-alpha-2/log/run +7 -0
  118. data/spec/resources/export/runit/app-alpha-2/run +4 -0
  119. data/spec/resources/export/runit/app-bravo-1/log/run +7 -0
  120. data/spec/resources/export/runit/app-bravo-1/run +4 -0
  121. data/spec/resources/export/supervisord/app-alpha-1.conf +42 -0
  122. data/spec/resources/export/supervisord/app-alpha-2.conf +22 -0
  123. data/spec/resources/export/systemd/app-alpha.1.service +18 -0
  124. data/spec/resources/export/systemd/app-alpha.2.service +18 -0
  125. data/spec/resources/export/systemd/app-alpha.target +2 -0
  126. data/spec/resources/export/systemd/app-bravo.1.service +18 -0
  127. data/spec/resources/export/systemd/app-bravo.target +2 -0
  128. data/spec/resources/export/systemd/app.target +5 -0
  129. data/spec/resources/export/upstart/app-alpha-1.conf +11 -0
  130. data/spec/resources/export/upstart/app-alpha-2.conf +11 -0
  131. data/spec/resources/export/upstart/app-alpha.conf +2 -0
  132. data/spec/resources/export/upstart/app-bravo-1.conf +11 -0
  133. data/spec/resources/export/upstart/app-bravo.conf +2 -0
  134. data/spec/resources/export/upstart/app.conf +2 -0
  135. data/spec/spec_helper.rb +177 -0
  136. metadata +147 -16
  137. data/lib/overman/version.rb +0 -5
  138. data/lib/overman.rb +0 -1
@@ -0,0 +1,492 @@
1
+ require "set"
2
+ require "foreman/vendor/thor/lib/thor/base"
3
+
4
+ class Foreman::Thor
5
+ class << self
6
+ # Allows for custom "Command" package naming.
7
+ #
8
+ # === Parameters
9
+ # name<String>
10
+ # options<Hash>
11
+ #
12
+ def package_name(name, _ = {})
13
+ @package_name = name.nil? || name == "" ? nil : name
14
+ end
15
+
16
+ # Sets the default command when thor is executed without an explicit command to be called.
17
+ #
18
+ # ==== Parameters
19
+ # meth<Symbol>:: name of the default command
20
+ #
21
+ def default_command(meth = nil)
22
+ if meth
23
+ @default_command = meth == :none ? "help" : meth.to_s
24
+ else
25
+ @default_command ||= from_superclass(:default_command, "help")
26
+ end
27
+ end
28
+ alias_method :default_task, :default_command
29
+
30
+ # Registers another Foreman::Thor subclass as a command.
31
+ #
32
+ # ==== Parameters
33
+ # klass<Class>:: Foreman::Thor subclass to register
34
+ # command<String>:: Subcommand name to use
35
+ # usage<String>:: Short usage for the subcommand
36
+ # description<String>:: Description for the subcommand
37
+ def register(klass, subcommand_name, usage, description, options = {})
38
+ if klass <= Foreman::Thor::Group
39
+ desc usage, description, options
40
+ define_method(subcommand_name) { |*args| invoke(klass, args) }
41
+ else
42
+ desc usage, description, options
43
+ subcommand subcommand_name, klass
44
+ end
45
+ end
46
+
47
+ # Defines the usage and the description of the next command.
48
+ #
49
+ # ==== Parameters
50
+ # usage<String>
51
+ # description<String>
52
+ # options<String>
53
+ #
54
+ def desc(usage, description, options = {})
55
+ if options[:for]
56
+ command = find_and_refresh_command(options[:for])
57
+ command.usage = usage if usage
58
+ command.description = description if description
59
+ else
60
+ @usage = usage
61
+ @desc = description
62
+ @hide = options[:hide] || false
63
+ end
64
+ end
65
+
66
+ # Defines the long description of the next command.
67
+ #
68
+ # ==== Parameters
69
+ # long description<String>
70
+ #
71
+ def long_desc(long_description, options = {})
72
+ if options[:for]
73
+ command = find_and_refresh_command(options[:for])
74
+ command.long_description = long_description if long_description
75
+ else
76
+ @long_desc = long_description
77
+ end
78
+ end
79
+
80
+ # Maps an input to a command. If you define:
81
+ #
82
+ # map "-T" => "list"
83
+ #
84
+ # Running:
85
+ #
86
+ # thor -T
87
+ #
88
+ # Will invoke the list command.
89
+ #
90
+ # ==== Parameters
91
+ # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
92
+ #
93
+ def map(mappings = nil)
94
+ @map ||= from_superclass(:map, {})
95
+
96
+ if mappings
97
+ mappings.each do |key, value|
98
+ if key.respond_to?(:each)
99
+ key.each { |subkey| @map[subkey] = value }
100
+ else
101
+ @map[key] = value
102
+ end
103
+ end
104
+ end
105
+
106
+ @map
107
+ end
108
+
109
+ # Declares the options for the next command to be declared.
110
+ #
111
+ # ==== Parameters
112
+ # Hash[Symbol => Object]:: The hash key is the name of the option and the value
113
+ # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric
114
+ # or :required (string). If you give a value, the type of the value is used.
115
+ #
116
+ def method_options(options = nil)
117
+ @method_options ||= {}
118
+ build_options(options, @method_options) if options
119
+ @method_options
120
+ end
121
+
122
+ alias_method :options, :method_options
123
+
124
+ # Adds an option to the set of method options. If :for is given as option,
125
+ # it allows you to change the options from a previous defined command.
126
+ #
127
+ # def previous_command
128
+ # # magic
129
+ # end
130
+ #
131
+ # method_option :foo => :bar, :for => :previous_command
132
+ #
133
+ # def next_command
134
+ # # magic
135
+ # end
136
+ #
137
+ # ==== Parameters
138
+ # name<Symbol>:: The name of the argument.
139
+ # options<Hash>:: Described below.
140
+ #
141
+ # ==== Options
142
+ # :desc - Description for the argument.
143
+ # :required - If the argument is required or not.
144
+ # :default - Default value for this argument. It cannot be required and have default values.
145
+ # :aliases - Aliases for this option.
146
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
147
+ # :banner - String to show on usage notes.
148
+ # :hide - If you want to hide this option from the help.
149
+ #
150
+ def method_option(name, options = {})
151
+ scope = if options[:for]
152
+ find_and_refresh_command(options[:for]).options
153
+ else
154
+ method_options
155
+ end
156
+
157
+ build_option(name, options, scope)
158
+ end
159
+ alias_method :option, :method_option
160
+
161
+ def disable_class_options
162
+ @disable_class_options = true
163
+ end
164
+
165
+ # Prints help information for the given command.
166
+ #
167
+ # ==== Parameters
168
+ # shell<Foreman::Thor::Shell>
169
+ # command_name<String>
170
+ #
171
+ def command_help(shell, command_name)
172
+ meth = normalize_command_name(command_name)
173
+ command = all_commands[meth]
174
+ handle_no_command_error(meth) unless command
175
+
176
+ shell.say "Usage:"
177
+ shell.say " #{banner(command)}"
178
+ shell.say
179
+ class_options_help(shell, nil => command.options.values)
180
+ if command.long_description
181
+ shell.say "Description:"
182
+ shell.print_wrapped(command.long_description, :indent => 2)
183
+ else
184
+ shell.say command.description
185
+ end
186
+ end
187
+ alias_method :task_help, :command_help
188
+
189
+ # Prints help information for this class.
190
+ #
191
+ # ==== Parameters
192
+ # shell<Foreman::Thor::Shell>
193
+ #
194
+ def help(shell, subcommand = false)
195
+ list = printable_commands(true, subcommand)
196
+ Foreman::Thor::Util.thor_classes_in(self).each do |klass|
197
+ list += klass.printable_commands(false)
198
+ end
199
+ list.sort! { |a, b| a[0] <=> b[0] }
200
+
201
+ if defined?(@package_name) && @package_name
202
+ shell.say "#{@package_name} commands:"
203
+ else
204
+ shell.say "Commands:"
205
+ end
206
+
207
+ shell.print_table(list, :indent => 2, :truncate => true)
208
+ shell.say
209
+ class_options_help(shell)
210
+ end
211
+
212
+ # Returns commands ready to be printed.
213
+ def printable_commands(all = true, subcommand = false)
214
+ (all ? all_commands : commands).map do |_, command|
215
+ next if command.hidden?
216
+ item = []
217
+ item << banner(command, false, subcommand)
218
+ item << (command.description ? "# #{command.description.gsub(/\s+/m, ' ')}" : "")
219
+ item
220
+ end.compact
221
+ end
222
+ alias_method :printable_tasks, :printable_commands
223
+
224
+ def subcommands
225
+ @subcommands ||= from_superclass(:subcommands, [])
226
+ end
227
+ alias_method :subtasks, :subcommands
228
+
229
+ def subcommand_classes
230
+ @subcommand_classes ||= {}
231
+ end
232
+
233
+ def subcommand(subcommand, subcommand_class)
234
+ subcommands << subcommand.to_s
235
+ subcommand_class.subcommand_help subcommand
236
+ subcommand_classes[subcommand.to_s] = subcommand_class
237
+
238
+ define_method(subcommand) do |*args|
239
+ args, opts = Foreman::Thor::Arguments.split(args)
240
+ invoke_args = [args, opts, {:invoked_via_subcommand => true, :class_options => options}]
241
+ invoke_args.unshift "help" if opts.delete("--help") || opts.delete("-h")
242
+ invoke subcommand_class, *invoke_args
243
+ end
244
+ end
245
+ alias_method :subtask, :subcommand
246
+
247
+ # Extend check unknown options to accept a hash of conditions.
248
+ #
249
+ # === Parameters
250
+ # options<Hash>: A hash containing :only and/or :except keys
251
+ def check_unknown_options!(options = {})
252
+ @check_unknown_options ||= {}
253
+ options.each do |key, value|
254
+ if value
255
+ @check_unknown_options[key] = Array(value)
256
+ else
257
+ @check_unknown_options.delete(key)
258
+ end
259
+ end
260
+ @check_unknown_options
261
+ end
262
+
263
+ # Overwrite check_unknown_options? to take subcommands and options into account.
264
+ def check_unknown_options?(config) #:nodoc:
265
+ options = check_unknown_options
266
+ return false unless options
267
+
268
+ command = config[:current_command]
269
+ return true unless command
270
+
271
+ name = command.name
272
+
273
+ if subcommands.include?(name)
274
+ false
275
+ elsif options[:except]
276
+ !options[:except].include?(name.to_sym)
277
+ elsif options[:only]
278
+ options[:only].include?(name.to_sym)
279
+ else
280
+ true
281
+ end
282
+ end
283
+
284
+ # Stop parsing of options as soon as an unknown option or a regular
285
+ # argument is encountered. All remaining arguments are passed to the command.
286
+ # This is useful if you have a command that can receive arbitrary additional
287
+ # options, and where those additional options should not be handled by
288
+ # Foreman::Thor.
289
+ #
290
+ # ==== Example
291
+ #
292
+ # To better understand how this is useful, let's consider a command that calls
293
+ # an external command. A user may want to pass arbitrary options and
294
+ # arguments to that command. The command itself also accepts some options,
295
+ # which should be handled by Foreman::Thor.
296
+ #
297
+ # class_option "verbose", :type => :boolean
298
+ # stop_on_unknown_option! :exec
299
+ # check_unknown_options! :except => :exec
300
+ #
301
+ # desc "exec", "Run a shell command"
302
+ # def exec(*args)
303
+ # puts "diagnostic output" if options[:verbose]
304
+ # Kernel.exec(*args)
305
+ # end
306
+ #
307
+ # Here +exec+ can be called with +--verbose+ to get diagnostic output,
308
+ # e.g.:
309
+ #
310
+ # $ thor exec --verbose echo foo
311
+ # diagnostic output
312
+ # foo
313
+ #
314
+ # But if +--verbose+ is given after +echo+, it is passed to +echo+ instead:
315
+ #
316
+ # $ thor exec echo --verbose foo
317
+ # --verbose foo
318
+ #
319
+ # ==== Parameters
320
+ # Symbol ...:: A list of commands that should be affected.
321
+ def stop_on_unknown_option!(*command_names)
322
+ stop_on_unknown_option.merge(command_names)
323
+ end
324
+
325
+ def stop_on_unknown_option?(command) #:nodoc:
326
+ command && stop_on_unknown_option.include?(command.name.to_sym)
327
+ end
328
+
329
+ protected
330
+
331
+ def stop_on_unknown_option #:nodoc:
332
+ @stop_on_unknown_option ||= Set.new
333
+ end
334
+
335
+ # The method responsible for dispatching given the args.
336
+ def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength
337
+ meth ||= retrieve_command_name(given_args)
338
+ command = all_commands[normalize_command_name(meth)]
339
+
340
+ if !command && config[:invoked_via_subcommand]
341
+ # We're a subcommand and our first argument didn't match any of our
342
+ # commands. So we put it back and call our default command.
343
+ given_args.unshift(meth)
344
+ command = all_commands[normalize_command_name(default_command)]
345
+ end
346
+
347
+ if command
348
+ args, opts = Foreman::Thor::Options.split(given_args)
349
+ if stop_on_unknown_option?(command) && !args.empty?
350
+ # given_args starts with a non-option, so we treat everything as
351
+ # ordinary arguments
352
+ args.concat opts
353
+ opts.clear
354
+ end
355
+ else
356
+ args = given_args
357
+ opts = nil
358
+ command = dynamic_command_class.new(meth)
359
+ end
360
+
361
+ opts = given_opts || opts || []
362
+ config[:current_command] = command
363
+ config[:command_options] = command.options
364
+
365
+ instance = new(args, opts, config)
366
+ yield instance if block_given?
367
+ args = instance.args
368
+ trailing = args[Range.new(arguments.size, -1)]
369
+ instance.invoke_command(command, trailing || [])
370
+ end
371
+
372
+ # The banner for this class. You can customize it if you are invoking the
373
+ # thor class by another ways which is not the Foreman::Thor::Runner. It receives
374
+ # the command that is going to be invoked and a boolean which indicates if
375
+ # the namespace should be displayed as arguments.
376
+ #
377
+ def banner(command, namespace = nil, subcommand = false)
378
+ "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
379
+ end
380
+
381
+ def baseclass #:nodoc:
382
+ Foreman::Thor
383
+ end
384
+
385
+ def dynamic_command_class #:nodoc:
386
+ Foreman::Thor::DynamicCommand
387
+ end
388
+
389
+ def create_command(meth) #:nodoc:
390
+ @usage ||= nil
391
+ @desc ||= nil
392
+ @long_desc ||= nil
393
+ @disable_class_options ||= nil
394
+
395
+ if @usage && @desc
396
+ base_class = @hide ? Foreman::Thor::HiddenCommand : Foreman::Thor::Command
397
+ commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options, @disable_class_options)
398
+ @usage, @desc, @long_desc, @method_options, @hide, @disable_class_options = nil
399
+ true
400
+ elsif all_commands[meth] || meth == "method_missing"
401
+ true
402
+ else
403
+ puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " \
404
+ "Call desc if you want this method to be available as command or declare it inside a " \
405
+ "no_commands{} block. Invoked from #{caller[1].inspect}."
406
+ false
407
+ end
408
+ end
409
+ alias_method :create_task, :create_command
410
+
411
+ def initialize_added #:nodoc:
412
+ class_options.merge!(method_options)
413
+ @method_options = nil
414
+ end
415
+
416
+ # Retrieve the command name from given args.
417
+ def retrieve_command_name(args) #:nodoc:
418
+ meth = args.first.to_s unless args.empty?
419
+ args.shift if meth && (map[meth] || meth !~ /^\-/)
420
+ end
421
+ alias_method :retrieve_task_name, :retrieve_command_name
422
+
423
+ # receives a (possibly nil) command name and returns a name that is in
424
+ # the commands hash. In addition to normalizing aliases, this logic
425
+ # will determine if a shortened command is an unambiguous substring of
426
+ # a command or alias.
427
+ #
428
+ # +normalize_command_name+ also converts names like +animal-prison+
429
+ # into +animal_prison+.
430
+ def normalize_command_name(meth) #:nodoc:
431
+ return default_command.to_s.tr("-", "_") unless meth
432
+
433
+ possibilities = find_command_possibilities(meth)
434
+ raise AmbiguousTaskError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]" if possibilities.size > 1
435
+
436
+ if possibilities.empty?
437
+ meth ||= default_command
438
+ elsif map[meth]
439
+ meth = map[meth]
440
+ else
441
+ meth = possibilities.first
442
+ end
443
+
444
+ meth.to_s.tr("-", "_") # treat foo-bar as foo_bar
445
+ end
446
+ alias_method :normalize_task_name, :normalize_command_name
447
+
448
+ # this is the logic that takes the command name passed in by the user
449
+ # and determines whether it is an unambiguous substrings of a command or
450
+ # alias name.
451
+ def find_command_possibilities(meth)
452
+ len = meth.to_s.length
453
+ possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort
454
+ unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
455
+
456
+ if possibilities.include?(meth)
457
+ [meth]
458
+ elsif unique_possibilities.size == 1
459
+ unique_possibilities
460
+ else
461
+ possibilities
462
+ end
463
+ end
464
+ alias_method :find_task_possibilities, :find_command_possibilities
465
+
466
+ def subcommand_help(cmd)
467
+ desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
468
+ class_eval "
469
+ def help(command = nil, subcommand = true); super; end
470
+ "
471
+ end
472
+ alias_method :subtask_help, :subcommand_help
473
+ end
474
+
475
+ include Foreman::Thor::Base
476
+
477
+ map HELP_MAPPINGS => :help
478
+
479
+ desc "help [COMMAND]", "Describe available commands or one specific command"
480
+ disable_class_options
481
+ def help(command = nil, subcommand = false)
482
+ if command
483
+ if self.class.subcommands.include? command
484
+ self.class.subcommand_classes[command].help(shell, true)
485
+ else
486
+ self.class.command_help(shell, command)
487
+ end
488
+ else
489
+ self.class.help(shell, subcommand)
490
+ end
491
+ end
492
+ end
@@ -0,0 +1,5 @@
1
+ module Foreman
2
+
3
+ VERSION = "0.87.3"
4
+
5
+ end
data/lib/foreman.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "foreman/version"
2
+
3
+ module Foreman
4
+
5
+ def self.runner
6
+ File.expand_path("../../bin/foreman-runner", __FILE__)
7
+ end
8
+
9
+ def self.ruby_18?
10
+ defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
11
+ end
12
+
13
+ def self.windows?
14
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
15
+ end
16
+
17
+ end