bundler 1.0.0.rc.2 → 1.0.0.rc.3
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/CHANGELOG.md +18 -0
- data/README.md +3 -1
- data/lib/bundler.rb +7 -11
- data/lib/bundler/cli.rb +32 -15
- data/lib/bundler/definition.rb +29 -14
- data/lib/bundler/dependency.rb +2 -1
- data/lib/bundler/dsl.rb +3 -1
- data/lib/bundler/environment.rb +1 -1
- data/lib/bundler/installer.rb +3 -3
- data/lib/bundler/lockfile_parser.rb +2 -1
- data/lib/bundler/resolver.rb +7 -1
- data/lib/bundler/runtime.rb +1 -1
- data/lib/bundler/shared_helpers.rb +4 -0
- data/lib/bundler/source.rb +20 -13
- data/lib/bundler/vendor/thor.rb +74 -49
- data/lib/bundler/vendor/thor/base.rb +26 -10
- data/lib/bundler/vendor/thor/invocation.rb +45 -57
- data/lib/bundler/vendor/thor/parser/options.rb +2 -0
- data/lib/bundler/vendor/thor/shell.rb +1 -1
- data/lib/bundler/vendor/thor/shell/basic.rb +5 -3
- data/lib/bundler/vendor/thor/version.rb +1 -1
- data/lib/bundler/version.rb +1 -1
- metadata +3 -3
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 1.0.0.rc.2 (August 3, 2010)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- Deprecate --production flag for --deployment, since the former
|
6
|
+
was causing confusion with the :production group
|
7
|
+
- Add --gemfile option to `bundle check`
|
8
|
+
- Reduce memory usage of `bundle install` by 2-4x
|
9
|
+
- Improve message from `bundle check` under various conditions
|
10
|
+
- Better error when a changed Gemfile conflicts with Gemfile.lock
|
11
|
+
|
12
|
+
Bugfixes:
|
13
|
+
|
14
|
+
- Create bin/ directory if it is missing, then install binstubs
|
15
|
+
- Error nicely on the edge case of a pinned gem with no spec
|
16
|
+
- Do not require gems for other platforms
|
17
|
+
- Update git sources along with the gems they contain
|
18
|
+
|
1
19
|
## 1.0.0.rc.2 (July 29, 2010)
|
2
20
|
|
3
21
|
- `bundle install path` was causing confusion, so we now print
|
data/README.md
CHANGED
@@ -135,11 +135,13 @@ If you are still having problems, please report bugs to the github issue tracker
|
|
135
135
|
|
136
136
|
The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket:
|
137
137
|
|
138
|
-
- Whether you have locked or not
|
139
138
|
- What version of bundler you are using
|
140
139
|
- What version of Ruby you are using
|
141
140
|
- Whether you are using RVM, and if so what version
|
142
141
|
- Your Gemfile
|
142
|
+
- Your Gemfile.lock
|
143
|
+
- If you are on 0.9, whether you have locked or not
|
144
|
+
- If you are on 1.0, the result of `bundle config`
|
143
145
|
- The command you ran to generate exception(s)
|
144
146
|
- The exception backtrace(s)
|
145
147
|
|
data/lib/bundler.rb
CHANGED
@@ -60,6 +60,7 @@ module Bundler
|
|
60
60
|
|
61
61
|
class << self
|
62
62
|
attr_writer :ui, :bundle_path
|
63
|
+
attr_accessor :deployment
|
63
64
|
|
64
65
|
def configure
|
65
66
|
@configured ||= begin
|
@@ -68,14 +69,6 @@ module Bundler
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
def production?
|
72
|
-
@production
|
73
|
-
end
|
74
|
-
|
75
|
-
def production=(value)
|
76
|
-
@production = value
|
77
|
-
end
|
78
|
-
|
79
72
|
def ui
|
80
73
|
@ui ||= UI.new
|
81
74
|
end
|
@@ -127,8 +120,7 @@ module Bundler
|
|
127
120
|
@definition ||= begin
|
128
121
|
configure
|
129
122
|
upgrade_lockfile
|
130
|
-
|
131
|
-
Definition.build(default_gemfile, lockfile, unlock)
|
123
|
+
Definition.build(default_gemfile, default_lockfile, unlock)
|
132
124
|
end
|
133
125
|
end
|
134
126
|
|
@@ -184,6 +176,10 @@ module Bundler
|
|
184
176
|
SharedHelpers.default_gemfile
|
185
177
|
end
|
186
178
|
|
179
|
+
def default_lockfile
|
180
|
+
SharedHelpers.default_lockfile
|
181
|
+
end
|
182
|
+
|
187
183
|
WINDOWS = Config::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)!
|
188
184
|
NULL = WINDOWS ? "NUL" : "/dev/null"
|
189
185
|
|
@@ -223,7 +219,7 @@ module Bundler
|
|
223
219
|
end
|
224
220
|
|
225
221
|
def upgrade_lockfile
|
226
|
-
lockfile =
|
222
|
+
lockfile = default_lockfile
|
227
223
|
if lockfile.exist? && lockfile.read(3) == "---"
|
228
224
|
Bundler.ui.warn "Detected Gemfile.lock generated by 0.9, deleting..."
|
229
225
|
lockfile.rmtree
|
data/lib/bundler/cli.rb
CHANGED
@@ -58,8 +58,17 @@ module Bundler
|
|
58
58
|
all gems are found, Bundler prints a success message and exits with a status of 0.
|
59
59
|
If not, the first missing gem is listed and Bundler exits status 1.
|
60
60
|
D
|
61
|
+
method_option "gemfile", :type => :string, :banner =>
|
62
|
+
"Use the specified gemfile instead of Gemfile"
|
61
63
|
def check
|
62
|
-
|
64
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile]
|
65
|
+
begin
|
66
|
+
not_installed = Bundler.definition.missing_specs
|
67
|
+
rescue GemNotFound, VersionConflict
|
68
|
+
Bundler.ui.error "Your Gemfile's dependencies could not be satisfied"
|
69
|
+
Bundler.ui.warn "Install missing gems with `bundle install`"
|
70
|
+
exit 1
|
71
|
+
end
|
63
72
|
|
64
73
|
if not_installed.any?
|
65
74
|
Bundler.ui.error "The following gems are missing"
|
@@ -103,20 +112,28 @@ module Bundler
|
|
103
112
|
"Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
|
104
113
|
method_option "system", :type => :boolean, :banner =>
|
105
114
|
"Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
|
106
|
-
method_option "
|
115
|
+
method_option "deployment", :type => :boolean, :banner =>
|
107
116
|
"Install using defaults tuned for deployment environments"
|
117
|
+
method_option "production", :type => :boolean, :banner =>
|
118
|
+
"Deprecated, please use --deployment instead"
|
108
119
|
def install(path = nil)
|
109
120
|
opts = options.dup
|
110
121
|
opts[:without] ||= []
|
111
122
|
opts[:without].map! { |g| g.to_sym }
|
112
123
|
|
113
|
-
if
|
124
|
+
if opts[:production]
|
125
|
+
opts[:deployment] = true
|
126
|
+
Bundler.ui.warn "The --production option is deprecated, and will be removed in " \
|
127
|
+
"the final release of Bundler 1.0. Please use --deployment instead."
|
128
|
+
end
|
129
|
+
|
130
|
+
if (path || opts[:path] || opts[:deployment]) && opts[:system]
|
114
131
|
Bundler.ui.error "You have specified both a path to install your gems to, \n" \
|
115
132
|
"as well as --system. Please choose."
|
116
133
|
exit 1
|
117
134
|
end
|
118
135
|
|
119
|
-
if path &&
|
136
|
+
if path && opts[:path]
|
120
137
|
Bundler.ui.error "You have specified a path via `bundle install #{path}` as well as\n" \
|
121
138
|
"by `bundle install --path #{options[:path]}`. These options are\n" \
|
122
139
|
"equivalent, so please use one or the other."
|
@@ -132,26 +149,26 @@ module Bundler
|
|
132
149
|
exit 1
|
133
150
|
end
|
134
151
|
|
135
|
-
if opts[:
|
136
|
-
Bundler.
|
152
|
+
if opts[:deployment]
|
153
|
+
Bundler.deployment = true
|
137
154
|
|
138
|
-
unless Bundler.
|
139
|
-
raise ProductionError, "The --
|
140
|
-
"
|
141
|
-
"
|
155
|
+
unless Bundler.default_lockfile.exist?
|
156
|
+
raise ProductionError, "The --deployment flag requires a Gemfile.lock. Please make " \
|
157
|
+
"sure you have checked your Gemfile.lock into version control " \
|
158
|
+
"before deploying."
|
142
159
|
end
|
143
160
|
|
144
161
|
if Bundler.root.join("vendor/cache").exist?
|
145
|
-
opts[
|
162
|
+
opts[:local] = true
|
146
163
|
end
|
147
164
|
end
|
148
165
|
|
149
166
|
# Can't use Bundler.settings for this because settings needs gemfile.dirname
|
150
|
-
ENV['BUNDLE_GEMFILE'] = opts[:gemfile] if opts[:gemfile]
|
151
|
-
Bundler.settings[:path] = nil if
|
152
|
-
Bundler.settings[:path] = "vendor/bundle" if
|
167
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path(opts[:gemfile]) if opts[:gemfile]
|
168
|
+
Bundler.settings[:path] = nil if opts[:system]
|
169
|
+
Bundler.settings[:path] = "vendor/bundle" if opts[:deployment]
|
153
170
|
Bundler.settings[:path] = path if path
|
154
|
-
Bundler.settings[:path] =
|
171
|
+
Bundler.settings[:path] = opts[:path] if opts[:path]
|
155
172
|
Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs]
|
156
173
|
Bundler.settings[:disable_shared_gems] = '1' if Bundler.settings[:path]
|
157
174
|
Bundler.settings.without = opts[:without]
|
data/lib/bundler/definition.rb
CHANGED
@@ -65,11 +65,10 @@ module Bundler
|
|
65
65
|
@unlock[:sources] ||= []
|
66
66
|
|
67
67
|
current_platform = Gem.platforms.map { |p| generic(p) }.compact.last
|
68
|
+
@new_platform = !@platforms.include?(current_platform)
|
68
69
|
@platforms |= [current_platform]
|
69
70
|
|
70
|
-
if Bundler.
|
71
|
-
ensure_equivalent_gemfile_and_lockfile
|
72
|
-
end
|
71
|
+
ensure_equivalent_gemfile_and_lockfile if Bundler.deployment
|
73
72
|
|
74
73
|
converge_sources
|
75
74
|
converge_dependencies
|
@@ -101,6 +100,10 @@ module Bundler
|
|
101
100
|
end
|
102
101
|
end
|
103
102
|
|
103
|
+
def new_platform?
|
104
|
+
@new_platform
|
105
|
+
end
|
106
|
+
|
104
107
|
def missing_specs
|
105
108
|
missing = []
|
106
109
|
resolve.materialize(requested_dependencies, missing)
|
@@ -128,18 +131,14 @@ module Bundler
|
|
128
131
|
def resolve
|
129
132
|
@resolve ||= begin
|
130
133
|
converge_locked_specs
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
source_requirements =
|
135
|
-
dependencies.each do |dep|
|
136
|
-
next unless dep.source
|
137
|
-
source_requirements[dep.name] = dep.source.specs
|
138
|
-
end
|
139
|
-
|
140
|
-
# Run a resolve against the locally available gems
|
141
|
-
@last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, @last_resolve)
|
134
|
+
source_requirements = {}
|
135
|
+
dependencies.each do |dep|
|
136
|
+
next unless dep.source
|
137
|
+
source_requirements[dep.name] = dep.source.specs
|
142
138
|
end
|
139
|
+
|
140
|
+
# Run a resolve against the locally available gems
|
141
|
+
@last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, @last_resolve)
|
143
142
|
end
|
144
143
|
end
|
145
144
|
|
@@ -305,6 +304,11 @@ module Bundler
|
|
305
304
|
if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
|
306
305
|
deps << dep
|
307
306
|
elsif dep.source.is_a?(Source::Path) && (!locked_dep || dep.source != locked_dep.source)
|
307
|
+
@last_resolve.each do |s|
|
308
|
+
@unlock[:gems] << s.name if s.source == dep.source
|
309
|
+
end
|
310
|
+
|
311
|
+
dep.source.unlock! if dep.source.respond_to?(:unlock!)
|
308
312
|
dep.source.specs.each { |s| @unlock[:gems] << s.name }
|
309
313
|
end
|
310
314
|
end
|
@@ -335,6 +339,17 @@ module Bundler
|
|
335
339
|
|
336
340
|
resolve = SpecSet.new(converged)
|
337
341
|
resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems])
|
342
|
+
diff = @last_resolve.to_a - resolve.to_a
|
343
|
+
|
344
|
+
# Now, we unlock any sources that do not have anymore gems pinned to it
|
345
|
+
@sources.each do |source|
|
346
|
+
next unless source.respond_to?(:unlock!)
|
347
|
+
|
348
|
+
unless resolve.any? { |s| s.source == source }
|
349
|
+
source.unlock! if diff.any? { |s| s.source == source }
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
338
353
|
@last_resolve = resolve
|
339
354
|
end
|
340
355
|
|
data/lib/bundler/dependency.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems/dependency'
|
2
2
|
require 'bundler/shared_helpers'
|
3
|
+
require 'bundler/rubygems_ext'
|
3
4
|
|
4
5
|
module Bundler
|
5
6
|
class Dependency < Gem::Dependency
|
@@ -16,7 +17,7 @@ module Bundler
|
|
16
17
|
:mri_19 => Gem::Platform::RUBY,
|
17
18
|
:jruby => Gem::Platform::JAVA,
|
18
19
|
:mswin => Gem::Platform::MSWIN
|
19
|
-
}
|
20
|
+
}.freeze
|
20
21
|
|
21
22
|
def initialize(name, version, options = {}, &blk)
|
22
23
|
super(name, version)
|
data/lib/bundler/dsl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'bundler/dependency'
|
2
|
+
|
1
3
|
module Bundler
|
2
4
|
class Dsl
|
3
5
|
def self.evaluate(gemfile)
|
@@ -6,7 +8,7 @@ module Bundler
|
|
6
8
|
builder.to_definition
|
7
9
|
end
|
8
10
|
|
9
|
-
VALID_PLATFORMS =
|
11
|
+
VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
|
10
12
|
|
11
13
|
def initialize
|
12
14
|
@rubygems_source = Source::Rubygems.new
|
data/lib/bundler/environment.rb
CHANGED
data/lib/bundler/installer.rb
CHANGED
@@ -15,10 +15,10 @@ module Bundler
|
|
15
15
|
return
|
16
16
|
end
|
17
17
|
|
18
|
-
if Bundler.
|
18
|
+
if Bundler.default_lockfile.exist? && !options["update"]
|
19
19
|
begin
|
20
|
-
|
21
|
-
local = true unless missing_specs.any?
|
20
|
+
tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
|
21
|
+
local = true unless tmpdef.new_platform? || tmpdef.missing_specs.any?
|
22
22
|
rescue BundlerError
|
23
23
|
end
|
24
24
|
end
|
@@ -66,7 +66,8 @@ module Bundler
|
|
66
66
|
dep = Bundler::Dependency.new(name, version)
|
67
67
|
|
68
68
|
if pinned && dep.name != 'bundler'
|
69
|
-
|
69
|
+
spec = @specs.find { |s| s.name == dep.name }
|
70
|
+
dep.source = spec.source if spec
|
70
71
|
|
71
72
|
# Path sources need to know what the default name / version
|
72
73
|
# to use in the case that there are no gemspecs present. A fake
|
data/lib/bundler/resolver.rb
CHANGED
@@ -254,7 +254,13 @@ module Bundler
|
|
254
254
|
|
255
255
|
if matching_versions.empty?
|
256
256
|
if current.required_by.empty?
|
257
|
-
if current.
|
257
|
+
if base = @base[current.name] and !base.empty?
|
258
|
+
version = base.first.version
|
259
|
+
message = "You have requested:\n" \
|
260
|
+
" #{current.name} #{current.requirement}\n\n" \
|
261
|
+
"The bundle currently has #{current.name} locked at #{version}.\n" \
|
262
|
+
"Try running `bundle update #{current.name}`"
|
263
|
+
elsif current.source
|
258
264
|
name = current.name
|
259
265
|
versions = @source_requirements[name][name].map { |s| s.version }
|
260
266
|
message = "Could not find gem '#{current}' in #{current.source}.\n"
|
data/lib/bundler/runtime.rb
CHANGED
@@ -51,7 +51,7 @@ module Bundler
|
|
51
51
|
@definition.dependencies.each do |dep|
|
52
52
|
# Skip the dependency if it is not in any of the requested
|
53
53
|
# groups
|
54
|
-
next unless (dep.groups & groups).any?
|
54
|
+
next unless ((dep.groups & groups).any? && dep.current_platform?)
|
55
55
|
|
56
56
|
required_file = nil
|
57
57
|
|
data/lib/bundler/source.rb
CHANGED
@@ -71,8 +71,12 @@ module Bundler
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def fetch(spec)
|
74
|
-
|
75
|
-
|
74
|
+
spec, uri = @spec_fetch_map[spec.full_name]
|
75
|
+
if spec
|
76
|
+
path = download_gem_from_uri(spec, uri)
|
77
|
+
s = Gem::Format.from_file_by_path(path).spec
|
78
|
+
spec.__swap__(s)
|
79
|
+
end
|
76
80
|
end
|
77
81
|
|
78
82
|
def install(spec)
|
@@ -101,7 +105,8 @@ module Bundler
|
|
101
105
|
sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Gem.dir}/gems/"
|
102
106
|
sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Gem.dir}/specifications/"
|
103
107
|
spec.executables.each do |exe|
|
104
|
-
|
108
|
+
sudo "mkdir -p #{Gem.dir}/bin"
|
109
|
+
sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Gem.dir}/bin/"
|
105
110
|
end
|
106
111
|
end
|
107
112
|
|
@@ -195,7 +200,6 @@ module Bundler
|
|
195
200
|
def remote_specs
|
196
201
|
@remote_specs ||= begin
|
197
202
|
idx = Index.new
|
198
|
-
remotes = self.remotes.map { |uri| uri.to_s }
|
199
203
|
old = Gem.sources
|
200
204
|
|
201
205
|
remotes.each do |uri|
|
@@ -206,12 +210,7 @@ module Bundler
|
|
206
210
|
next if name == 'bundler'
|
207
211
|
spec = RemoteSpecification.new(name, version, platform, uri)
|
208
212
|
spec.source = self
|
209
|
-
|
210
|
-
@spec_fetch_map[spec.full_name] = lambda do
|
211
|
-
path = download_gem_from_uri(spec, uri)
|
212
|
-
s = Gem::Format.from_file_by_path(path).spec
|
213
|
-
spec.__swap__(s)
|
214
|
-
end
|
213
|
+
@spec_fetch_map[spec.full_name] = [spec, uri]
|
215
214
|
idx << spec
|
216
215
|
end
|
217
216
|
end
|
@@ -332,9 +331,17 @@ module Bundler
|
|
332
331
|
rescue ArgumentError, SyntaxError, Gem::EndOfYAMLException, Gem::Exception
|
333
332
|
begin
|
334
333
|
eval(File.read(file.basename), TOPLEVEL_BINDING, file.expand_path.to_s)
|
335
|
-
rescue LoadError
|
336
|
-
|
337
|
-
|
334
|
+
rescue LoadError => e
|
335
|
+
original_line = e.backtrace.find { |line| line.include?(file.to_s) }
|
336
|
+
msg = "There was a LoadError while evaluating #{file.basename}:\n #{e.message}"
|
337
|
+
msg << " from\n #{original_line}" if original_line
|
338
|
+
msg << "\n"
|
339
|
+
|
340
|
+
if RUBY_VERSION >= "1.9.0"
|
341
|
+
msg << "\nDoes it try to require a relative path? That doesn't work in Ruby 1.9."
|
342
|
+
end
|
343
|
+
|
344
|
+
raise GemspecError, msg
|
338
345
|
end
|
339
346
|
end
|
340
347
|
end
|
data/lib/bundler/vendor/thor.rb
CHANGED
@@ -126,42 +126,6 @@ class Thor
|
|
126
126
|
build_option(name, options, scope)
|
127
127
|
end
|
128
128
|
|
129
|
-
# Parses the task and options from the given args, instantiate the class
|
130
|
-
# and invoke the task. This method is used when the arguments must be parsed
|
131
|
-
# from an array. If you are inside Ruby and want to use a Thor class, you
|
132
|
-
# can simply initialize it:
|
133
|
-
#
|
134
|
-
# script = MyScript.new(args, options, config)
|
135
|
-
# script.invoke(:task, first_arg, second_arg, third_arg)
|
136
|
-
#
|
137
|
-
def start(original_args=ARGV, config={})
|
138
|
-
@@original_args = original_args
|
139
|
-
|
140
|
-
super do |given_args|
|
141
|
-
meth = given_args.first.to_s
|
142
|
-
|
143
|
-
if !meth.empty? && (map[meth] || meth !~ /^\-/)
|
144
|
-
given_args.shift
|
145
|
-
else
|
146
|
-
meth = nil
|
147
|
-
end
|
148
|
-
|
149
|
-
meth = normalize_task_name(meth)
|
150
|
-
task = all_tasks[meth]
|
151
|
-
|
152
|
-
if task
|
153
|
-
args, opts = Thor::Options.split(given_args)
|
154
|
-
config.merge!(:task_options => task.options)
|
155
|
-
else
|
156
|
-
args, opts = given_args, {}
|
157
|
-
end
|
158
|
-
|
159
|
-
task ||= Thor::DynamicTask.new(meth)
|
160
|
-
trailing = args[Range.new(arguments.size, -1)]
|
161
|
-
new(args, opts, config).invoke(task, trailing || [])
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
129
|
# Prints help information for the given task.
|
166
130
|
#
|
167
131
|
# ==== Parameters
|
@@ -215,25 +179,81 @@ class Thor
|
|
215
179
|
end
|
216
180
|
|
217
181
|
def subcommands
|
218
|
-
|
182
|
+
@subcommands ||= from_superclass(:subcommands, [])
|
219
183
|
end
|
220
184
|
|
221
185
|
def subcommand(subcommand, subcommand_class)
|
222
|
-
|
223
|
-
subcommands[subcommand] = subcommand_class
|
186
|
+
self.subcommands << subcommand.to_s
|
224
187
|
subcommand_class.subcommand_help subcommand
|
225
|
-
define_method(subcommand) { |*
|
188
|
+
define_method(subcommand) { |*args| invoke subcommand_class, args }
|
189
|
+
end
|
190
|
+
|
191
|
+
# Extend check unknown options to accept a hash of conditions.
|
192
|
+
#
|
193
|
+
# === Parameters
|
194
|
+
# options<Hash>: A hash containing :only and/or :except keys
|
195
|
+
def check_unknown_options!(options={})
|
196
|
+
@check_unknown_options ||= Hash.new
|
197
|
+
options.each do |key, value|
|
198
|
+
if value
|
199
|
+
@check_unknown_options[key] = Array(value)
|
200
|
+
else
|
201
|
+
@check_unknown_options.delete(key)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
@check_unknown_options
|
205
|
+
end
|
206
|
+
|
207
|
+
# Overwrite check_unknown_options? to take subcommands and options into account.
|
208
|
+
def check_unknown_options?(config) #:nodoc:
|
209
|
+
options = check_unknown_options
|
210
|
+
return false unless options
|
211
|
+
|
212
|
+
task = config[:current_task]
|
213
|
+
return true unless task
|
214
|
+
|
215
|
+
name = task.name
|
216
|
+
|
217
|
+
if subcommands.include?(name)
|
218
|
+
false
|
219
|
+
elsif options[:except]
|
220
|
+
!options[:except].include?(name.to_sym)
|
221
|
+
elsif options[:only]
|
222
|
+
options[:only].include?(name.to_sym)
|
223
|
+
else
|
224
|
+
true
|
225
|
+
end
|
226
226
|
end
|
227
227
|
|
228
228
|
protected
|
229
229
|
|
230
|
+
# The method responsible for dispatching given the args.
|
231
|
+
def dispatch(meth, given_args, given_opts, config) #:nodoc:
|
232
|
+
meth ||= retrieve_task_name(given_args)
|
233
|
+
task = all_tasks[normalize_task_name(meth)]
|
234
|
+
|
235
|
+
if task
|
236
|
+
args, opts = Thor::Options.split(given_args)
|
237
|
+
else
|
238
|
+
args, opts = given_args, nil
|
239
|
+
task = Thor::DynamicTask.new(meth)
|
240
|
+
end
|
241
|
+
|
242
|
+
opts = given_opts || opts || []
|
243
|
+
config.merge!(:current_task => task, :task_options => task.options)
|
244
|
+
|
245
|
+
trailing = args[Range.new(arguments.size, -1)]
|
246
|
+
new(args, opts, config).invoke_task(task, trailing || [])
|
247
|
+
end
|
248
|
+
|
230
249
|
# The banner for this class. You can customize it if you are invoking the
|
231
250
|
# thor class by another ways which is not the Thor::Runner. It receives
|
232
251
|
# the task that is going to be invoked and a boolean which indicates if
|
233
252
|
# the namespace should be displayed as arguments.
|
234
253
|
#
|
235
254
|
def banner(task, namespace = nil, subcommand = false)
|
236
|
-
|
255
|
+
base = File.basename($0).split(" ").first
|
256
|
+
"#{base} #{task.formatted_usage(self, $thor_runner, subcommand)}"
|
237
257
|
end
|
238
258
|
|
239
259
|
def baseclass #:nodoc:
|
@@ -243,10 +263,10 @@ class Thor
|
|
243
263
|
def create_task(meth) #:nodoc:
|
244
264
|
if @usage && @desc
|
245
265
|
base_class = @hide ? Thor::HiddenTask : Thor::Task
|
246
|
-
tasks[meth
|
266
|
+
tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
|
247
267
|
@usage, @desc, @long_desc, @method_options, @hide = nil
|
248
268
|
true
|
249
|
-
elsif self.all_tasks[meth
|
269
|
+
elsif self.all_tasks[meth] || meth == "method_missing"
|
250
270
|
true
|
251
271
|
else
|
252
272
|
puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
|
@@ -261,9 +281,19 @@ class Thor
|
|
261
281
|
@method_options = nil
|
262
282
|
end
|
263
283
|
|
284
|
+
# Retrieve the task name from given args.
|
285
|
+
def retrieve_task_name(args) #:nodoc:
|
286
|
+
meth = args.first.to_s unless args.empty?
|
287
|
+
|
288
|
+
if meth && (map[meth] || meth !~ /^\-/)
|
289
|
+
args.shift
|
290
|
+
else
|
291
|
+
nil
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
264
295
|
# Receives a task name (can be nil), and try to get a map from it.
|
265
296
|
# If a map can't be found use the sent name or the default task.
|
266
|
-
#
|
267
297
|
def normalize_task_name(meth) #:nodoc:
|
268
298
|
meth = map[meth.to_s] || meth || default_task
|
269
299
|
meth.to_s.gsub('-','_') # treat foo-bar > foo_bar
|
@@ -275,11 +305,6 @@ class Thor
|
|
275
305
|
def help(task = nil, subcommand = true); super; end
|
276
306
|
RUBY
|
277
307
|
end
|
278
|
-
|
279
|
-
end
|
280
|
-
|
281
|
-
def subcommand_args
|
282
|
-
@@original_args[1..-1]
|
283
308
|
end
|
284
309
|
|
285
310
|
include Thor::Base
|
@@ -53,7 +53,7 @@ class Thor
|
|
53
53
|
|
54
54
|
opts = Thor::Options.new(parse_options, hash_options)
|
55
55
|
self.options = opts.parse(array_options)
|
56
|
-
opts.check_unknown! if self.class.check_unknown_options?
|
56
|
+
opts.check_unknown! if self.class.check_unknown_options?(config)
|
57
57
|
end
|
58
58
|
|
59
59
|
class << self
|
@@ -114,8 +114,12 @@ class Thor
|
|
114
114
|
@check_unknown_options = true
|
115
115
|
end
|
116
116
|
|
117
|
-
def check_unknown_options
|
118
|
-
@check_unknown_options
|
117
|
+
def check_unknown_options #:nodoc:
|
118
|
+
@check_unknown_options ||= from_superclass(:check_unknown_options, false)
|
119
|
+
end
|
120
|
+
|
121
|
+
def check_unknown_options?(config) #:nodoc:
|
122
|
+
!!check_unknown_options
|
119
123
|
end
|
120
124
|
|
121
125
|
# Adds an argument to the class and creates an attr_accessor for it.
|
@@ -364,19 +368,25 @@ class Thor
|
|
364
368
|
#
|
365
369
|
def namespace(name=nil)
|
366
370
|
case name
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
+
when nil
|
372
|
+
@namespace ||= Thor::Util.namespace_from_thor_class(self)
|
373
|
+
else
|
374
|
+
@namespace = name.to_s
|
371
375
|
end
|
372
376
|
end
|
373
377
|
|
374
|
-
#
|
378
|
+
# Parses the task and options from the given args, instantiate the class
|
379
|
+
# and invoke the task. This method is used when the arguments must be parsed
|
380
|
+
# from an array. If you are inside Ruby and want to use a Thor class, you
|
381
|
+
# can simply initialize it:
|
382
|
+
#
|
383
|
+
# script = MyScript.new(args, options, config)
|
384
|
+
# script.invoke(:task, first_arg, second_arg, third_arg)
|
375
385
|
#
|
376
386
|
def start(given_args=ARGV, config={})
|
377
|
-
self.debugging = given_args.
|
387
|
+
self.debugging = given_args.delete("--debug")
|
378
388
|
config[:shell] ||= Thor::Base.shell.new
|
379
|
-
|
389
|
+
dispatch(nil, given_args.dup, nil, config)
|
380
390
|
rescue Thor::Error => e
|
381
391
|
debugging ? (raise e) : config[:shell].error(e.message)
|
382
392
|
exit(1) if exit_on_failure?
|
@@ -535,6 +545,12 @@ class Thor
|
|
535
545
|
# class.
|
536
546
|
def initialize_added #:nodoc:
|
537
547
|
end
|
548
|
+
|
549
|
+
# SIGNATURE: The hook invoked by start.
|
550
|
+
def dispatch(task, given_args, given_opts, config) #:nodoc:
|
551
|
+
raise NotImplementedError
|
552
|
+
end
|
553
|
+
|
538
554
|
end
|
539
555
|
end
|
540
556
|
end
|
@@ -10,10 +10,10 @@ class Thor
|
|
10
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
when Symbol, String
|
14
|
+
Thor::Util.find_class_and_task_by_namespace(name.to_s, !key)
|
15
|
+
else
|
16
|
+
name
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -94,29 +94,34 @@ class Thor
|
|
94
94
|
# invoke Rspec::RR, [], :style => :foo
|
95
95
|
#
|
96
96
|
def invoke(name=nil, *args)
|
97
|
+
if name.nil?
|
98
|
+
warn "[Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}"
|
99
|
+
return invoke_all
|
100
|
+
end
|
101
|
+
|
97
102
|
args.unshift(nil) if Array === args.first || NilClass === args.first
|
98
103
|
task, args, opts, config = args
|
99
104
|
|
100
|
-
|
101
|
-
|
105
|
+
klass, task = _retrieve_class_and_task(name, task)
|
106
|
+
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
107
|
+
|
108
|
+
args, opts, config = _parse_initialization_options(args, opts, config)
|
109
|
+
klass.send(:dispatch, task, args, opts, config)
|
110
|
+
end
|
102
111
|
|
103
|
-
|
104
|
-
|
112
|
+
# Invoke the given task if the given args.
|
113
|
+
def invoke_task(task, *args) #:nodoc:
|
114
|
+
current = @_invocations[self.class]
|
105
115
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
task.run(instance, method_args)
|
110
|
-
end
|
116
|
+
unless current.include?(task.name)
|
117
|
+
current << task.name
|
118
|
+
task.run(self, *args)
|
111
119
|
end
|
120
|
+
end
|
112
121
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
iterator.call(nil, task)
|
117
|
-
else
|
118
|
-
klass.all_tasks.map(&iterator)
|
119
|
-
end
|
122
|
+
# Invoke all tasks for the current instance.
|
123
|
+
def invoke_all #:nodoc:
|
124
|
+
self.class.all_tasks.map { |_, task| invoke_task(task) }
|
120
125
|
end
|
121
126
|
|
122
127
|
# Invokes using shell padding.
|
@@ -131,50 +136,33 @@ class Thor
|
|
131
136
|
{ :invocations => @_invocations }
|
132
137
|
end
|
133
138
|
|
134
|
-
# This method
|
135
|
-
#
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
# This method simply retrieves the class and task to be invoked.
|
140
|
+
# If the name is nil or the given name is a task in the current class,
|
141
|
+
# use the given name and return self as class. Otherwise, call
|
142
|
+
# prepare_for_invocation in the current class.
|
143
|
+
def _retrieve_class_and_task(name, sent_task=nil) #:nodoc:
|
144
|
+
case
|
145
|
+
when name.nil?
|
146
|
+
[self.class, nil]
|
147
|
+
when self.class.all_tasks[name.to_s]
|
148
|
+
[self.class, name.to_s]
|
142
149
|
else
|
143
|
-
|
144
|
-
task
|
150
|
+
klass, task = self.class.prepare_for_invocation(nil, name)
|
151
|
+
[klass, task || sent_task]
|
145
152
|
end
|
146
|
-
|
147
|
-
# If the object was not set, use self and use the name as task.
|
148
|
-
object, task = self, name unless object
|
149
|
-
return object, _validate_task(object, task)
|
150
|
-
end
|
151
|
-
|
152
|
-
# Check if the object given is a Thor class object and get a task object
|
153
|
-
# for it.
|
154
|
-
def _validate_task(object, task) #:nodoc:
|
155
|
-
klass = object.is_a?(Class) ? object : object.class
|
156
|
-
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
157
|
-
|
158
|
-
task ||= klass.default_task if klass.respond_to?(:default_task)
|
159
|
-
task = klass.all_tasks[task.to_s] || Thor::DynamicTask.new(task) if task && !task.is_a?(Thor::Task)
|
160
|
-
task
|
161
153
|
end
|
162
154
|
|
163
155
|
# Initialize klass using values stored in the @_initializer.
|
164
|
-
def
|
165
|
-
|
166
|
-
klass = object
|
156
|
+
def _parse_initialization_options(args, opts, config) #:nodoc:
|
157
|
+
stored_args, stored_opts, stored_config = @_initializer
|
167
158
|
|
168
|
-
|
169
|
-
|
170
|
-
opts ||= stored_opts.dup
|
159
|
+
args ||= stored_args.dup
|
160
|
+
opts ||= stored_opts.dup
|
171
161
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
[ object.class, object ]
|
177
|
-
end
|
162
|
+
config ||= {}
|
163
|
+
config = stored_config.merge(_shared_configuration).merge!(config)
|
164
|
+
|
165
|
+
[ args, opts, config ]
|
178
166
|
end
|
179
167
|
end
|
180
168
|
end
|
@@ -151,6 +151,8 @@ class Thor
|
|
151
151
|
elsif option.string? && !option.required?
|
152
152
|
# Return the default if there is one, else the human name
|
153
153
|
return option.lazy_default || option.default || option.human_name
|
154
|
+
elsif option.lazy_default
|
155
|
+
return option.lazy_default
|
154
156
|
else
|
155
157
|
raise MalformattedArgumentError, "No value provided for option '#{switch}'"
|
156
158
|
end
|
@@ -35,8 +35,8 @@ class Thor
|
|
35
35
|
# say("I know you knew that.")
|
36
36
|
#
|
37
37
|
def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
|
38
|
-
message
|
39
|
-
message
|
38
|
+
message = message.to_s
|
39
|
+
message = set_color(message, color) if color
|
40
40
|
|
41
41
|
spaces = " " * padding
|
42
42
|
|
@@ -60,7 +60,9 @@ class Thor
|
|
60
60
|
|
61
61
|
status = status.to_s.rjust(12)
|
62
62
|
status = set_color status, color, true if color
|
63
|
-
|
63
|
+
|
64
|
+
$stdout.puts "#{status}#{spaces}#{message}"
|
65
|
+
$stdout.flush
|
64
66
|
end
|
65
67
|
|
66
68
|
# Make a question the to user and returns true if the user replies "y" or
|
data/lib/bundler/version.rb
CHANGED
@@ -2,5 +2,5 @@ module Bundler
|
|
2
2
|
# We're doing this because we might write tests that deal
|
3
3
|
# with other versions of bundler and we are unsure how to
|
4
4
|
# handle this better.
|
5
|
-
VERSION = "1.0.0.rc.
|
5
|
+
VERSION = "1.0.0.rc.3" unless defined?(::Bundler::VERSION)
|
6
6
|
end
|
metadata
CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
|
|
7
7
|
- 0
|
8
8
|
- 0
|
9
9
|
- rc
|
10
|
-
-
|
11
|
-
version: 1.0.0.rc.
|
10
|
+
- 3
|
11
|
+
version: 1.0.0.rc.3
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Carl Lerche
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2010-
|
21
|
+
date: 2010-08-03 00:00:00 -07:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|