bundler 0.9.6 → 0.9.7
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.
- data/README.markdown +6 -0
- data/lib/bundler.rb +1 -1
- data/lib/bundler/cli.rb +6 -0
- data/lib/bundler/installer.rb +4 -4
- data/lib/bundler/resolver.rb +1 -1
- data/lib/bundler/runtime.rb +3 -71
- data/lib/bundler/shared_helpers.rb +81 -12
- data/lib/bundler/templates/environment.erb +10 -32
- data/lib/bundler/vendor/thor.rb +10 -6
- data/lib/bundler/vendor/thor/base.rb +30 -20
- data/lib/bundler/vendor/thor/error.rb +3 -0
- data/lib/bundler/vendor/thor/invocation.rb +14 -17
- data/lib/bundler/vendor/thor/parser/arguments.rb +5 -4
- data/lib/bundler/vendor/thor/parser/option.rb +0 -4
- data/lib/bundler/vendor/thor/parser/options.rb +23 -10
- data/lib/bundler/vendor/thor/task.rb +20 -29
- data/lib/bundler/vendor/thor/util.rb +11 -14
- data/lib/bundler/vendor/thor/version.rb +1 -1
- metadata +2 -2
data/README.markdown
CHANGED
@@ -54,6 +54,12 @@ Bundler::Dsl.
|
|
54
54
|
#
|
55
55
|
gem "rack", "1.0.0"
|
56
56
|
|
57
|
+
# Add a git repository as a source, and add a dependency on a gem
|
58
|
+
# from it
|
59
|
+
git "git://github.com/indirect/rails3-generators.git"
|
60
|
+
gem "rails3-generators"
|
61
|
+
|
62
|
+
|
57
63
|
### Groups
|
58
64
|
|
59
65
|
Applications may have dependencies that are specific to certain environments,
|
data/lib/bundler.rb
CHANGED
data/lib/bundler/cli.rb
CHANGED
@@ -126,6 +126,12 @@ module Bundler
|
|
126
126
|
Kernel.exec *ARGV
|
127
127
|
end
|
128
128
|
|
129
|
+
desc "version", "Prints the bundler's version information"
|
130
|
+
def version
|
131
|
+
Bundler.ui.info "Bundler version #{Bundler::VERSION}"
|
132
|
+
end
|
133
|
+
map %w(-v --version) => :version
|
134
|
+
|
129
135
|
private
|
130
136
|
|
131
137
|
def locked?
|
data/lib/bundler/installer.rb
CHANGED
@@ -16,15 +16,15 @@ module Bundler
|
|
16
16
|
FileUtils.mkdir_p(Bundler.bundle_path)
|
17
17
|
|
18
18
|
specs.sort_by { |s| s.name }.each do |spec|
|
19
|
-
# unless spec.source.is_a?(Source::SystemGems)
|
20
|
-
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) from #{spec.source} "
|
21
|
-
# end
|
22
|
-
|
23
19
|
if (spec.groups & options[:without]).any?
|
24
20
|
Bundler.ui.debug " * Not in requested group; skipping."
|
25
21
|
next
|
26
22
|
end
|
27
23
|
|
24
|
+
# unless spec.source.is_a?(Source::SystemGems)
|
25
|
+
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) from #{spec.source} "
|
26
|
+
# end
|
27
|
+
|
28
28
|
spec.source.install(spec)
|
29
29
|
|
30
30
|
Bundler.ui.info ""
|
data/lib/bundler/resolver.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'set'
|
2
2
|
# This is the latest iteration of the gem dependency resolving algorithm. As of now,
|
3
|
-
# it can resolve (as a success
|
3
|
+
# it can resolve (as a success or failure) any set of gem dependencies we throw at it
|
4
4
|
# in a reasonable amount of time. The most iterations I've seen it take is about 150.
|
5
5
|
# The actual implementation of the algorithm is not as good as it could be yet, but that
|
6
6
|
# can come later.
|
data/lib/bundler/runtime.rb
CHANGED
@@ -172,13 +172,10 @@ module Bundler
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def specs_for_lock_file
|
175
|
-
specs.map do |
|
176
|
-
dep = @definition.dependencies.find { |d| d.name == spec.name }
|
175
|
+
specs.map do |s|
|
177
176
|
hash = {}
|
178
|
-
hash[:
|
179
|
-
hash[:
|
180
|
-
hash[:groups] = spec.groups
|
181
|
-
hash[:load_paths] = spec.load_paths
|
177
|
+
hash[:loaded_from] = s.loaded_from.to_s
|
178
|
+
hash[:load_paths] = s.load_paths
|
182
179
|
hash
|
183
180
|
end
|
184
181
|
end
|
@@ -213,70 +210,5 @@ module Bundler
|
|
213
210
|
groups.inject({}) { |h,g| h[g] = autorequires[g]; h }
|
214
211
|
end
|
215
212
|
end
|
216
|
-
|
217
|
-
def cripple_rubygems(specs)
|
218
|
-
reverse_rubygems_kernel_mixin
|
219
|
-
|
220
|
-
executables = specs.map { |s| s.executables }.flatten
|
221
|
-
|
222
|
-
# TODO: This is duplicated a bit too much in environment.erb.
|
223
|
-
# Let's figure out how to improve that.
|
224
|
-
::Kernel.send(:define_method, :gem) do |dep, *reqs|
|
225
|
-
if executables.include? File.basename(caller.first.split(':').first)
|
226
|
-
return
|
227
|
-
end
|
228
|
-
opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
|
229
|
-
|
230
|
-
unless dep.respond_to?(:name) && dep.respond_to?(:version_requirements)
|
231
|
-
dep = Gem::Dependency.new(dep, reqs)
|
232
|
-
end
|
233
|
-
|
234
|
-
spec = specs.find { |s| s.name == dep.name }
|
235
|
-
|
236
|
-
if spec.nil?
|
237
|
-
e = Gem::LoadError.new "#{dep} is not part of the bundle. Add it to Gemfile."
|
238
|
-
e.name = dep.name
|
239
|
-
e.version_requirement = dep.version_requirements
|
240
|
-
raise e
|
241
|
-
elsif dep !~ spec
|
242
|
-
e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
|
243
|
-
"Make sure all dependencies are added to Gemfile."
|
244
|
-
e.name = dep.name
|
245
|
-
e.version_requirement = dep.version_requirements
|
246
|
-
raise e
|
247
|
-
end
|
248
|
-
|
249
|
-
true
|
250
|
-
end
|
251
|
-
|
252
|
-
# === Following hacks are to improve on the generated bin wrappers ===
|
253
|
-
|
254
|
-
# Yeah, talk about a hack
|
255
|
-
source_index_class = (class << Gem::SourceIndex ; self ; end)
|
256
|
-
source_index_class.send(:define_method, :from_gems_in) do |*args|
|
257
|
-
source_index = Gem::SourceIndex.new
|
258
|
-
source_index.spec_dirs = *args
|
259
|
-
source_index.add_specs(*specs)
|
260
|
-
source_index
|
261
|
-
end
|
262
|
-
|
263
|
-
# OMG more hacks
|
264
|
-
gem_class = (class << Gem ; self ; end)
|
265
|
-
gem_class.send(:define_method, :bin_path) do |name, *args|
|
266
|
-
exec_name, *reqs = args
|
267
|
-
|
268
|
-
spec = nil
|
269
|
-
|
270
|
-
if exec_name
|
271
|
-
spec = specs.find { |s| s.executables.include?(exec_name) }
|
272
|
-
spec or raise Gem::Exception, "can't find executable #{exec_name}"
|
273
|
-
else
|
274
|
-
spec = specs.find { |s| s.name == name }
|
275
|
-
exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
|
276
|
-
end
|
277
|
-
|
278
|
-
File.join(spec.full_gem_path, spec.bindir, exec_name)
|
279
|
-
end
|
280
|
-
end
|
281
213
|
end
|
282
214
|
end
|
@@ -1,18 +1,6 @@
|
|
1
1
|
module Bundler
|
2
2
|
module SharedHelpers
|
3
3
|
|
4
|
-
def reverse_rubygems_kernel_mixin
|
5
|
-
# Disable rubygems' gem activation system
|
6
|
-
::Kernel.class_eval do
|
7
|
-
if private_method_defined?(:gem_original_require)
|
8
|
-
alias rubygems_require require
|
9
|
-
alias require gem_original_require
|
10
|
-
end
|
11
|
-
|
12
|
-
undef gem
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
4
|
def default_gemfile
|
17
5
|
gemfile = find_gemfile
|
18
6
|
gemfile or raise GemfileNotFound, "The default Gemfile was not found"
|
@@ -51,6 +39,87 @@ module Bundler
|
|
51
39
|
end
|
52
40
|
end
|
53
41
|
|
42
|
+
def reverse_rubygems_kernel_mixin
|
43
|
+
# Disable rubygems' gem activation system
|
44
|
+
::Kernel.class_eval do
|
45
|
+
if private_method_defined?(:gem_original_require)
|
46
|
+
alias rubygems_require require
|
47
|
+
alias require gem_original_require
|
48
|
+
end
|
49
|
+
|
50
|
+
undef gem
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cripple_rubygems(specs)
|
55
|
+
reverse_rubygems_kernel_mixin
|
56
|
+
|
57
|
+
executables = specs.map { |s| s.executables }.flatten
|
58
|
+
|
59
|
+
:: Kernel.class_eval do
|
60
|
+
private
|
61
|
+
def gem(*) ; end
|
62
|
+
end
|
63
|
+
Gem.source_index # ensure RubyGems is fully loaded
|
64
|
+
|
65
|
+
::Kernel.send(:define_method, :gem) do |dep, *reqs|
|
66
|
+
if executables.include? File.basename(caller.first.split(':').first)
|
67
|
+
return
|
68
|
+
end
|
69
|
+
opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
|
70
|
+
|
71
|
+
unless dep.respond_to?(:name) && dep.respond_to?(:version_requirements)
|
72
|
+
dep = Gem::Dependency.new(dep, reqs)
|
73
|
+
end
|
74
|
+
|
75
|
+
spec = specs.find { |s| s.name == dep.name }
|
76
|
+
|
77
|
+
if spec.nil?
|
78
|
+
e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile."
|
79
|
+
e.name = dep.name
|
80
|
+
e.version_requirement = dep.version_requirements
|
81
|
+
raise e
|
82
|
+
elsif dep !~ spec
|
83
|
+
e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \
|
84
|
+
"Make sure all dependencies are added to Gemfile."
|
85
|
+
e.name = dep.name
|
86
|
+
e.version_requirement = dep.version_requirements
|
87
|
+
raise e
|
88
|
+
end
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
# === Following hacks are to improve on the generated bin wrappers ===
|
94
|
+
|
95
|
+
# Yeah, talk about a hack
|
96
|
+
source_index_class = (class << Gem::SourceIndex ; self ; end)
|
97
|
+
source_index_class.send(:define_method, :from_gems_in) do |*args|
|
98
|
+
source_index = Gem::SourceIndex.new
|
99
|
+
source_index.spec_dirs = *args
|
100
|
+
source_index.add_specs(*specs)
|
101
|
+
source_index
|
102
|
+
end
|
103
|
+
|
104
|
+
# OMG more hacks
|
105
|
+
gem_class = (class << Gem ; self ; end)
|
106
|
+
gem_class.send(:define_method, :bin_path) do |name, *args|
|
107
|
+
exec_name, *reqs = args
|
108
|
+
|
109
|
+
spec = nil
|
110
|
+
|
111
|
+
if exec_name
|
112
|
+
spec = specs.find { |s| s.executables.include?(exec_name) }
|
113
|
+
spec or raise Gem::Exception, "can't find executable #{exec_name}"
|
114
|
+
else
|
115
|
+
spec = specs.find { |s| s.name == name }
|
116
|
+
exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}"
|
117
|
+
end
|
118
|
+
|
119
|
+
File.join(spec.full_gem_path, spec.bindir, exec_name)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
54
123
|
extend self
|
55
124
|
end
|
56
125
|
end
|
@@ -8,20 +8,20 @@ require "rubygems"
|
|
8
8
|
module Bundler
|
9
9
|
LOCKED_BY = '<%= Bundler::VERSION %>'
|
10
10
|
FINGERPRINT = <%= gemfile_fingerprint.inspect %>
|
11
|
+
AUTOREQUIRES = <%= autorequires_for_groups.inspect %>
|
11
12
|
SPECS = [
|
12
13
|
<% specs_for_lock_file.each do |spec| -%>
|
13
14
|
<%= spec.inspect %>,
|
14
15
|
<% end -%>
|
15
|
-
]
|
16
|
-
|
16
|
+
].map do |hash|
|
17
|
+
spec = eval(File.read(hash[:loaded_from]), binding, hash[:loaded_from])
|
18
|
+
spec.loaded_from = hash[:loaded_from]
|
19
|
+
spec.require_paths = hash[:load_paths]
|
20
|
+
spec
|
21
|
+
end
|
17
22
|
|
18
23
|
extend SharedHelpers
|
19
24
|
|
20
|
-
def self.cripple_ruby_gems
|
21
|
-
reverse_rubygems_kernel_mixin
|
22
|
-
patch_rubygems
|
23
|
-
end
|
24
|
-
|
25
25
|
def self.match_fingerprint
|
26
26
|
print = Digest::SHA1.hexdigest(File.read(File.expand_path('../../Gemfile', __FILE__)))
|
27
27
|
unless print == FINGERPRINT
|
@@ -32,8 +32,10 @@ module Bundler
|
|
32
32
|
def self.setup(*groups)
|
33
33
|
match_fingerprint
|
34
34
|
clean_load_path
|
35
|
+
cripple_rubygems(SPECS)
|
35
36
|
SPECS.each do |spec|
|
36
|
-
spec
|
37
|
+
Gem.loaded_specs[spec.name] = spec
|
38
|
+
$LOAD_PATH.unshift(*spec.require_paths)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
@@ -53,30 +55,6 @@ module Bundler
|
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
56
|
-
def self.patch_rubygems
|
57
|
-
Kernel.class_eval do
|
58
|
-
private
|
59
|
-
def gem(*) ; end
|
60
|
-
end
|
61
|
-
Gem.source_index # ensure RubyGems is fully loaded
|
62
|
-
specs = SPECS
|
63
|
-
|
64
|
-
::Kernel.send(:define_method, :gem) do |dep, *reqs|
|
65
|
-
opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
|
66
|
-
|
67
|
-
dep = dep.name if dep.respond_to?(:name)
|
68
|
-
unless specs.any? { |s| s[:name] == dep }
|
69
|
-
e = Gem::LoadError.new "#{dep} is not part of the bundle. Add it to Gemfile."
|
70
|
-
e.name = dep
|
71
|
-
e.version_requirement = reqs
|
72
|
-
raise e
|
73
|
-
end
|
74
|
-
|
75
|
-
true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
58
|
# Setup bundle when it's required.
|
80
|
-
cripple_ruby_gems
|
81
59
|
setup
|
82
60
|
end
|
data/lib/bundler/vendor/thor.rb
CHANGED
@@ -120,8 +120,8 @@ class Thor
|
|
120
120
|
# script = MyScript.new(args, options, config)
|
121
121
|
# script.invoke(:task, first_arg, second_arg, third_arg)
|
122
122
|
#
|
123
|
-
def start(
|
124
|
-
super do
|
123
|
+
def start(original_args=ARGV, config={})
|
124
|
+
super do |given_args|
|
125
125
|
meth = normalize_task_name(given_args.shift)
|
126
126
|
task = all_tasks[meth]
|
127
127
|
|
@@ -145,8 +145,9 @@ class Thor
|
|
145
145
|
# task_name<String>
|
146
146
|
#
|
147
147
|
def task_help(shell, task_name)
|
148
|
-
|
149
|
-
|
148
|
+
meth = normalize_task_name(task_name)
|
149
|
+
task = all_tasks[meth]
|
150
|
+
handle_no_task_error(meth) unless task
|
150
151
|
|
151
152
|
shell.say "Usage:"
|
152
153
|
shell.say " #{banner(task)}"
|
@@ -183,6 +184,10 @@ class Thor
|
|
183
184
|
end
|
184
185
|
end
|
185
186
|
|
187
|
+
def handle_argument_error(task, error) #:nodoc:
|
188
|
+
raise InvocationError, "#{task.name.inspect} was called incorrectly. Call as #{task.formatted_usage(self, banner_base == "thor").inspect}."
|
189
|
+
end
|
190
|
+
|
186
191
|
protected
|
187
192
|
|
188
193
|
# The banner for this class. You can customize it if you are invoking the
|
@@ -191,8 +196,7 @@ class Thor
|
|
191
196
|
# the namespace should be displayed as arguments.
|
192
197
|
#
|
193
198
|
def banner(task)
|
194
|
-
|
195
|
-
"#{base} #{task.formatted_usage(self, base == "thor")}"
|
199
|
+
"#{banner_base} #{task.formatted_usage(self, banner_base == "thor")}"
|
196
200
|
end
|
197
201
|
|
198
202
|
def baseclass #:nodoc:
|
@@ -38,9 +38,8 @@ class Thor
|
|
38
38
|
# config<Hash>:: Configuration for this Thor class.
|
39
39
|
#
|
40
40
|
def initialize(args=[], options={}, config={})
|
41
|
-
Thor::Arguments.parse(self.class.arguments, args)
|
42
|
-
|
43
|
-
end
|
41
|
+
args = Thor::Arguments.parse(self.class.arguments, args)
|
42
|
+
args.each { |key, value| send("#{key}=", value) }
|
44
43
|
|
45
44
|
parse_options = self.class.class_options
|
46
45
|
|
@@ -52,9 +51,9 @@ class Thor
|
|
52
51
|
array_options, hash_options = [], options
|
53
52
|
end
|
54
53
|
|
55
|
-
|
56
|
-
self.options =
|
57
|
-
self.
|
54
|
+
opts = Thor::Options.new(parse_options, hash_options)
|
55
|
+
self.options = opts.parse(array_options)
|
56
|
+
opts.check_unknown! if self.class.check_unknown_options?
|
58
57
|
end
|
59
58
|
|
60
59
|
class << self
|
@@ -109,6 +108,16 @@ class Thor
|
|
109
108
|
no_tasks { super }
|
110
109
|
end
|
111
110
|
|
111
|
+
# If you want to raise an error for unknown options, call check_unknown_options!
|
112
|
+
# This is disabled by default to allow dynamic invocations.
|
113
|
+
def check_unknown_options!
|
114
|
+
@check_unknown_options = true
|
115
|
+
end
|
116
|
+
|
117
|
+
def check_unknown_options? #:nodoc:
|
118
|
+
@check_unknown_options || false
|
119
|
+
end
|
120
|
+
|
112
121
|
# Adds an argument to the class and creates an attr_accessor for it.
|
113
122
|
#
|
114
123
|
# Arguments are different from options in several aspects. The first one
|
@@ -355,7 +364,7 @@ class Thor
|
|
355
364
|
def namespace(name=nil)
|
356
365
|
case name
|
357
366
|
when nil
|
358
|
-
@namespace ||= Thor::Util.namespace_from_thor_class(self
|
367
|
+
@namespace ||= Thor::Util.namespace_from_thor_class(self)
|
359
368
|
else
|
360
369
|
@namespace = name.to_s
|
361
370
|
end
|
@@ -366,14 +375,18 @@ class Thor
|
|
366
375
|
def start(given_args=ARGV, config={})
|
367
376
|
self.debugging = given_args.include?("--debug")
|
368
377
|
config[:shell] ||= Thor::Base.shell.new
|
369
|
-
yield
|
378
|
+
yield(given_args.dup)
|
370
379
|
rescue Thor::Error => e
|
371
|
-
|
372
|
-
|
380
|
+
debugging ? (raise e) : config[:shell].error(e.message)
|
381
|
+
exit(1) if exit_on_failure?
|
382
|
+
end
|
383
|
+
|
384
|
+
def handle_no_task_error(task) #:nodoc:
|
385
|
+
if self.banner_base == "thor"
|
386
|
+
raise UndefinedTaskError, "Could not find task #{task.inspect} in #{namespace.inspect} namespace."
|
373
387
|
else
|
374
|
-
|
388
|
+
raise UndefinedTaskError, "Could not find task #{task.inspect}."
|
375
389
|
end
|
376
|
-
exit(1) if exit_on_failure?
|
377
390
|
end
|
378
391
|
|
379
392
|
protected
|
@@ -419,7 +432,6 @@ class Thor
|
|
419
432
|
end
|
420
433
|
|
421
434
|
# Raises an error if the word given is a Thor reserved word.
|
422
|
-
#
|
423
435
|
def is_thor_reserved_word?(word, type) #:nodoc:
|
424
436
|
return false unless THOR_RESERVED_WORDS.include?(word.to_s)
|
425
437
|
raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
|
@@ -430,7 +442,6 @@ class Thor
|
|
430
442
|
# ==== Parameters
|
431
443
|
# name<Symbol>:: The name of the argument.
|
432
444
|
# options<Hash>:: Described in both class_option and method_option.
|
433
|
-
#
|
434
445
|
def build_option(name, options, scope) #:nodoc:
|
435
446
|
scope[name] = Thor::Option.new(name, options[:desc], options[:required],
|
436
447
|
options[:type], options[:default], options[:banner],
|
@@ -444,7 +455,6 @@ class Thor
|
|
444
455
|
#
|
445
456
|
# ==== Parameters
|
446
457
|
# Hash[Symbol => Object]
|
447
|
-
#
|
448
458
|
def build_options(options, scope) #:nodoc:
|
449
459
|
options.each do |key, value|
|
450
460
|
scope[key] = Thor::Option.parse(key, value)
|
@@ -454,7 +464,6 @@ class Thor
|
|
454
464
|
# Finds a task with the given name. If the task belongs to the current
|
455
465
|
# class, just return it, otherwise dup it and add the fresh copy to the
|
456
466
|
# current task hash.
|
457
|
-
#
|
458
467
|
def find_and_refresh_task(name) #:nodoc:
|
459
468
|
task = if task = tasks[name.to_s]
|
460
469
|
task
|
@@ -467,14 +476,12 @@ class Thor
|
|
467
476
|
|
468
477
|
# Everytime someone inherits from a Thor class, register the klass
|
469
478
|
# and file into baseclass.
|
470
|
-
#
|
471
479
|
def inherited(klass)
|
472
480
|
Thor::Base.register_klass_file(klass)
|
473
481
|
end
|
474
482
|
|
475
483
|
# Fire this callback whenever a method is added. Added methods are
|
476
484
|
# tracked as tasks by invoking the create_task method.
|
477
|
-
#
|
478
485
|
def method_added(meth)
|
479
486
|
meth = meth.to_s
|
480
487
|
|
@@ -495,7 +502,6 @@ class Thor
|
|
495
502
|
|
496
503
|
# Retrieves a value from superclass. If it reaches the baseclass,
|
497
504
|
# returns default.
|
498
|
-
#
|
499
505
|
def from_superclass(method, default=nil)
|
500
506
|
if self == baseclass || !superclass.respond_to?(method, true)
|
501
507
|
default
|
@@ -506,11 +512,15 @@ class Thor
|
|
506
512
|
end
|
507
513
|
|
508
514
|
# A flag that makes the process exit with status 1 if any error happens.
|
509
|
-
#
|
510
515
|
def exit_on_failure?
|
511
516
|
false
|
512
517
|
end
|
513
518
|
|
519
|
+
# Returns the base for banner.
|
520
|
+
def banner_base
|
521
|
+
@banner_base ||= $thor_runner ? "thor" : File.basename($0.split(" ").first)
|
522
|
+
end
|
523
|
+
|
514
524
|
# SIGNATURE: Sets the baseclass. This is where the superclass lookup
|
515
525
|
# finishes.
|
516
526
|
def baseclass #:nodoc:
|
@@ -5,21 +5,20 @@ class Thor
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# This method is responsible for receiving a name and find the proper
|
9
|
+
# class and task for it. The key is an optional parameter which is
|
10
|
+
# available only in class methods invocations (i.e. in Thor::Group).
|
11
11
|
def prepare_for_invocation(key, name) #:nodoc:
|
12
12
|
case name
|
13
13
|
when Symbol, String
|
14
|
-
Thor::Util.
|
14
|
+
Thor::Util.find_class_and_task_by_namespace(name.to_s)
|
15
15
|
else
|
16
16
|
name
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
# Make initializer aware of invocations and the
|
22
|
-
#
|
21
|
+
# Make initializer aware of invocations and the initialization args.
|
23
22
|
def initialize(args=[], options={}, config={}, &block) #:nodoc:
|
24
23
|
@_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] }
|
25
24
|
@_initializer = [ args, options, config ]
|
@@ -34,6 +33,8 @@ class Thor
|
|
34
33
|
# the task to be invoked, if none is given, the same values used to
|
35
34
|
# initialize the invoker are used to initialize the invoked.
|
36
35
|
#
|
36
|
+
# When no name is given, it will invoke the default task of the current class.
|
37
|
+
#
|
37
38
|
# ==== Examples
|
38
39
|
#
|
39
40
|
# class A < Thor
|
@@ -92,9 +93,9 @@ class Thor
|
|
92
93
|
#
|
93
94
|
# invoke Rspec::RR, [], :style => :foo
|
94
95
|
#
|
95
|
-
def invoke(name=nil,
|
96
|
-
|
97
|
-
args, opts, config =
|
96
|
+
def invoke(name=nil, *args)
|
97
|
+
args.unshift(nil) if Array === args.first || NilClass === args.first
|
98
|
+
task, args, opts, config = args
|
98
99
|
|
99
100
|
object, task = _prepare_for_invocation(name, task)
|
100
101
|
klass, instance = _initialize_klass_with_initializer(object, args, opts, config)
|
@@ -121,15 +122,13 @@ class Thor
|
|
121
122
|
protected
|
122
123
|
|
123
124
|
# Configuration values that are shared between invocations.
|
124
|
-
#
|
125
125
|
def _shared_configuration #:nodoc:
|
126
126
|
{ :invocations => @_invocations }
|
127
127
|
end
|
128
128
|
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
129
|
+
# This method can receive several different types of arguments and it's then
|
130
|
+
# responsible to normalize them by returning the object where the task should
|
131
|
+
# be invoked and a Thor::Task object.
|
133
132
|
def _prepare_for_invocation(name, sent_task=nil) #:nodoc:
|
134
133
|
if name.is_a?(Thor::Task)
|
135
134
|
task = name
|
@@ -147,18 +146,16 @@ class Thor
|
|
147
146
|
|
148
147
|
# Check if the object given is a Thor class object and get a task object
|
149
148
|
# for it.
|
150
|
-
#
|
151
149
|
def _validate_task(object, task) #:nodoc:
|
152
150
|
klass = object.is_a?(Class) ? object : object.class
|
153
151
|
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
154
152
|
|
155
|
-
task ||= klass.default_task if klass
|
153
|
+
task ||= klass.default_task if klass.respond_to?(:default_task)
|
156
154
|
task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
|
157
155
|
task
|
158
156
|
end
|
159
157
|
|
160
158
|
# Initialize klass using values stored in the @_initializer.
|
161
|
-
#
|
162
159
|
def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc:
|
163
160
|
if object.is_a?(Class)
|
164
161
|
klass = object
|
@@ -16,8 +16,9 @@ class Thor
|
|
16
16
|
return arguments, args[Range.new(arguments.size, -1)]
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.parse(
|
20
|
-
|
19
|
+
def self.parse(*args)
|
20
|
+
to_parse = args.pop
|
21
|
+
new(*args).parse(to_parse)
|
21
22
|
end
|
22
23
|
|
23
24
|
# Takes an array of Thor::Argument objects.
|
@@ -116,7 +117,7 @@ class Thor
|
|
116
117
|
return shift if peek.is_a?(Numeric)
|
117
118
|
|
118
119
|
unless peek =~ NUMERIC && $& == peek
|
119
|
-
raise MalformattedArgumentError, "
|
120
|
+
raise MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}"
|
120
121
|
end
|
121
122
|
|
122
123
|
$&.index('.') ? shift.to_f : shift.to_i
|
@@ -137,7 +138,7 @@ class Thor
|
|
137
138
|
end.join("', '")
|
138
139
|
|
139
140
|
class_name = self.class.name.split('::').last.downcase
|
140
|
-
raise RequiredArgumentMissingError, "
|
141
|
+
raise RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'"
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
@@ -55,10 +55,6 @@ class Thor
|
|
55
55
|
value
|
56
56
|
elsif required = (value == :required)
|
57
57
|
:string
|
58
|
-
elsif value == :optional
|
59
|
-
# TODO Remove this warning in the future.
|
60
|
-
warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean."
|
61
|
-
:boolean
|
62
58
|
end
|
63
59
|
when TrueClass, FalseClass
|
64
60
|
:boolean
|
@@ -10,7 +10,6 @@ class Thor
|
|
10
10
|
SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
|
11
11
|
|
12
12
|
# Receives a hash and makes it switches.
|
13
|
-
#
|
14
13
|
def self.to_switches(options)
|
15
14
|
options.map do |key, value|
|
16
15
|
case value
|
@@ -28,12 +27,18 @@ class Thor
|
|
28
27
|
end.join(" ")
|
29
28
|
end
|
30
29
|
|
31
|
-
# Takes a hash of Thor::Option
|
32
|
-
|
33
|
-
|
34
|
-
options = options.values
|
30
|
+
# Takes a hash of Thor::Option and a hash with defaults.
|
31
|
+
def initialize(hash_options={}, defaults={})
|
32
|
+
options = hash_options.values
|
35
33
|
super(options)
|
36
|
-
|
34
|
+
|
35
|
+
# Add defaults
|
36
|
+
defaults.each do |key, value|
|
37
|
+
@assigns[key.to_s] = value
|
38
|
+
@non_assigned_required.delete(hash_options[key])
|
39
|
+
end
|
40
|
+
|
41
|
+
@shorts, @switches, @unknown = {}, {}, []
|
37
42
|
|
38
43
|
options.each do |option|
|
39
44
|
@switches[option.switch_name] = option
|
@@ -61,16 +66,24 @@ class Thor
|
|
61
66
|
end
|
62
67
|
|
63
68
|
switch = normalize_switch(switch)
|
64
|
-
|
65
|
-
|
69
|
+
option = switch_option(switch)
|
66
70
|
@assigns[option.human_name] = parse_peek(switch, option)
|
71
|
+
elsif peek =~ /^\-/
|
72
|
+
@unknown << shift
|
67
73
|
else
|
68
74
|
shift
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
72
78
|
check_requirement!
|
73
|
-
|
79
|
+
|
80
|
+
assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
|
81
|
+
assigns.freeze
|
82
|
+
assigns
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_unknown!
|
86
|
+
raise UnknownArgumentError, "Unknown switches '#{@unknown.join(', ')}'" unless @unknown.empty?
|
74
87
|
end
|
75
88
|
|
76
89
|
protected
|
@@ -130,7 +143,7 @@ class Thor
|
|
130
143
|
elsif option.string? && !option.required?
|
131
144
|
return option.human_name # Return the option name
|
132
145
|
else
|
133
|
-
raise MalformattedArgumentError, "
|
146
|
+
raise MalformattedArgumentError, "No value provided for option '#{switch}'"
|
134
147
|
end
|
135
148
|
end
|
136
149
|
|
@@ -9,10 +9,11 @@ class Thor
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def run(instance, args=[])
|
12
|
-
|
13
|
-
|
12
|
+
if (instance.methods & [name.to_s, name.to_sym]).empty?
|
13
|
+
super
|
14
|
+
else
|
15
|
+
instance.class.handle_no_task_error(name)
|
14
16
|
end
|
15
|
-
super
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -28,14 +29,14 @@ class Thor
|
|
28
29
|
# By default, a task invokes a method in the thor class. You can change this
|
29
30
|
# implementation to create custom tasks.
|
30
31
|
def run(instance, args=[])
|
31
|
-
|
32
|
-
|
32
|
+
public_method?(instance) ?
|
33
|
+
instance.send(name, *args) : instance.class.handle_no_task_error(name)
|
33
34
|
rescue ArgumentError => e
|
34
|
-
|
35
|
-
|
35
|
+
handle_argument_error?(instance, e, caller) ?
|
36
|
+
instance.class.handle_argument_error(self, e) : (raise e)
|
36
37
|
rescue NoMethodError => e
|
37
|
-
|
38
|
-
|
38
|
+
handle_no_method_error?(instance, e, caller) ?
|
39
|
+
instance.class.handle_no_task_error(name) : (raise e)
|
39
40
|
end
|
40
41
|
|
41
42
|
# Returns the formatted usage by injecting given required arguments
|
@@ -68,6 +69,10 @@ class Thor
|
|
68
69
|
|
69
70
|
protected
|
70
71
|
|
72
|
+
def not_debugging?(instance)
|
73
|
+
!(instance.class.respond_to?(:debugging) && instance.class.debugging)
|
74
|
+
end
|
75
|
+
|
71
76
|
def required_options
|
72
77
|
@required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
|
73
78
|
end
|
@@ -83,28 +88,14 @@ class Thor
|
|
83
88
|
saned -= caller
|
84
89
|
end
|
85
90
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
if backtrace.empty? && e.message =~ /wrong number of arguments/
|
90
|
-
if instance.is_a?(Thor::Group)
|
91
|
-
raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?"
|
92
|
-
else
|
93
|
-
raise InvocationError, "'#{name}' was called incorrectly. Call as " <<
|
94
|
-
"'#{formatted_usage(instance.class)}'"
|
95
|
-
end
|
96
|
-
else
|
97
|
-
raise e
|
98
|
-
end
|
91
|
+
def handle_argument_error?(instance, error, caller)
|
92
|
+
not_debugging?(instance) && error.message =~ /wrong number of arguments/ &&
|
93
|
+
sans_backtrace(error.backtrace, caller).empty?
|
99
94
|
end
|
100
95
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
"doesn't have a '#{name}' task"
|
105
|
-
else
|
106
|
-
raise e
|
107
|
-
end
|
96
|
+
def handle_no_method_error?(instance, error, caller)
|
97
|
+
not_debugging?(instance) &&
|
98
|
+
error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
|
108
99
|
end
|
109
100
|
|
110
101
|
end
|
@@ -23,10 +23,7 @@ class Thor
|
|
23
23
|
#
|
24
24
|
def self.find_by_namespace(namespace)
|
25
25
|
namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/
|
26
|
-
|
27
|
-
Thor::Base.subclasses.find do |klass|
|
28
|
-
klass.namespace == namespace
|
29
|
-
end
|
26
|
+
Thor::Base.subclasses.find { |klass| klass.namespace == namespace }
|
30
27
|
end
|
31
28
|
|
32
29
|
# Receives a constant and converts it to a Thor namespace. Since Thor tasks
|
@@ -43,10 +40,9 @@ class Thor
|
|
43
40
|
# ==== Returns
|
44
41
|
# String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz"
|
45
42
|
#
|
46
|
-
def self.namespace_from_thor_class(constant
|
43
|
+
def self.namespace_from_thor_class(constant)
|
47
44
|
constant = constant.to_s.gsub(/^Thor::Sandbox::/, "")
|
48
45
|
constant = snake_case(constant).squeeze(":")
|
49
|
-
constant.gsub!(/^default/, '') if remove_default
|
50
46
|
constant
|
51
47
|
end
|
52
48
|
|
@@ -132,13 +128,7 @@ class Thor
|
|
132
128
|
# ==== Parameters
|
133
129
|
# namespace<String>
|
134
130
|
#
|
135
|
-
|
136
|
-
# Thor::Error:: raised if the namespace cannot be found.
|
137
|
-
#
|
138
|
-
# Thor::Error:: raised if the namespace evals to a class which does not
|
139
|
-
# inherit from Thor or Thor::Group.
|
140
|
-
#
|
141
|
-
def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true)
|
131
|
+
def self.find_class_and_task_by_namespace(namespace)
|
142
132
|
if namespace.include?(?:)
|
143
133
|
pieces = namespace.split(":")
|
144
134
|
task = pieces.pop
|
@@ -149,7 +139,14 @@ class Thor
|
|
149
139
|
klass, task = Thor::Util.find_by_namespace(namespace), nil
|
150
140
|
end
|
151
141
|
|
152
|
-
|
142
|
+
return klass, task
|
143
|
+
end
|
144
|
+
|
145
|
+
# The same as namespace_to_thor_class_and_task!, but raises an error if a klass
|
146
|
+
# could not be found.
|
147
|
+
def self.find_class_and_task_by_namespace!(namespace)
|
148
|
+
klass, task = find_class_and_task_by_namespace(namespace)
|
149
|
+
raise Error, "Could not find namespace or task #{namespace.inspect}." unless klass
|
153
150
|
return klass, task
|
154
151
|
end
|
155
152
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carl Lerche
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-02-
|
13
|
+
date: 2010-02-17 00:00:00 -08:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|