bundler 1.3.6 → 1.4.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'uri'
|
3
|
-
require 'thor/core_ext/
|
3
|
+
require 'thor/core_ext/io_binary_read'
|
4
4
|
require 'thor/actions/create_file'
|
5
5
|
require 'thor/actions/create_link'
|
6
6
|
require 'thor/actions/directory'
|
@@ -73,13 +73,13 @@ class Thor
|
|
73
73
|
#
|
74
74
|
def initialize(args=[], options={}, config={})
|
75
75
|
self.behavior = case config[:behavior].to_s
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
when "force", "skip"
|
77
|
+
_cleanup_options_and_set(options, config[:behavior])
|
78
|
+
:invoke
|
79
|
+
when "revoke"
|
80
|
+
:revoke
|
81
|
+
else
|
82
|
+
:invoke
|
83
83
|
end
|
84
84
|
|
85
85
|
super
|
@@ -227,7 +227,7 @@ class Thor
|
|
227
227
|
# ==== Parameters
|
228
228
|
# command<String>:: the command to be executed.
|
229
229
|
# config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with
|
230
|
-
# to append an executable to command
|
230
|
+
# to append an executable to command execution.
|
231
231
|
#
|
232
232
|
# ==== Example
|
233
233
|
#
|
@@ -268,8 +268,8 @@ class Thor
|
|
268
268
|
# switches.
|
269
269
|
#
|
270
270
|
# ==== Parameters
|
271
|
-
#
|
272
|
-
# args<Array>:: arguments to the
|
271
|
+
# command<String>:: the command to be invoked
|
272
|
+
# args<Array>:: arguments to the command
|
273
273
|
# config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output.
|
274
274
|
# Other options are given as parameter to Thor.
|
275
275
|
#
|
@@ -282,13 +282,13 @@ class Thor
|
|
282
282
|
# thor :list, :all => true, :substring => 'rails'
|
283
283
|
# #=> thor list --all --substring=rails
|
284
284
|
#
|
285
|
-
def thor(
|
285
|
+
def thor(command, *args)
|
286
286
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
287
287
|
verbose = config.key?(:verbose) ? config.delete(:verbose) : true
|
288
288
|
pretend = config.key?(:pretend) ? config.delete(:pretend) : false
|
289
289
|
capture = config.key?(:capture) ? config.delete(:capture) : false
|
290
290
|
|
291
|
-
args.unshift
|
291
|
+
args.unshift(command)
|
292
292
|
args.push Thor::Options.to_switches(config)
|
293
293
|
command = args.join(' ').strip
|
294
294
|
|
@@ -305,12 +305,12 @@ class Thor
|
|
305
305
|
|
306
306
|
def _cleanup_options_and_set(options, key) #:nodoc:
|
307
307
|
case options
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
308
|
+
when Array
|
309
|
+
%w(--force -f --skip -s).each { |i| options.delete(i) }
|
310
|
+
options << "--#{key}"
|
311
|
+
when Hash
|
312
|
+
[:force, :skip, "force", "skip"].each { |i| options.delete(i) }
|
313
|
+
options.merge!(key => true)
|
314
314
|
end
|
315
315
|
end
|
316
316
|
|
@@ -39,6 +39,7 @@ class Thor
|
|
39
39
|
# config<Hash>:: give :verbose => false to not log the status.
|
40
40
|
# If :recursive => false, does not look for paths recursively.
|
41
41
|
# If :mode => :preserve, preserve the file mode from the source.
|
42
|
+
# If :exclude_pattern => /regexp/, prevents copying files that match that regexp.
|
42
43
|
#
|
43
44
|
# ==== Examples
|
44
45
|
#
|
@@ -74,26 +75,45 @@ class Thor
|
|
74
75
|
def execute!
|
75
76
|
lookup = Util.escape_globs(source)
|
76
77
|
lookup = config[:recursive] ? File.join(lookup, '**') : lookup
|
77
|
-
lookup =
|
78
|
+
lookup = file_level_lookup(lookup)
|
78
79
|
|
79
|
-
|
80
|
+
files(lookup).sort.each do |file_source|
|
80
81
|
next if File.directory?(file_source)
|
82
|
+
next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern])
|
81
83
|
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
82
84
|
file_destination.gsub!('/./', '/')
|
83
85
|
|
84
86
|
case file_source
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
when /\.empty_directory$/
|
88
|
+
dirname = File.dirname(file_destination).gsub(/\/\.$/, '')
|
89
|
+
next if dirname == given_destination
|
90
|
+
base.empty_directory(dirname, config)
|
91
|
+
when /\.tt$/
|
92
|
+
destination = base.template(file_source, file_destination[0..-4], config, &@block)
|
93
|
+
else
|
94
|
+
destination = base.copy_file(file_source, file_destination, config, &@block)
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
96
98
|
|
99
|
+
if RUBY_VERSION < '2.0'
|
100
|
+
def file_level_lookup(previous_lookup)
|
101
|
+
File.join(previous_lookup, '{*,.[a-z]*}')
|
102
|
+
end
|
103
|
+
|
104
|
+
def files(lookup)
|
105
|
+
Dir[lookup]
|
106
|
+
end
|
107
|
+
else
|
108
|
+
def file_level_lookup(previous_lookup)
|
109
|
+
File.join(previous_lookup, '*')
|
110
|
+
end
|
111
|
+
|
112
|
+
def files(lookup)
|
113
|
+
Dir.glob(lookup, File::FNM_DOTMATCH)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
97
117
|
end
|
98
118
|
end
|
99
119
|
end
|
@@ -97,28 +97,12 @@ class Thor
|
|
97
97
|
#
|
98
98
|
# user.rb
|
99
99
|
#
|
100
|
-
# The method referenced
|
101
|
-
# get the exception with the corresponding error message.
|
100
|
+
# The method referenced can be either public or private.
|
102
101
|
#
|
103
102
|
def convert_encoded_instructions(filename)
|
104
103
|
filename.gsub(/%(.*?)%/) do |initial_string|
|
105
|
-
|
106
|
-
|
107
|
-
end
|
108
|
-
|
109
|
-
# Calls `base`'s public method `sym`.
|
110
|
-
# Returns:: result of `base.sym` or `nil` if `sym` wasn't found in
|
111
|
-
# `base`
|
112
|
-
# Raises:: Thor::PrivateMethodEncodedError if `sym` references
|
113
|
-
# a private method.
|
114
|
-
def call_public_method(sym)
|
115
|
-
if base.respond_to?(sym)
|
116
|
-
base.send(sym)
|
117
|
-
elsif base.respond_to?(sym, true)
|
118
|
-
raise Thor::PrivateMethodEncodedError,
|
119
|
-
"Method #{base.class}##{sym} should be public, not private"
|
120
|
-
else
|
121
|
-
nil
|
104
|
+
method = $1.strip
|
105
|
+
base.respond_to?(method, true) ? base.send(method) : initial_string
|
122
106
|
end
|
123
107
|
end
|
124
108
|
|
@@ -129,7 +129,7 @@ class Thor
|
|
129
129
|
#
|
130
130
|
# ==== Example
|
131
131
|
#
|
132
|
-
# chmod "script
|
132
|
+
# chmod "script/server", 0755
|
133
133
|
#
|
134
134
|
def chmod(path, mode, config={})
|
135
135
|
return unless behavior == :invoke
|
@@ -251,7 +251,7 @@ class Thor
|
|
251
251
|
def uncomment_lines(path, flag, *args)
|
252
252
|
flag = flag.respond_to?(:source) ? flag.source : flag
|
253
253
|
|
254
|
-
gsub_file(path, /^(\s*)
|
254
|
+
gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
|
255
255
|
end
|
256
256
|
|
257
257
|
# Comment all lines matching a given regex. It will leave the space
|
@@ -293,8 +293,11 @@ class Thor
|
|
293
293
|
end
|
294
294
|
alias :remove_dir :remove_file
|
295
295
|
|
296
|
-
|
296
|
+
attr_accessor :output_buffer
|
297
|
+
private :output_buffer, :output_buffer=
|
298
|
+
|
297
299
|
private
|
300
|
+
|
298
301
|
def concat(string)
|
299
302
|
@output_buffer.concat(string)
|
300
303
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
+
require 'thor/command'
|
1
2
|
require 'thor/core_ext/hash_with_indifferent_access'
|
2
3
|
require 'thor/core_ext/ordered_hash'
|
3
4
|
require 'thor/error'
|
4
|
-
require 'thor/shell'
|
5
5
|
require 'thor/invocation'
|
6
6
|
require 'thor/parser'
|
7
|
-
require 'thor/
|
7
|
+
require 'thor/shell'
|
8
8
|
require 'thor/util'
|
9
9
|
|
10
10
|
class Thor
|
@@ -47,8 +47,8 @@ class Thor
|
|
47
47
|
# first two parameters.
|
48
48
|
|
49
49
|
if options.is_a?(Array)
|
50
|
-
|
51
|
-
parse_options = parse_options.merge(
|
50
|
+
command_options = config.delete(:command_options) # hook for start
|
51
|
+
parse_options = parse_options.merge(command_options) if command_options
|
52
52
|
array_options, hash_options = options, {}
|
53
53
|
else
|
54
54
|
# Handle the case where the class was explicitly instantiated
|
@@ -59,9 +59,10 @@ class Thor
|
|
59
59
|
# Let Thor::Options parse the options first, so it can remove
|
60
60
|
# declared options from the array. This will leave us with
|
61
61
|
# a list of arguments that weren't declared.
|
62
|
-
stop_on_unknown = self.class.stop_on_unknown_option? config[:
|
62
|
+
stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command]
|
63
63
|
opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
|
64
64
|
self.options = opts.parse(array_options)
|
65
|
+
self.options = config[:class_options].merge(self.options) if config[:class_options]
|
65
66
|
|
66
67
|
# If unknown options are disallowed, make sure that none of the
|
67
68
|
# remaining arguments looks like an option.
|
@@ -119,15 +120,15 @@ class Thor
|
|
119
120
|
|
120
121
|
module ClassMethods
|
121
122
|
def attr_reader(*) #:nodoc:
|
122
|
-
|
123
|
+
no_commands { super }
|
123
124
|
end
|
124
125
|
|
125
126
|
def attr_writer(*) #:nodoc:
|
126
|
-
|
127
|
+
no_commands { super }
|
127
128
|
end
|
128
129
|
|
129
130
|
def attr_accessor(*) #:nodoc:
|
130
|
-
|
131
|
+
no_commands { super }
|
131
132
|
end
|
132
133
|
|
133
134
|
# If you want to raise an error for unknown options, call check_unknown_options!
|
@@ -146,8 +147,8 @@ class Thor
|
|
146
147
|
|
147
148
|
# If true, option parsing is suspended as soon as an unknown option or a
|
148
149
|
# regular argument is encountered. All remaining arguments are passed to
|
149
|
-
# the
|
150
|
-
def stop_on_unknown_option?(
|
150
|
+
# the command as regular arguments.
|
151
|
+
def stop_on_unknown_option?(command_name) #:nodoc:
|
151
152
|
false
|
152
153
|
end
|
153
154
|
|
@@ -172,11 +173,11 @@ class Thor
|
|
172
173
|
# is how they are parsed from the command line, arguments are retrieved
|
173
174
|
# from position:
|
174
175
|
#
|
175
|
-
# thor
|
176
|
+
# thor command NAME
|
176
177
|
#
|
177
178
|
# Instead of:
|
178
179
|
#
|
179
|
-
# thor
|
180
|
+
# thor command --name=NAME
|
180
181
|
#
|
181
182
|
# Besides, arguments are used inside your code as an accessor (self.argument),
|
182
183
|
# while options are all kept in a hash (self.options).
|
@@ -203,7 +204,7 @@ class Thor
|
|
203
204
|
#
|
204
205
|
def argument(name, options={})
|
205
206
|
is_thor_reserved_word?(name, :argument)
|
206
|
-
|
207
|
+
no_commands { attr_accessor name }
|
207
208
|
|
208
209
|
required = if options.key?(:optional)
|
209
210
|
!options[:optional]
|
@@ -307,88 +308,92 @@ class Thor
|
|
307
308
|
end
|
308
309
|
|
309
310
|
# Defines the group. This is used when thor list is invoked so you can specify
|
310
|
-
# that only
|
311
|
+
# that only commands from a pre-defined group will be shown. Defaults to standard.
|
311
312
|
#
|
312
313
|
# ==== Parameters
|
313
314
|
# name<String|Symbol>
|
314
315
|
#
|
315
316
|
def group(name=nil)
|
316
|
-
case name
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
317
|
+
@group = case name
|
318
|
+
when nil
|
319
|
+
@group || from_superclass(:group, 'standard')
|
320
|
+
else
|
321
|
+
name.to_s
|
321
322
|
end
|
322
323
|
end
|
323
324
|
|
324
|
-
# Returns the
|
325
|
+
# Returns the commands for this Thor class.
|
325
326
|
#
|
326
327
|
# ==== Returns
|
327
|
-
# OrderedHash:: An ordered hash with
|
328
|
+
# OrderedHash:: An ordered hash with commands names as keys and Thor::Command
|
328
329
|
# objects as values.
|
329
330
|
#
|
330
|
-
def
|
331
|
-
@
|
331
|
+
def commands
|
332
|
+
@commands ||= Thor::CoreExt::OrderedHash.new
|
332
333
|
end
|
334
|
+
alias tasks commands
|
333
335
|
|
334
|
-
# Returns the
|
336
|
+
# Returns the commands for this Thor class and all subclasses.
|
335
337
|
#
|
336
338
|
# ==== Returns
|
337
|
-
# OrderedHash:: An ordered hash with
|
339
|
+
# OrderedHash:: An ordered hash with commands names as keys and Thor::Command
|
338
340
|
# objects as values.
|
339
341
|
#
|
340
|
-
def
|
341
|
-
@
|
342
|
-
@
|
342
|
+
def all_commands
|
343
|
+
@all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new)
|
344
|
+
@all_commands.merge(commands)
|
343
345
|
end
|
346
|
+
alias all_tasks all_commands
|
344
347
|
|
345
|
-
# Removes a given
|
348
|
+
# Removes a given command from this Thor class. This is usually done if you
|
346
349
|
# are inheriting from another class and don't want it to be available
|
347
350
|
# anymore.
|
348
351
|
#
|
349
|
-
# By default it only remove the mapping to the
|
352
|
+
# By default it only remove the mapping to the command. But you can supply
|
350
353
|
# :undefine => true to undefine the method from the class as well.
|
351
354
|
#
|
352
355
|
# ==== Parameters
|
353
|
-
# name<Symbol|String>:: The name of the
|
354
|
-
# options<Hash>:: You can give :undefine => true if you want
|
356
|
+
# name<Symbol|String>:: The name of the command to be removed
|
357
|
+
# options<Hash>:: You can give :undefine => true if you want commands the method
|
355
358
|
# to be undefined from the class as well.
|
356
359
|
#
|
357
|
-
def
|
360
|
+
def remove_command(*names)
|
358
361
|
options = names.last.is_a?(Hash) ? names.pop : {}
|
359
362
|
|
360
363
|
names.each do |name|
|
361
|
-
|
362
|
-
|
364
|
+
commands.delete(name.to_s)
|
365
|
+
all_commands.delete(name.to_s)
|
363
366
|
undef_method name if options[:undefine]
|
364
367
|
end
|
365
368
|
end
|
369
|
+
alias remove_task remove_command
|
366
370
|
|
367
|
-
# All methods defined inside the given block are not added as
|
371
|
+
# All methods defined inside the given block are not added as commands.
|
368
372
|
#
|
369
373
|
# So you can do:
|
370
374
|
#
|
371
375
|
# class MyScript < Thor
|
372
|
-
#
|
373
|
-
# def
|
376
|
+
# no_commands do
|
377
|
+
# def this_is_not_a_command
|
374
378
|
# end
|
375
379
|
# end
|
376
380
|
# end
|
377
381
|
#
|
378
|
-
# You can also add the method and remove it from the
|
382
|
+
# You can also add the method and remove it from the command list:
|
379
383
|
#
|
380
384
|
# class MyScript < Thor
|
381
|
-
# def
|
385
|
+
# def this_is_not_a_command
|
382
386
|
# end
|
383
|
-
#
|
387
|
+
# remove_command :this_is_not_a_command
|
384
388
|
# end
|
385
389
|
#
|
386
|
-
def
|
387
|
-
@
|
390
|
+
def no_commands
|
391
|
+
@no_commands = true
|
388
392
|
yield
|
389
393
|
ensure
|
390
|
-
@
|
394
|
+
@no_commands = false
|
391
395
|
end
|
396
|
+
alias no_tasks no_commands
|
392
397
|
|
393
398
|
# Sets the namespace for the Thor or Thor::Group class. By default the
|
394
399
|
# namespace is retrieved from the class name. If your Thor class is named
|
@@ -400,7 +405,7 @@ class Thor
|
|
400
405
|
#
|
401
406
|
# namespace :my_scripts
|
402
407
|
#
|
403
|
-
# You change how your
|
408
|
+
# You change how your commands are invoked:
|
404
409
|
#
|
405
410
|
# thor my_scripts -h
|
406
411
|
#
|
@@ -408,26 +413,25 @@ class Thor
|
|
408
413
|
#
|
409
414
|
# namespace :default
|
410
415
|
#
|
411
|
-
# Your
|
416
|
+
# Your commands can be invoked with a shortcut. Instead of:
|
412
417
|
#
|
413
|
-
# thor :
|
418
|
+
# thor :my_command
|
414
419
|
#
|
415
420
|
def namespace(name=nil)
|
416
|
-
|
417
|
-
when nil
|
418
|
-
@namespace ||= Thor::Util.namespace_from_thor_class(self)
|
419
|
-
else
|
421
|
+
if name
|
420
422
|
@namespace = name.to_s
|
423
|
+
else
|
424
|
+
@namespace ||= Thor::Util.namespace_from_thor_class(self)
|
421
425
|
end
|
422
426
|
end
|
423
427
|
|
424
|
-
# Parses the
|
425
|
-
# and invoke the
|
428
|
+
# Parses the command and options from the given args, instantiate the class
|
429
|
+
# and invoke the command. This method is used when the arguments must be parsed
|
426
430
|
# from an array. If you are inside Ruby and want to use a Thor class, you
|
427
431
|
# can simply initialize it:
|
428
432
|
#
|
429
433
|
# script = MyScript.new(args, options, config)
|
430
|
-
# script.invoke(:
|
434
|
+
# script.invoke(:command, first_arg, second_arg, third_arg)
|
431
435
|
#
|
432
436
|
def start(given_args=ARGV, config={})
|
433
437
|
config[:shell] ||= Thor::Base.shell.new
|
@@ -436,48 +440,44 @@ class Thor
|
|
436
440
|
ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
|
437
441
|
exit(1) if exit_on_failure?
|
438
442
|
rescue Errno::EPIPE
|
439
|
-
# This happens if a thor
|
443
|
+
# This happens if a thor command is piped to something like `head`,
|
440
444
|
# which closes the pipe when it's done reading. This will also
|
441
445
|
# mean that if the pipe is closed, further unnecessary
|
442
446
|
# computation will not occur.
|
443
447
|
exit(0)
|
444
448
|
end
|
445
449
|
|
446
|
-
# Allows to use private methods from parent in child classes as
|
450
|
+
# Allows to use private methods from parent in child classes as commands.
|
447
451
|
#
|
448
452
|
# ==== Parameters
|
449
|
-
# names<Array>:: Method names to be used as
|
453
|
+
# names<Array>:: Method names to be used as commands
|
450
454
|
#
|
451
455
|
# ==== Examples
|
452
456
|
#
|
453
|
-
#
|
454
|
-
#
|
457
|
+
# public_command :foo
|
458
|
+
# public_command :foo, :bar, :baz
|
455
459
|
#
|
456
|
-
def
|
460
|
+
def public_command(*names)
|
457
461
|
names.each do |name|
|
458
462
|
class_eval "def #{name}(*); super end"
|
459
463
|
end
|
460
464
|
end
|
465
|
+
alias public_task public_command
|
461
466
|
|
462
|
-
def
|
467
|
+
def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
|
463
468
|
if has_namespace
|
464
|
-
raise
|
469
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace."
|
465
470
|
else
|
466
|
-
raise
|
471
|
+
raise UndefinedCommandError, "Could not find command #{command.inspect}."
|
467
472
|
end
|
468
473
|
end
|
474
|
+
alias handle_no_task_error handle_no_command_error
|
469
475
|
|
470
|
-
def handle_argument_error(
|
471
|
-
msg = "#{basename} #{
|
472
|
-
if
|
473
|
-
|
474
|
-
|
475
|
-
msg << "s" if required > 1
|
476
|
-
else
|
477
|
-
msg = "call #{msg} as"
|
478
|
-
end
|
479
|
-
|
480
|
-
msg << ": #{self.banner(task).inspect}."
|
476
|
+
def handle_argument_error(command, error, args, arity) #:nodoc:
|
477
|
+
msg = "ERROR: \"#{basename} #{command.name}\" was called with "
|
478
|
+
msg << 'no arguments' if args.empty?
|
479
|
+
msg << 'arguments ' << args.inspect if !args.empty?
|
480
|
+
msg << "\nUsage: #{self.banner(command).inspect}"
|
481
481
|
raise InvocationError, msg
|
482
482
|
end
|
483
483
|
|
@@ -555,28 +555,29 @@ class Thor
|
|
555
555
|
end
|
556
556
|
end
|
557
557
|
|
558
|
-
# Finds a
|
558
|
+
# Finds a command with the given name. If the command belongs to the current
|
559
559
|
# class, just return it, otherwise dup it and add the fresh copy to the
|
560
|
-
# current
|
561
|
-
def
|
562
|
-
|
563
|
-
|
564
|
-
elsif
|
565
|
-
|
560
|
+
# current command hash.
|
561
|
+
def find_and_refresh_command(name) #:nodoc:
|
562
|
+
command = if command = commands[name.to_s]
|
563
|
+
command
|
564
|
+
elsif command = all_commands[name.to_s]
|
565
|
+
commands[name.to_s] = command.clone
|
566
566
|
else
|
567
|
-
raise ArgumentError, "You supplied :for => #{name.inspect}, but the
|
567
|
+
raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
|
568
568
|
end
|
569
569
|
end
|
570
|
+
alias find_and_refresh_task find_and_refresh_command
|
570
571
|
|
571
572
|
# Everytime someone inherits from a Thor class, register the klass
|
572
573
|
# and file into baseclass.
|
573
574
|
def inherited(klass)
|
574
575
|
Thor::Base.register_klass_file(klass)
|
575
|
-
klass.instance_variable_set(:@
|
576
|
+
klass.instance_variable_set(:@no_commands, false)
|
576
577
|
end
|
577
578
|
|
578
579
|
# Fire this callback whenever a method is added. Added methods are
|
579
|
-
# tracked as
|
580
|
+
# tracked as commands by invoking the create_command method.
|
580
581
|
def method_added(meth)
|
581
582
|
meth = meth.to_s
|
582
583
|
|
@@ -586,12 +587,11 @@ class Thor
|
|
586
587
|
end
|
587
588
|
|
588
589
|
# Return if it's not a public instance method
|
589
|
-
return unless
|
590
|
-
public_instance_methods.include?(meth.to_sym)
|
590
|
+
return unless public_method_defined?(meth.to_sym)
|
591
591
|
|
592
|
-
return if
|
592
|
+
return if @no_commands || !create_command(meth)
|
593
593
|
|
594
|
-
is_thor_reserved_word?(meth, :
|
594
|
+
is_thor_reserved_word?(meth, :command)
|
595
595
|
Thor::Base.register_klass_file(self)
|
596
596
|
end
|
597
597
|
|
@@ -603,13 +603,16 @@ class Thor
|
|
603
603
|
else
|
604
604
|
value = superclass.send(method)
|
605
605
|
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
606
|
+
# Ruby implements `dup` on Object, but raises a `TypeError`
|
607
|
+
# if the method is called on immediates. As a result, we
|
608
|
+
# don't have a good way to check whether dup will succeed
|
609
|
+
# without calling it and rescuing the TypeError.
|
610
|
+
begin
|
611
|
+
value.dup
|
612
|
+
rescue TypeError
|
613
|
+
value
|
612
614
|
end
|
615
|
+
|
613
616
|
end
|
614
617
|
end
|
615
618
|
|
@@ -630,10 +633,11 @@ class Thor
|
|
630
633
|
def baseclass #:nodoc:
|
631
634
|
end
|
632
635
|
|
633
|
-
# SIGNATURE: Creates a new
|
636
|
+
# SIGNATURE: Creates a new command if valid_command? is true. This method is
|
634
637
|
# called when a new method is added to the class.
|
635
|
-
def
|
638
|
+
def create_command(meth) #:nodoc:
|
636
639
|
end
|
640
|
+
alias create_task create_command
|
637
641
|
|
638
642
|
# SIGNATURE: Defines behavior when the initialize method is added to the
|
639
643
|
# class.
|
@@ -641,7 +645,7 @@ class Thor
|
|
641
645
|
end
|
642
646
|
|
643
647
|
# SIGNATURE: The hook invoked by start.
|
644
|
-
def dispatch(
|
648
|
+
def dispatch(command, given_args, given_opts, config) #:nodoc:
|
645
649
|
raise NotImplementedError
|
646
650
|
end
|
647
651
|
|