engineyard 2.1.1 → 2.1.2

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.
@@ -1,4 +1,4 @@
1
1
  module EY
2
- VERSION = '2.1.1'
3
- ENGINEYARD_SERVERSIDE_VERSION = ENV['ENGINEYARD_SERVERSIDE_VERSION'] || '2.1.1'
2
+ VERSION = '2.1.2'
3
+ ENGINEYARD_SERVERSIDE_VERSION = ENV['ENGINEYARD_SERVERSIDE_VERSION'] || '2.1.3'
4
4
  end
@@ -1,4 +1,8 @@
1
+ [![Gem Version](https://badge.fury.io/rb/thor.png)](https://rubygems.org/gems/thor)
1
2
  [![Build Status](https://secure.travis-ci.org/wycats/thor.png?branch=master)](http://travis-ci.org/wycats/thor)
3
+ [![Dependency Status](https://gemnasium.com/wycats/thor.png?travis)](https://gemnasium.com/wycats/thor)
4
+ [![Code Climate](https://codeclimate.com/github/wycats/thor.png)](https://codeclimate.com/github/wycats/thor)
5
+ [![Coverage Status](https://coveralls.io/repos/wycats/thor/badge.png?branch=master)](https://coveralls.io/r/wycats/thor)
2
6
 
3
7
  Thor
4
8
  ====
@@ -19,10 +23,13 @@ Installation
19
23
 
20
24
  Usage and documentation
21
25
  -----------------------
22
- Please see [the wiki](https://github.com/wycats/thor/wiki) for basic usage and other documentation on using Thor.
26
+ Please see the [wiki][] for basic usage and other documentation on using Thor. You can also checkout the [official homepage][homepage].
27
+
28
+ [wiki]: https://github.com/wycats/thor/wiki
29
+ [homepage]: http://whatisthor.com/
23
30
 
24
31
  License
25
32
  -------
26
- Released under the MIT License. See the [LICENSE][license] file for further details.
33
+ Released under the MIT License. See the [LICENSE][] file for further details.
27
34
 
28
- [license]: https://github.com/wycats/thor/blob/master/LICENSE.md
35
+ [license]: LICENSE.md
@@ -1,22 +1,34 @@
1
+ require 'set'
1
2
  require 'thor/base'
2
3
 
3
4
  class Thor
4
5
  class << self
5
- # Sets the default task when thor is executed without an explicit task to be called.
6
+ # Allows for custom "Command" package naming.
7
+ #
8
+ # === Parameters
9
+ # name<String>
10
+ # options<Hash>
11
+ #
12
+ def package_name(name, options={})
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.
6
17
  #
7
18
  # ==== Parameters
8
- # meth<Symbol>:: name of the default task
9
- #
10
- def default_task(meth=nil)
11
- case meth
12
- when :none
13
- @default_task = 'help'
14
- when nil
15
- @default_task ||= from_superclass(:default_task, 'help')
16
- else
17
- @default_task = meth.to_s
19
+ # meth<Symbol>:: name of the default command
20
+ #
21
+ def default_command(meth=nil)
22
+ @default_command = case meth
23
+ when :none
24
+ 'help'
25
+ when nil
26
+ @default_command || from_superclass(:default_command, 'help')
27
+ else
28
+ meth.to_s
18
29
  end
19
30
  end
31
+ alias default_task default_command
20
32
 
21
33
  # Registers another Thor subclass as a command.
22
34
  #
@@ -35,7 +47,7 @@ class Thor
35
47
  end
36
48
  end
37
49
 
38
- # Defines the usage and the description of the next task.
50
+ # Defines the usage and the description of the next command.
39
51
  #
40
52
  # ==== Parameters
41
53
  # usage<String>
@@ -44,29 +56,29 @@ class Thor
44
56
  #
45
57
  def desc(usage, description, options={})
46
58
  if options[:for]
47
- task = find_and_refresh_task(options[:for])
48
- task.usage = usage if usage
49
- task.description = description if description
59
+ command = find_and_refresh_command(options[:for])
60
+ command.usage = usage if usage
61
+ command.description = description if description
50
62
  else
51
63
  @usage, @desc, @hide = usage, description, options[:hide] || false
52
64
  end
53
65
  end
54
66
 
55
- # Defines the long description of the next task.
67
+ # Defines the long description of the next command.
56
68
  #
57
69
  # ==== Parameters
58
70
  # long description<String>
59
71
  #
60
72
  def long_desc(long_description, options={})
61
73
  if options[:for]
62
- task = find_and_refresh_task(options[:for])
63
- task.long_description = long_description if long_description
74
+ command = find_and_refresh_command(options[:for])
75
+ command.long_description = long_description if long_description
64
76
  else
65
77
  @long_desc = long_description
66
78
  end
67
79
  end
68
80
 
69
- # Maps an input to a task. If you define:
81
+ # Maps an input to a command. If you define:
70
82
  #
71
83
  # map "-T" => "list"
72
84
  #
@@ -74,10 +86,10 @@ class Thor
74
86
  #
75
87
  # thor -T
76
88
  #
77
- # Will invoke the list task.
89
+ # Will invoke the list command.
78
90
  #
79
91
  # ==== Parameters
80
- # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task.
92
+ # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
81
93
  #
82
94
  def map(mappings=nil)
83
95
  @map ||= from_superclass(:map, {})
@@ -95,7 +107,7 @@ class Thor
95
107
  @map
96
108
  end
97
109
 
98
- # Declares the options for the next task to be declared.
110
+ # Declares the options for the next command to be declared.
99
111
  #
100
112
  # ==== Parameters
101
113
  # Hash[Symbol => Object]:: The hash key is the name of the option and the value
@@ -111,15 +123,15 @@ class Thor
111
123
  alias options method_options
112
124
 
113
125
  # Adds an option to the set of method options. If :for is given as option,
114
- # it allows you to change the options from a previous defined task.
126
+ # it allows you to change the options from a previous defined command.
115
127
  #
116
- # def previous_task
128
+ # def previous_command
117
129
  # # magic
118
130
  # end
119
131
  #
120
- # method_option :foo => :bar, :for => :previous_task
132
+ # method_option :foo => :bar, :for => :previous_command
121
133
  #
122
- # def next_task
134
+ # def next_command
123
135
  # # magic
124
136
  # end
125
137
  #
@@ -138,38 +150,38 @@ class Thor
138
150
  #
139
151
  def method_option(name, options={})
140
152
  scope = if options[:for]
141
- find_and_refresh_task(options[:for]).options
153
+ find_and_refresh_command(options[:for]).options
142
154
  else
143
155
  method_options
144
156
  end
145
157
 
146
158
  build_option(name, options, scope)
147
159
  end
148
-
149
160
  alias option method_option
150
161
 
151
- # Prints help information for the given task.
162
+ # Prints help information for the given command.
152
163
  #
153
164
  # ==== Parameters
154
165
  # shell<Thor::Shell>
155
- # task_name<String>
166
+ # command_name<String>
156
167
  #
157
- def task_help(shell, task_name)
158
- meth = normalize_task_name(task_name)
159
- task = all_tasks[meth]
160
- handle_no_task_error(meth) unless task
168
+ def command_help(shell, command_name)
169
+ meth = normalize_command_name(command_name)
170
+ command = all_commands[meth]
171
+ handle_no_command_error(meth) unless command
161
172
 
162
173
  shell.say "Usage:"
163
- shell.say " #{banner(task)}"
174
+ shell.say " #{banner(command)}"
164
175
  shell.say
165
- class_options_help(shell, nil => task.options.map { |_, o| o })
166
- if task.long_description
176
+ class_options_help(shell, nil => command.options.map { |_, o| o })
177
+ if command.long_description
167
178
  shell.say "Description:"
168
- shell.print_wrapped(task.long_description, :indent => 2)
179
+ shell.print_wrapped(command.long_description, :indent => 2)
169
180
  else
170
- shell.say task.description
181
+ shell.say command.description
171
182
  end
172
183
  end
184
+ alias task_help command_help
173
185
 
174
186
  # Prints help information for this class.
175
187
  #
@@ -177,32 +189,39 @@ class Thor
177
189
  # shell<Thor::Shell>
178
190
  #
179
191
  def help(shell, subcommand = false)
180
- list = printable_tasks(true, subcommand)
192
+ list = printable_commands(true, subcommand)
181
193
  Thor::Util.thor_classes_in(self).each do |klass|
182
- list += klass.printable_tasks(false)
194
+ list += klass.printable_commands(false)
183
195
  end
184
196
  list.sort!{ |a,b| a[0] <=> b[0] }
185
197
 
186
- shell.say "Tasks:"
198
+ if @package_name
199
+ shell.say "#{@package_name} commands:"
200
+ else
201
+ shell.say "Commands:"
202
+ end
203
+
187
204
  shell.print_table(list, :indent => 2, :truncate => true)
188
205
  shell.say
189
206
  class_options_help(shell)
190
207
  end
191
208
 
192
- # Returns tasks ready to be printed.
193
- def printable_tasks(all = true, subcommand = false)
194
- (all ? all_tasks : tasks).map do |_, task|
195
- next if task.hidden?
209
+ # Returns commands ready to be printed.
210
+ def printable_commands(all = true, subcommand = false)
211
+ (all ? all_commands : commands).map do |_, command|
212
+ next if command.hidden?
196
213
  item = []
197
- item << banner(task, false, subcommand)
198
- item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "")
214
+ item << banner(command, false, subcommand)
215
+ item << (command.description ? "# #{command.description.gsub(/\s+/m,' ')}" : "")
199
216
  item
200
217
  end.compact
201
218
  end
219
+ alias printable_tasks printable_commands
202
220
 
203
221
  def subcommands
204
222
  @subcommands ||= from_superclass(:subcommands, [])
205
223
  end
224
+ alias subtasks subcommands
206
225
 
207
226
  def subcommand(subcommand, subcommand_class)
208
227
  self.subcommands << subcommand.to_s
@@ -210,9 +229,10 @@ class Thor
210
229
 
211
230
  define_method(subcommand) do |*args|
212
231
  args, opts = Thor::Arguments.split(args)
213
- invoke subcommand_class, args, opts
232
+ invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options
214
233
  end
215
234
  end
235
+ alias subtask subcommand
216
236
 
217
237
  # Extend check unknown options to accept a hash of conditions.
218
238
  #
@@ -235,10 +255,10 @@ class Thor
235
255
  options = check_unknown_options
236
256
  return false unless options
237
257
 
238
- task = config[:current_task]
239
- return true unless task
258
+ command = config[:current_command]
259
+ return true unless command
240
260
 
241
- name = task.name
261
+ name = command.name
242
262
 
243
263
  if subcommands.include?(name)
244
264
  false
@@ -251,129 +271,203 @@ class Thor
251
271
  end
252
272
  end
253
273
 
254
- protected
255
-
256
- # The method responsible for dispatching given the args.
257
- def dispatch(meth, given_args, given_opts, config) #:nodoc:
258
- meth ||= retrieve_task_name(given_args)
259
- task = all_tasks[normalize_task_name(meth)]
260
-
261
- if task
262
- args, opts = Thor::Options.split(given_args)
263
- else
264
- args, opts = given_args, nil
265
- task = Thor::DynamicTask.new(meth)
266
- end
274
+ # Stop parsing of options as soon as an unknown option or a regular
275
+ # argument is encountered. All remaining arguments are passed to the command.
276
+ # This is useful if you have a command that can receive arbitrary additional
277
+ # options, and where those additional options should not be handled by
278
+ # Thor.
279
+ #
280
+ # ==== Example
281
+ #
282
+ # To better understand how this is useful, let's consider a command that calls
283
+ # an external command. A user may want to pass arbitrary options and
284
+ # arguments to that command. The command itself also accepts some options,
285
+ # which should be handled by Thor.
286
+ #
287
+ # class_option "verbose", :type => :boolean
288
+ # stop_on_unknown_option! :exec
289
+ # check_unknown_options! :except => :exec
290
+ #
291
+ # desc "exec", "Run a shell command"
292
+ # def exec(*args)
293
+ # puts "diagnostic output" if options[:verbose]
294
+ # Kernel.exec(*args)
295
+ # end
296
+ #
297
+ # Here +exec+ can be called with +--verbose+ to get diagnostic output,
298
+ # e.g.:
299
+ #
300
+ # $ thor exec --verbose echo foo
301
+ # diagnostic output
302
+ # foo
303
+ #
304
+ # But if +--verbose+ is given after +echo+, it is passed to +echo+ instead:
305
+ #
306
+ # $ thor exec echo --verbose foo
307
+ # --verbose foo
308
+ #
309
+ # ==== Parameters
310
+ # Symbol ...:: A list of commands that should be affected.
311
+ def stop_on_unknown_option!(*command_names)
312
+ @stop_on_unknown_option ||= Set.new
313
+ @stop_on_unknown_option.merge(command_names)
314
+ end
267
315
 
268
- opts = given_opts || opts || []
269
- config.merge!(:current_task => task, :task_options => task.options)
316
+ def stop_on_unknown_option?(command) #:nodoc:
317
+ !!@stop_on_unknown_option && @stop_on_unknown_option.include?(command.name.to_sym)
318
+ end
270
319
 
271
- instance = new(args, opts, config)
272
- yield instance if block_given?
273
- args = instance.args
274
- trailing = args[Range.new(arguments.size, -1)]
275
- instance.invoke_task(task, trailing || [])
320
+ protected
321
+
322
+ # The method responsible for dispatching given the args.
323
+ def dispatch(meth, given_args, given_opts, config) #:nodoc:
324
+ # There is an edge case when dispatching from a subcommand.
325
+ # A problem occurs invoking the default command. This case occurs
326
+ # when arguments are passed and a default command is defined, and
327
+ # the first given_args does not match the default command.
328
+ # Thor use "help" by default so we skip that case.
329
+ # Note the call to retrieve_command_name. It's called with
330
+ # given_args.dup since that method calls args.shift. Then lookup
331
+ # the command normally. If the first item in given_args is not
332
+ # a command then use the default command. The given_args will be
333
+ # intact later since dup was used.
334
+ if config[:invoked_via_subcommand] && given_args.size >= 1 && default_command != "help" && given_args.first != default_command
335
+ meth ||= retrieve_command_name(given_args.dup)
336
+ command = all_commands[normalize_command_name(meth)]
337
+ command ||= all_commands[normalize_command_name(default_command)]
338
+ else
339
+ meth ||= retrieve_command_name(given_args)
340
+ command = all_commands[normalize_command_name(meth)]
276
341
  end
277
342
 
278
- # The banner for this class. You can customize it if you are invoking the
279
- # thor class by another ways which is not the Thor::Runner. It receives
280
- # the task that is going to be invoked and a boolean which indicates if
281
- # the namespace should be displayed as arguments.
282
- #
283
- def banner(task, namespace = nil, subcommand = false)
284
- "#{basename} #{task.formatted_usage(self, $thor_runner, subcommand)}"
343
+ if command
344
+ args, opts = Thor::Options.split(given_args)
345
+ if stop_on_unknown_option?(command) && !args.empty?
346
+ # given_args starts with a non-option, so we treat everything as
347
+ # ordinary arguments
348
+ args.concat opts
349
+ opts.clear
350
+ end
351
+ else
352
+ args, opts = given_args, nil
353
+ command = Thor::DynamicCommand.new(meth)
285
354
  end
286
355
 
287
- def baseclass #:nodoc:
288
- Thor
289
- end
356
+ opts = given_opts || opts || []
357
+ config.merge!(:current_command => command, :command_options => command.options)
290
358
 
291
- def create_task(meth) #:nodoc:
292
- if @usage && @desc
293
- base_class = @hide ? Thor::HiddenTask : Thor::Task
294
- tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
295
- @usage, @desc, @long_desc, @method_options, @hide = nil
296
- true
297
- elsif self.all_tasks[meth] || meth == "method_missing"
298
- true
299
- else
300
- puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
301
- "Call desc if you want this method to be available as task or declare it inside a " <<
302
- "no_tasks{} block. Invoked from #{caller[1].inspect}."
303
- false
304
- end
305
- end
359
+ instance = new(args, opts, config)
360
+ yield instance if block_given?
361
+ args = instance.args
362
+ trailing = args[Range.new(arguments.size, -1)]
363
+ instance.invoke_command(command, trailing || [])
364
+ end
306
365
 
307
- def initialize_added #:nodoc:
308
- class_options.merge!(method_options)
309
- @method_options = nil
310
- end
366
+ # The banner for this class. You can customize it if you are invoking the
367
+ # thor class by another ways which is not the Thor::Runner. It receives
368
+ # the command that is going to be invoked and a boolean which indicates if
369
+ # the namespace should be displayed as arguments.
370
+ #
371
+ def banner(command, namespace = nil, subcommand = false)
372
+ "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
373
+ end
311
374
 
312
- # Retrieve the task name from given args.
313
- def retrieve_task_name(args) #:nodoc:
314
- meth = args.first.to_s unless args.empty?
315
- if meth && (map[meth] || meth !~ /^\-/)
316
- args.shift
317
- else
318
- nil
319
- end
375
+ def baseclass #:nodoc:
376
+ Thor
377
+ end
378
+
379
+ def create_command(meth) #:nodoc:
380
+ if @usage && @desc
381
+ base_class = @hide ? Thor::HiddenCommand : Thor::Command
382
+ commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
383
+ @usage, @desc, @long_desc, @method_options, @hide = nil
384
+ true
385
+ elsif self.all_commands[meth] || meth == "method_missing"
386
+ true
387
+ else
388
+ puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " <<
389
+ "Call desc if you want this method to be available as command or declare it inside a " <<
390
+ "no_commands{} block. Invoked from #{caller[1].inspect}."
391
+ false
320
392
  end
393
+ end
394
+ alias create_task create_command
321
395
 
322
- # receives a (possibly nil) task name and returns a name that is in
323
- # the tasks hash. In addition to normalizing aliases, this logic
324
- # will determine if a shortened command is an unambiguous substring of
325
- # a task or alias.
326
- #
327
- # +normalize_task_name+ also converts names like +animal-prison+
328
- # into +animal_prison+.
329
- def normalize_task_name(meth) #:nodoc:
330
- return default_task.to_s.gsub('-', '_') unless meth
331
-
332
- possibilities = find_task_possibilities(meth)
333
- if possibilities.size > 1
334
- raise ArgumentError, "Ambiguous task #{meth} matches [#{possibilities.join(', ')}]"
335
- elsif possibilities.size < 1
336
- meth = meth || default_task
337
- elsif map[meth]
338
- meth = map[meth]
339
- else
340
- meth = possibilities.first
341
- end
396
+ def initialize_added #:nodoc:
397
+ class_options.merge!(method_options)
398
+ @method_options = nil
399
+ end
342
400
 
343
- meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
401
+ # Retrieve the command name from given args.
402
+ def retrieve_command_name(args) #:nodoc:
403
+ meth = args.first.to_s unless args.empty?
404
+ if meth && (map[meth] || meth !~ /^\-/)
405
+ args.shift
406
+ else
407
+ nil
344
408
  end
409
+ end
410
+ alias retrieve_task_name retrieve_command_name
345
411
 
346
- # this is the logic that takes the task name passed in by the user
347
- # and determines whether it is an unambiguous substrings of a task or
348
- # alias name.
349
- def find_task_possibilities(meth)
350
- len = meth.to_s.length
351
- possibilities = all_tasks.merge(map).keys.select { |n| meth == n[0, len] }.sort
352
- unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
353
-
354
- if possibilities.include?(meth)
355
- [meth]
356
- elsif unique_possibilities.size == 1
357
- unique_possibilities
358
- else
359
- possibilities
360
- end
412
+ # receives a (possibly nil) command name and returns a name that is in
413
+ # the commands hash. In addition to normalizing aliases, this logic
414
+ # will determine if a shortened command is an unambiguous substring of
415
+ # a command or alias.
416
+ #
417
+ # +normalize_command_name+ also converts names like +animal-prison+
418
+ # into +animal_prison+.
419
+ def normalize_command_name(meth) #:nodoc:
420
+ return default_command.to_s.gsub('-', '_') unless meth
421
+
422
+ possibilities = find_command_possibilities(meth)
423
+ if possibilities.size > 1
424
+ raise ArgumentError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
425
+ elsif possibilities.size < 1
426
+ meth = meth || default_command
427
+ elsif map[meth]
428
+ meth = map[meth]
429
+ else
430
+ meth = possibilities.first
361
431
  end
362
432
 
363
- def subcommand_help(cmd)
364
- desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
365
- class_eval <<-RUBY
366
- def help(task = nil, subcommand = true); super; end
367
- RUBY
433
+ meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
434
+ end
435
+ alias normalize_task_name normalize_command_name
436
+
437
+ # this is the logic that takes the command name passed in by the user
438
+ # and determines whether it is an unambiguous substrings of a command or
439
+ # alias name.
440
+ def find_command_possibilities(meth)
441
+ len = meth.to_s.length
442
+ possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort
443
+ unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
444
+
445
+ if possibilities.include?(meth)
446
+ [meth]
447
+ elsif unique_possibilities.size == 1
448
+ unique_possibilities
449
+ else
450
+ possibilities
368
451
  end
452
+ end
453
+ alias find_task_possibilities find_command_possibilities
454
+
455
+ def subcommand_help(cmd)
456
+ desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
457
+ class_eval <<-RUBY
458
+ def help(command = nil, subcommand = true); super; end
459
+ RUBY
460
+ end
461
+ alias subtask_help subcommand_help
462
+
369
463
  end
370
464
 
371
465
  include Thor::Base
372
466
 
373
467
  map HELP_MAPPINGS => :help
374
468
 
375
- desc "help [TASK]", "Describe available tasks or one specific task"
376
- def help(task = nil, subcommand = false)
377
- task ? self.class.task_help(shell, task) : self.class.help(shell, subcommand)
469
+ desc "help [COMMAND]", "Describe available commands or one specific command"
470
+ def help(command = nil, subcommand = false)
471
+ command ? self.class.command_help(shell, command) : self.class.help(shell, subcommand)
378
472
  end
379
473
  end