bundler 1.3.6 → 1.4.0.pre.1
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.
Potentially problematic release.
This version of bundler might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/CHANGELOG.md +27 -14
- data/CONTRIBUTING.md +2 -2
- data/{CONTRIBUTE.md → DEVELOPMENT.md} +31 -12
- data/ISSUES.md +1 -1
- data/README.md +6 -4
- data/Rakefile +1 -15
- data/bin/bundle +5 -8
- data/bundler.gemspec +1 -1
- data/lib/bundler.rb +37 -21
- data/lib/bundler/cli.rb +33 -21
- data/lib/bundler/constants.rb +5 -0
- data/lib/bundler/current_ruby.rb +88 -0
- data/lib/bundler/definition.rb +35 -11
- data/lib/bundler/dependency.rb +7 -78
- data/lib/bundler/dsl.rb +1 -1
- data/lib/bundler/fetcher.rb +37 -24
- data/lib/bundler/gem_helper.rb +2 -2
- data/lib/bundler/gem_installer.rb +9 -0
- data/lib/bundler/installer.rb +76 -7
- data/lib/bundler/parallel_workers.rb +18 -0
- data/lib/bundler/parallel_workers/thread_worker.rb +27 -0
- data/lib/bundler/parallel_workers/unix_worker.rb +88 -0
- data/lib/bundler/parallel_workers/worker.rb +68 -0
- data/lib/bundler/resolver.rb +17 -11
- data/lib/bundler/rubygems_ext.rb +2 -2
- data/lib/bundler/rubygems_integration.rb +37 -25
- data/lib/bundler/runtime.rb +8 -1
- data/lib/bundler/safe_catch.rb +101 -0
- data/lib/bundler/shared_helpers.rb +27 -1
- data/lib/bundler/source/git.rb +2 -1
- data/lib/bundler/source/git/git_proxy.rb +3 -3
- data/lib/bundler/source/path.rb +3 -2
- data/lib/bundler/source/rubygems.rb +5 -17
- data/lib/bundler/spec_set.rb +16 -1
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
- data/lib/bundler/vendor/net/http/persistent.rb +136 -38
- data/lib/bundler/vendor/thor.rb +211 -188
- data/lib/bundler/vendor/thor/actions.rb +19 -19
- data/lib/bundler/vendor/thor/actions/create_link.rb +3 -0
- data/lib/bundler/vendor/thor/actions/directory.rb +30 -10
- data/lib/bundler/vendor/thor/actions/empty_directory.rb +3 -19
- data/lib/bundler/vendor/thor/actions/file_manipulation.rb +6 -3
- data/lib/bundler/vendor/thor/base.rb +101 -97
- data/lib/bundler/vendor/thor/{task.rb → command.rb} +17 -13
- data/lib/bundler/vendor/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/bundler/vendor/thor/error.rb +8 -11
- data/lib/bundler/vendor/thor/group.rb +35 -38
- data/lib/bundler/vendor/thor/invocation.rb +28 -26
- data/lib/bundler/vendor/thor/parser/options.rb +21 -19
- data/lib/bundler/vendor/thor/rake_compat.rb +3 -2
- data/lib/bundler/vendor/thor/runner.rb +22 -21
- data/lib/bundler/vendor/thor/shell/basic.rb +44 -22
- data/lib/bundler/vendor/thor/shell/color.rb +13 -9
- data/lib/bundler/vendor/thor/shell/html.rb +13 -9
- data/lib/bundler/vendor/thor/util.rb +214 -210
- data/lib/bundler/vendor/thor/version.rb +1 -1
- data/lib/bundler/version.rb +1 -1
- data/man/bundle-install.ronn +5 -1
- data/man/gemfile.5.ronn +10 -2
- data/spec/bundler/dsl_spec.rb +3 -3
- data/spec/bundler/gem_helper_spec.rb +14 -17
- data/spec/bundler/safe_catch_spec.rb +37 -0
- data/spec/install/gems/dependency_api_spec.rb +1 -36
- data/spec/install/gems/packed_spec.rb +4 -2
- data/spec/install/gems/resolving_spec.rb +37 -0
- data/spec/install/gems/simple_case_spec.rb +18 -16
- data/spec/install/git_spec.rb +1 -1
- data/spec/other/binstubs_spec.rb +24 -13
- data/spec/other/exec_spec.rb +24 -2
- data/spec/other/help_spec.rb +6 -6
- data/spec/other/outdated_spec.rb +3 -3
- data/spec/quality_spec.rb +3 -2
- data/spec/realworld/dependency_api_spec.rb +1 -1
- data/spec/realworld/edgecases_spec.rb +3 -3
- data/spec/realworld/parallel_install_spec.rb +19 -0
- data/spec/resolver/basic_spec.rb +11 -0
- data/spec/runtime/require_spec.rb +9 -0
- data/spec/runtime/setup_spec.rb +2 -3
- data/spec/spec_helper.rb +0 -1
- data/spec/support/builders.rb +2 -4
- data/spec/support/helpers.rb +4 -8
- data/spec/support/indexes.rb +18 -0
- data/spec/support/streams.rb +13 -0
- metadata +19 -11
- data/lib/bundler/vendor/thor/core_ext/dir_escape.rb +0 -0
- data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +0 -9
- data/spec/support/artifice/endpoint_host_redirect.rb +0 -15
- data/spec/support/permissions.rb +0 -11
data/lib/bundler/vendor/thor.rb
CHANGED
@@ -3,21 +3,32 @@ require 'thor/base'
|
|
3
3
|
|
4
4
|
class Thor
|
5
5
|
class << self
|
6
|
-
#
|
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.
|
7
17
|
#
|
8
18
|
# ==== Parameters
|
9
|
-
# meth<Symbol>:: name of the default
|
10
|
-
#
|
11
|
-
def
|
12
|
-
case meth
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
19
29
|
end
|
20
30
|
end
|
31
|
+
alias default_task default_command
|
21
32
|
|
22
33
|
# Registers another Thor subclass as a command.
|
23
34
|
#
|
@@ -36,7 +47,7 @@ class Thor
|
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
39
|
-
# Defines the usage and the description of the next
|
50
|
+
# Defines the usage and the description of the next command.
|
40
51
|
#
|
41
52
|
# ==== Parameters
|
42
53
|
# usage<String>
|
@@ -45,29 +56,29 @@ class Thor
|
|
45
56
|
#
|
46
57
|
def desc(usage, description, options={})
|
47
58
|
if options[:for]
|
48
|
-
|
49
|
-
|
50
|
-
|
59
|
+
command = find_and_refresh_command(options[:for])
|
60
|
+
command.usage = usage if usage
|
61
|
+
command.description = description if description
|
51
62
|
else
|
52
63
|
@usage, @desc, @hide = usage, description, options[:hide] || false
|
53
64
|
end
|
54
65
|
end
|
55
66
|
|
56
|
-
# Defines the long description of the next
|
67
|
+
# Defines the long description of the next command.
|
57
68
|
#
|
58
69
|
# ==== Parameters
|
59
70
|
# long description<String>
|
60
71
|
#
|
61
72
|
def long_desc(long_description, options={})
|
62
73
|
if options[:for]
|
63
|
-
|
64
|
-
|
74
|
+
command = find_and_refresh_command(options[:for])
|
75
|
+
command.long_description = long_description if long_description
|
65
76
|
else
|
66
77
|
@long_desc = long_description
|
67
78
|
end
|
68
79
|
end
|
69
80
|
|
70
|
-
# Maps an input to a
|
81
|
+
# Maps an input to a command. If you define:
|
71
82
|
#
|
72
83
|
# map "-T" => "list"
|
73
84
|
#
|
@@ -75,10 +86,10 @@ class Thor
|
|
75
86
|
#
|
76
87
|
# thor -T
|
77
88
|
#
|
78
|
-
# Will invoke the list
|
89
|
+
# Will invoke the list command.
|
79
90
|
#
|
80
91
|
# ==== Parameters
|
81
|
-
# Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given
|
92
|
+
# Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
|
82
93
|
#
|
83
94
|
def map(mappings=nil)
|
84
95
|
@map ||= from_superclass(:map, {})
|
@@ -96,7 +107,7 @@ class Thor
|
|
96
107
|
@map
|
97
108
|
end
|
98
109
|
|
99
|
-
# Declares the options for the next
|
110
|
+
# Declares the options for the next command to be declared.
|
100
111
|
#
|
101
112
|
# ==== Parameters
|
102
113
|
# Hash[Symbol => Object]:: The hash key is the name of the option and the value
|
@@ -112,15 +123,15 @@ class Thor
|
|
112
123
|
alias options method_options
|
113
124
|
|
114
125
|
# Adds an option to the set of method options. If :for is given as option,
|
115
|
-
# it allows you to change the options from a previous defined
|
126
|
+
# it allows you to change the options from a previous defined command.
|
116
127
|
#
|
117
|
-
# def
|
128
|
+
# def previous_command
|
118
129
|
# # magic
|
119
130
|
# end
|
120
131
|
#
|
121
|
-
# method_option :foo => :bar, :for => :
|
132
|
+
# method_option :foo => :bar, :for => :previous_command
|
122
133
|
#
|
123
|
-
# def
|
134
|
+
# def next_command
|
124
135
|
# # magic
|
125
136
|
# end
|
126
137
|
#
|
@@ -139,38 +150,38 @@ class Thor
|
|
139
150
|
#
|
140
151
|
def method_option(name, options={})
|
141
152
|
scope = if options[:for]
|
142
|
-
|
153
|
+
find_and_refresh_command(options[:for]).options
|
143
154
|
else
|
144
155
|
method_options
|
145
156
|
end
|
146
157
|
|
147
158
|
build_option(name, options, scope)
|
148
159
|
end
|
149
|
-
|
150
160
|
alias option method_option
|
151
161
|
|
152
|
-
# Prints help information for the given
|
162
|
+
# Prints help information for the given command.
|
153
163
|
#
|
154
164
|
# ==== Parameters
|
155
165
|
# shell<Thor::Shell>
|
156
|
-
#
|
166
|
+
# command_name<String>
|
157
167
|
#
|
158
|
-
def
|
159
|
-
meth =
|
160
|
-
|
161
|
-
|
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
|
162
172
|
|
163
173
|
shell.say "Usage:"
|
164
|
-
shell.say " #{banner(
|
174
|
+
shell.say " #{banner(command)}"
|
165
175
|
shell.say
|
166
|
-
class_options_help(shell, nil =>
|
167
|
-
if
|
176
|
+
class_options_help(shell, nil => command.options.map { |_, o| o })
|
177
|
+
if command.long_description
|
168
178
|
shell.say "Description:"
|
169
|
-
shell.print_wrapped(
|
179
|
+
shell.print_wrapped(command.long_description, :indent => 2)
|
170
180
|
else
|
171
|
-
shell.say
|
181
|
+
shell.say command.description
|
172
182
|
end
|
173
183
|
end
|
184
|
+
alias task_help command_help
|
174
185
|
|
175
186
|
# Prints help information for this class.
|
176
187
|
#
|
@@ -178,32 +189,39 @@ class Thor
|
|
178
189
|
# shell<Thor::Shell>
|
179
190
|
#
|
180
191
|
def help(shell, subcommand = false)
|
181
|
-
list =
|
192
|
+
list = printable_commands(true, subcommand)
|
182
193
|
Thor::Util.thor_classes_in(self).each do |klass|
|
183
|
-
list += klass.
|
194
|
+
list += klass.printable_commands(false)
|
184
195
|
end
|
185
196
|
list.sort!{ |a,b| a[0] <=> b[0] }
|
186
197
|
|
187
|
-
|
198
|
+
if @package_name
|
199
|
+
shell.say "#{@package_name} commands:"
|
200
|
+
else
|
201
|
+
shell.say "Commands:"
|
202
|
+
end
|
203
|
+
|
188
204
|
shell.print_table(list, :indent => 2, :truncate => true)
|
189
205
|
shell.say
|
190
206
|
class_options_help(shell)
|
191
207
|
end
|
192
208
|
|
193
|
-
# Returns
|
194
|
-
def
|
195
|
-
(all ?
|
196
|
-
next if
|
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?
|
197
213
|
item = []
|
198
|
-
item << banner(
|
199
|
-
item << (
|
214
|
+
item << banner(command, false, subcommand)
|
215
|
+
item << (command.description ? "# #{command.description.gsub(/\s+/m,' ')}" : "")
|
200
216
|
item
|
201
217
|
end.compact
|
202
218
|
end
|
219
|
+
alias printable_tasks printable_commands
|
203
220
|
|
204
221
|
def subcommands
|
205
222
|
@subcommands ||= from_superclass(:subcommands, [])
|
206
223
|
end
|
224
|
+
alias subtasks subcommands
|
207
225
|
|
208
226
|
def subcommand(subcommand, subcommand_class)
|
209
227
|
self.subcommands << subcommand.to_s
|
@@ -211,9 +229,10 @@ class Thor
|
|
211
229
|
|
212
230
|
define_method(subcommand) do |*args|
|
213
231
|
args, opts = Thor::Arguments.split(args)
|
214
|
-
invoke subcommand_class, args, opts, :invoked_via_subcommand => true
|
232
|
+
invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options
|
215
233
|
end
|
216
234
|
end
|
235
|
+
alias subtask subcommand
|
217
236
|
|
218
237
|
# Extend check unknown options to accept a hash of conditions.
|
219
238
|
#
|
@@ -236,10 +255,10 @@ class Thor
|
|
236
255
|
options = check_unknown_options
|
237
256
|
return false unless options
|
238
257
|
|
239
|
-
|
240
|
-
return true unless
|
258
|
+
command = config[:current_command]
|
259
|
+
return true unless command
|
241
260
|
|
242
|
-
name =
|
261
|
+
name = command.name
|
243
262
|
|
244
263
|
if subcommands.include?(name)
|
245
264
|
false
|
@@ -253,16 +272,16 @@ class Thor
|
|
253
272
|
end
|
254
273
|
|
255
274
|
# Stop parsing of options as soon as an unknown option or a regular
|
256
|
-
# argument is encountered. All remaining arguments are passed to the
|
257
|
-
# This is useful if you have a
|
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
|
258
277
|
# options, and where those additional options should not be handled by
|
259
278
|
# Thor.
|
260
279
|
#
|
261
280
|
# ==== Example
|
262
281
|
#
|
263
|
-
# To better understand how this is useful, let's consider a
|
282
|
+
# To better understand how this is useful, let's consider a command that calls
|
264
283
|
# an external command. A user may want to pass arbitrary options and
|
265
|
-
# arguments to that command. The
|
284
|
+
# arguments to that command. The command itself also accepts some options,
|
266
285
|
# which should be handled by Thor.
|
267
286
|
#
|
268
287
|
# class_option "verbose", :type => :boolean
|
@@ -288,163 +307,167 @@ class Thor
|
|
288
307
|
# --verbose foo
|
289
308
|
#
|
290
309
|
# ==== Parameters
|
291
|
-
# Symbol ...:: A list of
|
292
|
-
def stop_on_unknown_option!(*
|
310
|
+
# Symbol ...:: A list of commands that should be affected.
|
311
|
+
def stop_on_unknown_option!(*command_names)
|
293
312
|
@stop_on_unknown_option ||= Set.new
|
294
|
-
@stop_on_unknown_option.merge(
|
313
|
+
@stop_on_unknown_option.merge(command_names)
|
295
314
|
end
|
296
315
|
|
297
|
-
def stop_on_unknown_option?(
|
298
|
-
|
316
|
+
def stop_on_unknown_option?(command) #:nodoc:
|
317
|
+
command && !@stop_on_unknown_option.nil? && @stop_on_unknown_option.include?(command.name.to_sym)
|
299
318
|
end
|
300
319
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
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)]
|
341
|
+
end
|
323
342
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
end
|
332
|
-
else
|
333
|
-
args, opts = given_args, nil
|
334
|
-
task = Thor::DynamicTask.new(meth)
|
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
|
335
350
|
end
|
336
|
-
|
337
|
-
opts =
|
338
|
-
|
339
|
-
|
340
|
-
instance = new(args, opts, config)
|
341
|
-
yield instance if block_given?
|
342
|
-
args = instance.args
|
343
|
-
trailing = args[Range.new(arguments.size, -1)]
|
344
|
-
instance.invoke_task(task, trailing || [])
|
351
|
+
else
|
352
|
+
args, opts = given_args, nil
|
353
|
+
command = Thor::DynamicCommand.new(meth)
|
345
354
|
end
|
346
355
|
|
347
|
-
|
348
|
-
|
349
|
-
# the task that is going to be invoked and a boolean which indicates if
|
350
|
-
# the namespace should be displayed as arguments.
|
351
|
-
#
|
352
|
-
def banner(task, namespace = nil, subcommand = false)
|
353
|
-
"#{basename} #{task.formatted_usage(self, $thor_runner, subcommand)}"
|
354
|
-
end
|
356
|
+
opts = given_opts || opts || []
|
357
|
+
config.merge!(:current_command => command, :command_options => command.options)
|
355
358
|
|
356
|
-
|
357
|
-
|
358
|
-
|
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
|
359
365
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
elsif self.all_tasks[meth] || meth == "method_missing"
|
369
|
-
true
|
370
|
-
else
|
371
|
-
puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
|
372
|
-
"Call desc if you want this method to be available as task or declare it inside a " <<
|
373
|
-
"no_tasks{} block. Invoked from #{caller[1].inspect}."
|
374
|
-
false
|
375
|
-
end
|
376
|
-
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
|
377
374
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
end
|
375
|
+
def baseclass #:nodoc:
|
376
|
+
Thor
|
377
|
+
end
|
382
378
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
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
|
391
392
|
end
|
393
|
+
end
|
394
|
+
alias create_task create_command
|
392
395
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
#
|
398
|
-
# +normalize_task_name+ also converts names like +animal-prison+
|
399
|
-
# into +animal_prison+.
|
400
|
-
def normalize_task_name(meth) #:nodoc:
|
401
|
-
return default_task.to_s.gsub('-', '_') unless meth
|
402
|
-
|
403
|
-
possibilities = find_task_possibilities(meth)
|
404
|
-
if possibilities.size > 1
|
405
|
-
raise ArgumentError, "Ambiguous task #{meth} matches [#{possibilities.join(', ')}]"
|
406
|
-
elsif possibilities.size < 1
|
407
|
-
meth = meth || default_task
|
408
|
-
elsif map[meth]
|
409
|
-
meth = map[meth]
|
410
|
-
else
|
411
|
-
meth = possibilities.first
|
412
|
-
end
|
396
|
+
def initialize_added #:nodoc:
|
397
|
+
class_options.merge!(method_options)
|
398
|
+
@method_options = nil
|
399
|
+
end
|
413
400
|
|
414
|
-
|
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
|
415
408
|
end
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
409
|
+
end
|
410
|
+
alias retrieve_task_name retrieve_command_name
|
411
|
+
|
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 AmbiguousTaskError, "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
|
432
431
|
end
|
433
432
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
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
|
439
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
|
+
|
440
463
|
end
|
441
464
|
|
442
465
|
include Thor::Base
|
443
466
|
|
444
467
|
map HELP_MAPPINGS => :help
|
445
468
|
|
446
|
-
desc "help [
|
447
|
-
def help(
|
448
|
-
|
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)
|
449
472
|
end
|
450
473
|
end
|