bundler 1.8.9 → 1.9.0.pre
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 +9 -7
- data/CHANGELOG.md +8 -33
- data/Rakefile +51 -8
- data/lib/bundler/cli/gem.rb +20 -1
- data/lib/bundler/cli/install.rb +1 -1
- data/lib/bundler/definition.rb +8 -12
- data/lib/bundler/dep_proxy.rb +2 -2
- data/lib/bundler/installer.rb +12 -18
- data/lib/bundler/resolver.rb +168 -383
- data/lib/bundler/rubygems_ext.rb +1 -1
- data/lib/bundler/rubygems_integration.rb +6 -14
- data/lib/bundler/runtime.rb +3 -0
- data/lib/bundler/shared_helpers.rb +12 -7
- data/lib/bundler/source.rb +0 -5
- data/lib/bundler/source/path.rb +2 -1
- data/lib/bundler/source/path/installer.rb +0 -2
- data/lib/bundler/source/rubygems.rb +9 -11
- data/lib/bundler/templates/newgem/Rakefile.tt +0 -1
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb +5 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb +266 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb +69 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb +3 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/specification_provider.rb +90 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/ui.rb +63 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb +412 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolver.rb +43 -0
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb +43 -0
- data/lib/bundler/vendor/{thor.rb → thor-0.19.1/lib/thor.rb} +57 -53
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions.rb +34 -34
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/create_file.rb +7 -7
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/create_link.rb +2 -2
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/directory.rb +11 -11
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/empty_directory.rb +2 -2
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/file_manipulation.rb +14 -14
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/actions/inject_into_file.rb +24 -24
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/base.rb +71 -71
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/command.rb +8 -8
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/core_ext/hash_with_indifferent_access.rb +2 -2
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/core_ext/io_binary_read.rb +1 -1
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/core_ext/ordered_hash.rb +2 -2
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/error.rb +3 -3
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/group.rb +27 -27
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/invocation.rb +16 -11
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor.rb +17 -0
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/line_editor/basic.rb +2 -2
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/line_editor/readline.rb +7 -7
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb +4 -0
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/parser/argument.rb +7 -7
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/parser/arguments.rb +10 -10
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/parser/option.rb +14 -10
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/parser/options.rb +12 -12
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/rake_compat.rb +14 -14
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/runner.rb +76 -76
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/shell.rb +18 -18
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/shell/basic.rb +31 -30
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/shell/color.rb +10 -10
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/shell/html.rb +28 -28
- data/lib/bundler/vendor/{thor → thor-0.19.1/lib/thor}/util.rb +61 -61
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/version.rb +3 -0
- data/lib/bundler/vendored_molinillo.rb +5 -0
- data/lib/bundler/vendored_thor.rb +3 -6
- data/lib/bundler/version.rb +1 -1
- metadata +44 -35
- data/lib/bundler/vendor/.document +0 -0
- data/lib/bundler/vendor/thor/line_editor.rb +0 -17
- data/lib/bundler/vendor/thor/parser.rb +0 -4
- data/lib/bundler/vendor/thor/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86a33559b397d9ddda95f691097fa4811d9a9c12
|
4
|
+
data.tar.gz: f93e41d2292a01daa7566fc9ab92ce80441dd543
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f97a40fcec05c571ce3d189aa40dd94293f14b39fb3cf14ccb71e1dee73b17300234010b5ca13903eba84620e3afa5f95eb9d8e527607bf8c4cb1d7988a20fcc
|
7
|
+
data.tar.gz: 1c9aa9f983791d29fb606d85d5ab3d5048c0fbc92d5eb01cb3c8ba9ffcd33529d773a22c660582166aa99dc6cc32ae86233e7963ed7c7d8756d2114931adcfa2
|
data/.travis.yml
CHANGED
@@ -27,6 +27,7 @@ notifications:
|
|
27
27
|
- secure: JxBi7DDJGkIF/7f/FSN/HUHpvV4EKfQccZHTPd1b2pNJn3GXo6u+tNVbAw2WjxYzPyPQI3ZcYBCU9SEXp/i7VmG8uMzh8Kyildw+miSKYKVb90uYqcsXWzbxwyNBgJLvyDkzST45H5lgnyAicee3WkFes/WDZikIajbH7ztdb04=
|
28
28
|
|
29
29
|
rvm:
|
30
|
+
- 2.2
|
30
31
|
- 2.1
|
31
32
|
- 2.0.0
|
32
33
|
- 1.9.3
|
@@ -38,24 +39,25 @@ env:
|
|
38
39
|
# We need to know if changes to rubygems will break bundler on release
|
39
40
|
- RGV=master
|
40
41
|
# Test the latest rubygems release with all of our supported rubies
|
41
|
-
- RGV=v2.4.
|
42
|
+
- RGV=v2.4.6
|
42
43
|
|
43
44
|
matrix:
|
44
45
|
fast_finish: true
|
45
46
|
include:
|
47
|
+
# Ruby 2.2, Rubygems 2.4.5 and up (RG 2.4 is included by the matrix above)
|
46
48
|
# Ruby 2.1, Rubygems 2.2.2 and up
|
47
49
|
- rvm: 2.1
|
48
|
-
env: RGV=v2.2.
|
49
|
-
# Ruby 2.0.0, Rubygems 2.0 and up
|
50
|
+
env: RGV=v2.2.3
|
51
|
+
# Ruby 2.0.0, Rubygems 2.0.0 and up
|
50
52
|
- rvm: 2.0.0
|
51
|
-
env: RGV=v2.2.
|
53
|
+
env: RGV=v2.2.3
|
52
54
|
- rvm: 2.0.0
|
53
55
|
env: RGV=v2.1.11
|
54
56
|
- rvm: 2.0.0
|
55
57
|
env: RGV=v2.0.14
|
56
58
|
# Ruby 1.9.3, Rubygems 1.5.3 and up
|
57
59
|
- rvm: 1.9.3
|
58
|
-
env: RGV=v2.2.
|
60
|
+
env: RGV=v2.2.3
|
59
61
|
- rvm: 1.9.3
|
60
62
|
env: RGV=v2.1.11
|
61
63
|
- rvm: 1.9.3
|
@@ -70,7 +72,7 @@ matrix:
|
|
70
72
|
env: RGV=v1.5.3
|
71
73
|
# Ruby 1.8.7, Rubygems 1.3.6 and up
|
72
74
|
- rvm: 1.8.7
|
73
|
-
env: RGV=v2.2.
|
75
|
+
env: RGV=v2.2.3
|
74
76
|
- rvm: 1.8.7
|
75
77
|
env: RGV=v2.0.14
|
76
78
|
- rvm: 1.8.7
|
@@ -95,7 +97,7 @@ matrix:
|
|
95
97
|
# Ruby 1.9.2 sanity check
|
96
98
|
# (but it's just too slow and sometimes goes over the Travis limit)
|
97
99
|
- rvm: 1.9.2
|
98
|
-
env: RGV=v2.
|
100
|
+
env: RGV=v2.4.6
|
99
101
|
# Ruby-head (we want to know how we're doing, but not fail the build)
|
100
102
|
- rvm: ruby-head
|
101
103
|
env: RGV=master
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,14 @@
|
|
1
|
-
## 1.
|
1
|
+
## 1.9.0.pre (2015-03-11)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
- Support RubyGems versions above 2.4.6 (@tenderlove, @segiddins, @indirect)
|
6
|
-
|
7
|
-
## 1.8.8 (2015-04-29)
|
8
|
-
|
9
|
-
Bugfixes:
|
10
|
-
|
11
|
-
- Respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
|
12
|
-
|
13
|
-
## 1.8.7 (2015-04-07)
|
14
|
-
|
15
|
-
Bugfixes:
|
16
|
-
|
17
|
-
- stop suppressing errors inside gems that get required (#3549, @indirect)
|
3
|
+
Features:
|
18
4
|
|
19
|
-
|
5
|
+
- prefer gemspecs closest to the directory root (#3428, @segiddins)
|
6
|
+
- debug log for API request limits (#3452, @neerfri)
|
20
7
|
|
21
|
-
|
8
|
+
"Features":
|
22
9
|
|
23
|
-
-
|
24
|
-
-
|
10
|
+
- Molinillo resolver, shared with CocoaPods (@segiddins)
|
11
|
+
- updated Thor to v0.19.1 (@segiddins)
|
25
12
|
|
26
13
|
## 1.8.5 (2015-03-11)
|
27
14
|
|
@@ -109,6 +96,7 @@ Features:
|
|
109
96
|
- add `package --cache-path` and `config cache_path` for cache location (@jnraine)
|
110
97
|
- allow `config` to work even when a Gemfile is not present (@dholdren)
|
111
98
|
- add `config gemfile /path` for other Gemfile locations (@dholdren)
|
99
|
+
- add `github` method alonside the `git` method (@BenMorganIO)
|
112
100
|
|
113
101
|
Bugfixes:
|
114
102
|
|
@@ -121,19 +109,6 @@ Documentation:
|
|
121
109
|
|
122
110
|
- add missing Gemfile global `path` explanation (@agenteo)
|
123
111
|
|
124
|
-
## 1.7.15 (2015-04-29)
|
125
|
-
|
126
|
-
Bugfixes:
|
127
|
-
|
128
|
-
- Respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
|
129
|
-
|
130
|
-
## 1.7.14 (2015-03-30)
|
131
|
-
|
132
|
-
Bugfixes:
|
133
|
-
|
134
|
-
- Keep gems locked when updating another gem from the same source (#3250, @indirect)
|
135
|
-
- Don't add extra quotes around long, quoted config values (@aroben, #3338)
|
136
|
-
|
137
112
|
## 1.7.13 (2015-02-07)
|
138
113
|
|
139
114
|
Bugfixes:
|
data/Rakefile
CHANGED
@@ -27,6 +27,52 @@ module Rake
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
namespace :molinillo do
|
31
|
+
task :namespace do
|
32
|
+
files = Dir.glob('lib/bundler/vendor/Molinillo*/**/*.rb')
|
33
|
+
sh "sed -i.bak 's/Molinillo/Bundler::Molinillo/g' #{files.join(' ')}"
|
34
|
+
sh "rm #{files.join('.bak ')}.bak"
|
35
|
+
end
|
36
|
+
|
37
|
+
task :clean do
|
38
|
+
files = Dir.glob('lib/bundler/vendor/Molinillo*/*', File::FNM_DOTMATCH).reject { |f| %(. .. lib).include? f.split('/').last }
|
39
|
+
puts files
|
40
|
+
sh "rm -r #{files.join(' ')}"
|
41
|
+
end
|
42
|
+
|
43
|
+
task :update, [:tag] => [] do |t, args|
|
44
|
+
tag = args[:tag]
|
45
|
+
Dir.chdir 'lib/bundler/vendor' do
|
46
|
+
`curl -L https://github.com/CocoaPods/molinillo/archive/#{tag}.tar.gz | tar -xz`
|
47
|
+
end
|
48
|
+
Rake::Task['molinillo:namespace'].invoke
|
49
|
+
Rake::Task['molinillo:clean'].invoke
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
namespace :thor do
|
54
|
+
task :namespace do
|
55
|
+
files = Dir.glob('lib/bundler/vendor/thor*/**/*.rb')
|
56
|
+
sh "sed -i.bak 's/Thor/Bundler::Thor/g' #{files.join(' ')}"
|
57
|
+
sh "rm #{files.join('.bak ')}.bak"
|
58
|
+
end
|
59
|
+
|
60
|
+
task :clean do
|
61
|
+
files = Dir.glob('lib/bundler/vendor/thor*/*', File::FNM_DOTMATCH).reject { |f| %(. .. lib).include? f.split('/').last }
|
62
|
+
puts files
|
63
|
+
sh "rm -r #{files.join(' ')}"
|
64
|
+
end
|
65
|
+
|
66
|
+
task :update, [:tag] => [] do |t, args|
|
67
|
+
tag = args[:tag]
|
68
|
+
Dir.chdir 'lib/bundler/vendor' do
|
69
|
+
`curl -L https://github.com/erikhuda/thor/archive/#{tag}.tar.gz | tar -xz`
|
70
|
+
end
|
71
|
+
Rake::Task['thor:namespace'].invoke
|
72
|
+
Rake::Task['thor:clean'].invoke
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
30
76
|
namespace :spec do
|
31
77
|
desc "Ensure spec dependencies are installed"
|
32
78
|
task :deps do
|
@@ -111,8 +157,8 @@ begin
|
|
111
157
|
namespace :rubygems do
|
112
158
|
rubyopt = ENV["RUBYOPT"]
|
113
159
|
# When editing this list, also edit .travis.yml!
|
114
|
-
branches = %w(master
|
115
|
-
releases = %w(v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.29 v2.0.14 v2.1.11 v2.2.
|
160
|
+
branches = %w(master)
|
161
|
+
releases = %w(v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.29 v2.0.14 v2.1.11 v2.2.3 v2.4.6)
|
116
162
|
(branches + releases).each do |rg|
|
117
163
|
desc "Run specs with Rubygems #{rg}"
|
118
164
|
RSpec::Core::RakeTask.new(rg) do |t|
|
@@ -234,15 +280,12 @@ begin
|
|
234
280
|
task :clean do
|
235
281
|
rm_rf "lib/bundler/man"
|
236
282
|
end
|
237
|
-
|
238
|
-
task(:require) { }
|
239
283
|
end
|
240
284
|
|
241
285
|
rescue LoadError
|
242
286
|
namespace :man do
|
243
|
-
task(:
|
244
|
-
task(:
|
245
|
-
task(:clean) { }
|
287
|
+
task(:build) { warn "Install the ronn gem to be able to release!" }
|
288
|
+
task(:clean) { warn "Install the ronn gem to be able to release!" }
|
246
289
|
end
|
247
290
|
end
|
248
291
|
|
@@ -254,6 +297,6 @@ end
|
|
254
297
|
|
255
298
|
require 'bundler/gem_tasks'
|
256
299
|
task :build => ["man:clean", "man:build"]
|
257
|
-
task :release => ["man:
|
300
|
+
task :release => ["man:clean", "man:build"]
|
258
301
|
|
259
302
|
task :default => :spec
|
data/lib/bundler/cli/gem.rb
CHANGED
@@ -37,8 +37,10 @@ module Bundler
|
|
37
37
|
:email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
|
38
38
|
:test => options[:test],
|
39
39
|
:ext => options[:ext],
|
40
|
-
:bin => options[:bin]
|
40
|
+
:bin => options[:bin],
|
41
|
+
:bundler_version => bundler_dependency_version
|
41
42
|
}
|
43
|
+
ensure_safe_gem_name(opts[:name], opts[:constant_array])
|
42
44
|
|
43
45
|
templates = {
|
44
46
|
"Gemfile.tt" => "Gemfile",
|
@@ -161,5 +163,22 @@ module Bundler
|
|
161
163
|
test_framework
|
162
164
|
end
|
163
165
|
|
166
|
+
def bundler_dependency_version
|
167
|
+
v = Gem::Version.new(Bundler::VERSION)
|
168
|
+
req = v.segments[0..1]
|
169
|
+
req << v.segments.last if v.prerelease?
|
170
|
+
req.join(".")
|
171
|
+
end
|
172
|
+
|
173
|
+
def ensure_safe_gem_name name, constant_array
|
174
|
+
if name =~ /^\d/
|
175
|
+
Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
|
176
|
+
exit 1
|
177
|
+
elsif Object.const_defined?(constant_array.first)
|
178
|
+
Bundler.ui.error "Invalid gem name #{name} constant #{constant_array.join("::")} is already in use. Please choose another gem name."
|
179
|
+
exit 1
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
164
183
|
end
|
165
184
|
end
|
data/lib/bundler/cli/install.rb
CHANGED
data/lib/bundler/definition.rb
CHANGED
@@ -184,10 +184,11 @@ module Bundler
|
|
184
184
|
# @return [SpecSet] resolved dependencies
|
185
185
|
def resolve
|
186
186
|
@resolve ||= begin
|
187
|
-
last_resolve = converge_locked_specs
|
188
187
|
if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
|
189
|
-
|
188
|
+
@locked_specs
|
190
189
|
else
|
190
|
+
last_resolve = converge_locked_specs
|
191
|
+
|
191
192
|
# Run a resolve against the locally available gems
|
192
193
|
last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve)
|
193
194
|
end
|
@@ -271,7 +272,7 @@ module Bundler
|
|
271
272
|
each do |spec|
|
272
273
|
next if spec.name == 'bundler'
|
273
274
|
out << spec.to_lock
|
274
|
-
|
275
|
+
end
|
275
276
|
out << "\n"
|
276
277
|
end
|
277
278
|
|
@@ -520,9 +521,7 @@ module Bundler
|
|
520
521
|
|
521
522
|
converged = []
|
522
523
|
@locked_specs.each do |s|
|
523
|
-
|
524
|
-
dep = @dependencies.find { |d| s.satisfies?(d) }
|
525
|
-
s.source = (dep && dep.source) || sources.get(s.source)
|
524
|
+
s.source = sources.get(s.source)
|
526
525
|
|
527
526
|
# Don't add a spec to the list if its source is expired. For example,
|
528
527
|
# if you change a Git gem to Rubygems.
|
@@ -562,15 +561,12 @@ module Bundler
|
|
562
561
|
resolve
|
563
562
|
end
|
564
563
|
|
565
|
-
def in_locked_deps?(dep,
|
566
|
-
|
567
|
-
# treat sources as equivalent anytime the locked dep has all the remotes
|
568
|
-
# that the Gemfile dep does.
|
569
|
-
locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
|
564
|
+
def in_locked_deps?(dep, d)
|
565
|
+
d && dep.source == d.source
|
570
566
|
end
|
571
567
|
|
572
568
|
def satisfies_locked_spec?(dep)
|
573
|
-
@locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source
|
569
|
+
@locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source == dep.source) }
|
574
570
|
end
|
575
571
|
|
576
572
|
def expanded_dependencies
|
data/lib/bundler/dep_proxy.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Bundler
|
2
2
|
class DepProxy
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :__platform, :dep
|
5
5
|
|
6
6
|
def initialize(dep, platform)
|
7
|
-
@dep, @__platform
|
7
|
+
@dep, @__platform = dep, platform
|
8
8
|
end
|
9
9
|
|
10
10
|
def hash
|
data/lib/bundler/installer.rb
CHANGED
@@ -96,26 +96,20 @@ module Bundler
|
|
96
96
|
|
97
97
|
def install_gem_from_spec(spec, standalone = false, worker = 0)
|
98
98
|
# Fetch the build settings, if there are any
|
99
|
-
settings
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
99
|
+
settings = Bundler.settings["build.#{spec.name}"]
|
100
|
+
install_message = nil
|
101
|
+
post_install_message = nil
|
102
|
+
debug_message = nil
|
103
|
+
Bundler.rubygems.with_build_args [settings] do
|
104
|
+
install_message, post_install_message, debug_message = spec.source.install(spec)
|
105
|
+
if install_message.include? 'Installing'
|
106
|
+
Bundler.ui.confirm install_message
|
107
|
+
else
|
108
|
+
Bundler.ui.info install_message
|
105
109
|
end
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
install_message, post_install_message, debug_message = *messages
|
111
|
-
|
112
|
-
if install_message.include? 'Installing'
|
113
|
-
Bundler.ui.confirm install_message
|
114
|
-
else
|
115
|
-
Bundler.ui.info install_message
|
110
|
+
Bundler.ui.debug debug_message if debug_message
|
111
|
+
Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
|
116
112
|
end
|
117
|
-
Bundler.ui.debug debug_message if debug_message
|
118
|
-
Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
|
119
113
|
|
120
114
|
if Bundler.settings[:bin] && standalone
|
121
115
|
generate_standalone_bundler_executable_stubs(spec)
|
data/lib/bundler/resolver.rb
CHANGED
@@ -1,27 +1,73 @@
|
|
1
1
|
require 'set'
|
2
|
+
|
2
3
|
# This is the latest iteration of the gem dependency resolving algorithm. As of now,
|
3
4
|
# it can resolve (as a success or failure) any set of gem dependencies we throw at it
|
4
5
|
# in a reasonable amount of time. The most iterations I've seen it take is about 150.
|
5
6
|
# The actual implementation of the algorithm is not as good as it could be yet, but that
|
6
7
|
# can come later.
|
7
8
|
|
8
|
-
# Extending Gem classes to add necessary tracking information
|
9
|
-
module Gem
|
10
|
-
class Specification
|
11
|
-
def required_by
|
12
|
-
@required_by ||= []
|
13
|
-
end
|
14
|
-
end
|
15
|
-
class Dependency
|
16
|
-
def required_by
|
17
|
-
@required_by ||= []
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
9
|
module Bundler
|
23
10
|
class Resolver
|
24
11
|
|
12
|
+
require 'bundler/vendored_molinillo'
|
13
|
+
|
14
|
+
class Molinillo::VersionConflict
|
15
|
+
def clean_req(req)
|
16
|
+
if req.to_s.include?(">= 0")
|
17
|
+
req.to_s.gsub(/ \(.*?\)$/, '')
|
18
|
+
else
|
19
|
+
req.to_s.gsub(/\, (runtime|development)\)$/, ')')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def message
|
24
|
+
conflicts.values.flatten.reduce('') do |o, conflict|
|
25
|
+
o << %(Bundler could not find compatible versions for gem "#{conflict.requirement.name}":\n)
|
26
|
+
if conflict.locked_requirement
|
27
|
+
o << %( In snapshot (Gemfile.lock):\n)
|
28
|
+
o << %( #{clean_req conflict.locked_requirement}\n)
|
29
|
+
o << %(\n)
|
30
|
+
end
|
31
|
+
o << %( In Gemfile:\n)
|
32
|
+
o << conflict.requirement_trees.map do |tree|
|
33
|
+
t = ''
|
34
|
+
depth = 2
|
35
|
+
tree.each do |req|
|
36
|
+
t << ' ' * depth << %(#{clean_req req})
|
37
|
+
t << %( depends on) unless tree[-1] == req
|
38
|
+
t << %(\n)
|
39
|
+
depth += 1
|
40
|
+
end
|
41
|
+
t
|
42
|
+
end.join("\n")
|
43
|
+
|
44
|
+
if conflict.requirement.name == 'bundler'
|
45
|
+
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
|
46
|
+
other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new Bundler::VERSION)
|
47
|
+
end
|
48
|
+
|
49
|
+
if conflict.requirement.name == "bundler" && other_bundler_required
|
50
|
+
o << "\n"
|
51
|
+
o << "This Gemfile requires a different version of Bundler.\n"
|
52
|
+
o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
|
53
|
+
end
|
54
|
+
if conflict.locked_requirement
|
55
|
+
o << "\n"
|
56
|
+
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
|
57
|
+
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
|
58
|
+
elsif !conflict.existing
|
59
|
+
if conflict.requirement_trees.first.size > 1
|
60
|
+
o << "Could not find gem '#{clean_req(conflict.requirement)}', which is required by "
|
61
|
+
o << "gem '#{clean_req(conflict.requirement_trees.first[-2])}', in any of the sources."
|
62
|
+
else
|
63
|
+
o << "Could not find gem '#{clean_req(conflict.requirement)} in any of the sources\n"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
o
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
25
71
|
ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
|
26
72
|
|
27
73
|
class SpecGroup < Array
|
@@ -65,8 +111,10 @@ module Bundler
|
|
65
111
|
|
66
112
|
def activate_platform(platform)
|
67
113
|
unless @activated.include?(platform)
|
68
|
-
|
69
|
-
|
114
|
+
if for?(platform)
|
115
|
+
@activated << platform
|
116
|
+
return __dependencies[platform] || []
|
117
|
+
end
|
70
118
|
end
|
71
119
|
[]
|
72
120
|
end
|
@@ -91,6 +139,14 @@ module Bundler
|
|
91
139
|
"#{name} (#{version})"
|
92
140
|
end
|
93
141
|
|
142
|
+
def dependencies_for_activated_platforms
|
143
|
+
@activated.map { |p| __dependencies[p] }.flatten
|
144
|
+
end
|
145
|
+
|
146
|
+
def platforms_for_dependency_named(dependency)
|
147
|
+
__dependencies.select { |p, deps| deps.map(&:name).include? dependency }.keys
|
148
|
+
end
|
149
|
+
|
94
150
|
private
|
95
151
|
|
96
152
|
def __dependencies
|
@@ -110,8 +166,6 @@ module Bundler
|
|
110
166
|
end
|
111
167
|
end
|
112
168
|
|
113
|
-
attr_reader :errors, :started_at, :iteration_rate, :iteration_counter, :initial_reqs
|
114
|
-
|
115
169
|
# Figures out the best possible configuration of gems that satisfies
|
116
170
|
# the list of passed dependencies and any child dependencies without
|
117
171
|
# causing any gem activation errors.
|
@@ -123,289 +177,85 @@ module Bundler
|
|
123
177
|
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
|
124
178
|
# collection of gemspecs is returned. Otherwise, nil is returned.
|
125
179
|
def self.resolve(requirements, index, source_requirements = {}, base = [])
|
126
|
-
Bundler.ui.info "Resolving dependencies...", false
|
127
180
|
base = SpecSet.new(base) unless base.is_a?(SpecSet)
|
128
181
|
resolver = new(index, source_requirements, base)
|
129
182
|
result = resolver.start(requirements)
|
130
|
-
Bundler.ui.info "" # new line now that dots are done
|
131
183
|
SpecSet.new(result)
|
132
|
-
rescue => e
|
133
|
-
Bundler.ui.info "" # new line before the error
|
134
|
-
raise e
|
135
|
-
end
|
136
|
-
|
137
|
-
def initialize(index, source_requirements, base)
|
138
|
-
@initial_reqs = []
|
139
|
-
@errors = {}
|
140
|
-
@base = base
|
141
|
-
@index = index
|
142
|
-
@deps_for = {}
|
143
|
-
@missing_gems = Hash.new(0)
|
144
|
-
@prereleases_cache = Hash.new { |h,k| h[k] = k.prerelease? }
|
145
|
-
@source_requirements = source_requirements
|
146
|
-
@iteration_counter = 0
|
147
|
-
@started_at = Time.now
|
148
184
|
end
|
149
185
|
|
150
|
-
def debug
|
151
|
-
if ENV['DEBUG_RESOLVER']
|
152
|
-
debug_info = yield
|
153
|
-
debug_info = debug_info.inspect unless debug_info.is_a?(String)
|
154
|
-
$stderr.puts debug_info
|
155
|
-
end
|
156
|
-
end
|
157
186
|
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
@
|
164
|
-
|
165
|
-
@
|
166
|
-
|
167
|
-
resolve(reqs, activated, current_traversal)
|
187
|
+
def initialize(index, source_requirements, base)
|
188
|
+
@index = index
|
189
|
+
@source_requirements = source_requirements
|
190
|
+
@base = base
|
191
|
+
@resolver = Molinillo::Resolver.new(self, self)
|
192
|
+
@search_for = {}
|
193
|
+
@prereleases_cache = Hash.new { |h,k| h[k] = k.prerelease? }
|
194
|
+
@base_dg = Molinillo::DependencyGraph.new
|
195
|
+
@base.each { |ls| @base_dg.add_root_vertex ls.name, Dependency.new(ls.name, ls.version) }
|
168
196
|
end
|
169
197
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
198
|
+
def start(requirements)
|
199
|
+
verify_gemfile_dependencies_are_found!(requirements)
|
200
|
+
dg = @resolver.resolve(requirements, @base_dg)
|
201
|
+
dg.map(&:payload).map(&:to_specs).flatten
|
202
|
+
rescue Molinillo::VersionConflict => e
|
203
|
+
raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
|
204
|
+
rescue Molinillo::CircularDependencyError => e
|
205
|
+
names = e.dependencies.sort_by(&:name).map { |d| "gem '#{d.name}'"}
|
206
|
+
raise CyclicDependencyError, "Your Gemfile requires gems that depend" \
|
207
|
+
" on each other, creating an infinite loop. Please remove" \
|
208
|
+
" #{names.count > 1 ? 'either ' : '' }#{names.join(' or ')}" \
|
209
|
+
" and try again."
|
174
210
|
end
|
175
211
|
|
176
|
-
|
177
|
-
until current.nil?
|
178
|
-
current_state = find_state(current, states)
|
179
|
-
return current if state_any?(current_state)
|
180
|
-
current = current.required_by.last if current
|
181
|
-
end
|
212
|
+
include Molinillo::UI
|
182
213
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
214
|
+
# Conveys debug information to the user.
|
215
|
+
#
|
216
|
+
# @param [Integer] depth the current depth of the resolution process.
|
217
|
+
# @return [void]
|
218
|
+
def debug(depth = 0)
|
219
|
+
if debug?
|
220
|
+
debug_info = yield
|
221
|
+
debug_info = debug_info.inspect unless debug_info.is_a?(String)
|
222
|
+
STDERR.puts debug_info.split("\n").map { |s| ' ' * depth + s }
|
187
223
|
end
|
188
224
|
end
|
189
225
|
|
190
|
-
def
|
191
|
-
|
226
|
+
def debug?
|
227
|
+
ENV['DEBUG_RESOLVER'] || ENV['DEBUG_RESOLVER_TREE']
|
192
228
|
end
|
193
229
|
|
194
|
-
def
|
195
|
-
|
230
|
+
def before_resolution
|
231
|
+
Bundler.ui.info 'Resolving dependencies...', false
|
196
232
|
end
|
197
233
|
|
198
|
-
def
|
199
|
-
|
200
|
-
state = states.detect { |i| i.name == conflict.name }
|
201
|
-
state && state.possibles.any?
|
234
|
+
def after_resolution
|
235
|
+
Bundler.ui.info ''
|
202
236
|
end
|
203
237
|
|
204
|
-
def
|
205
|
-
|
206
|
-
until states.empty? do
|
207
|
-
state = states.pop
|
208
|
-
return state if conflict.name == state.name
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
def activate_gem(reqs, activated, requirement, current)
|
213
|
-
requirement.required_by.replace current.required_by
|
214
|
-
requirement.required_by << current
|
215
|
-
activated[requirement.name] = requirement
|
216
|
-
|
217
|
-
debug { " Activating: #{requirement.name} (#{requirement.version})" }
|
218
|
-
debug { requirement.required_by.map { |d| " * #{d.name} (#{d.requirement})" }.join("\n") }
|
219
|
-
|
220
|
-
dependencies = requirement.activate_platform(current.__platform)
|
221
|
-
|
222
|
-
debug { " Dependencies"}
|
223
|
-
dependencies.each do |dep|
|
224
|
-
next if dep.type == :development
|
225
|
-
dep.required_by.replace(current.required_by)
|
226
|
-
dep.required_by << current
|
227
|
-
@gems_size[dep] ||= gems_size(dep)
|
228
|
-
reqs << dep
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def resolve_for_conflict(state)
|
233
|
-
return version_conflict if state.nil? || state.possibles.empty?
|
234
|
-
reqs, activated, depth, conflicts = state.reqs.dup, state.activated.dup, state.depth, state.conflicts.dup
|
235
|
-
requirement = state.requirement
|
236
|
-
possible = state.possibles.pop
|
237
|
-
|
238
|
-
activate_gem(reqs, activated, possible, requirement)
|
239
|
-
|
240
|
-
return reqs, activated, depth, conflicts
|
238
|
+
def indicate_progress
|
239
|
+
Bundler.ui.info '.', false
|
241
240
|
end
|
242
241
|
|
243
|
-
|
244
|
-
# Find the state where the conflict has occurred
|
245
|
-
state = find_conflict_state(current, states)
|
246
|
-
|
247
|
-
debug { " -> Going to: #{current.name} state" } if current
|
248
|
-
|
249
|
-
# Resolve the conflicts by rewinding the state
|
250
|
-
# when the conflicted gem was activated
|
251
|
-
reqs, activated, depth, conflicts = resolve_for_conflict(state)
|
242
|
+
private
|
252
243
|
|
253
|
-
|
254
|
-
states << state unless state.possibles.empty?
|
255
|
-
clear_search_cache
|
244
|
+
include Molinillo::SpecificationProvider
|
256
245
|
|
257
|
-
|
246
|
+
def dependencies_for(specification)
|
247
|
+
specification.dependencies_for_activated_platforms
|
258
248
|
end
|
259
249
|
|
260
|
-
def
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
debug { print "\e[2J\e[f" ; "==== Iterating ====\n\n" }
|
270
|
-
|
271
|
-
reqs = reqs.sort_by do |a|
|
272
|
-
[ activated[a.name] ? 0 : 1,
|
273
|
-
@prereleases_cache[a.requirement] ? 0 : 1,
|
274
|
-
@errors[a.name] ? 0 : 1,
|
275
|
-
activated[a.name] ? 0 : @gems_size[a] ]
|
276
|
-
end
|
277
|
-
|
278
|
-
debug { "Activated:\n" + activated.values.map {|a| " #{a}" }.join("\n") }
|
279
|
-
debug { "Requirements:\n" + reqs.map {|r| " #{r}"}.join("\n") }
|
280
|
-
|
281
|
-
current = reqs.shift
|
282
|
-
|
283
|
-
$stderr.puts "#{' ' * depth}#{current}" if ENV['DEBUG_RESOLVER_TREE']
|
284
|
-
|
285
|
-
debug { "Attempting:\n #{current}"}
|
286
|
-
|
287
|
-
existing = activated[current.name]
|
288
|
-
|
289
|
-
|
290
|
-
if existing || current.name == 'bundler'
|
291
|
-
# Force the current
|
292
|
-
if current.name == 'bundler' && !existing
|
293
|
-
existing = search(DepProxy.new(Gem::Dependency.new('bundler', VERSION), Gem::Platform::RUBY)).first
|
294
|
-
raise GemNotFound, %Q{Bundler could not find gem "bundler" (#{VERSION})} unless existing
|
295
|
-
existing.required_by << existing
|
296
|
-
activated['bundler'] = existing
|
297
|
-
end
|
298
|
-
|
299
|
-
if current.requirement.satisfied_by?(existing.version)
|
300
|
-
debug { " * [SUCCESS] Already activated" }
|
301
|
-
@errors.delete(existing.name)
|
302
|
-
dependencies = existing.activate_platform(current.__platform)
|
303
|
-
reqs.concat dependencies
|
304
|
-
|
305
|
-
dependencies.each do |dep|
|
306
|
-
next if dep.type == :development
|
307
|
-
@gems_size[dep] ||= gems_size(dep)
|
308
|
-
end
|
309
|
-
|
310
|
-
depth += 1
|
311
|
-
next
|
312
|
-
else
|
313
|
-
debug { " * [FAIL] Already activated" }
|
314
|
-
@errors[existing.name] = [existing, current]
|
315
|
-
|
316
|
-
conflicts << current.name
|
317
|
-
|
318
|
-
parent = current.required_by.last
|
319
|
-
|
320
|
-
if current_traversal
|
321
|
-
parent = handle_conflict(current, states)
|
322
|
-
else
|
323
|
-
parent = handle_conflict(parent, states)
|
324
|
-
end
|
325
|
-
|
326
|
-
|
327
|
-
if parent.nil? && !conflicts.empty?
|
328
|
-
parent = states.reverse.detect { |i| conflicts.include?(i.name) && state_any?(i)}
|
329
|
-
end
|
330
|
-
|
331
|
-
if existing.respond_to?(:required_by)
|
332
|
-
parent = handle_conflict(parent, states, existing.required_by[-2]) unless other_possible?(parent, states)
|
333
|
-
end
|
334
|
-
|
335
|
-
return version_conflict(current_traversal) if parent.nil? || parent.name == 'bundler'
|
336
|
-
|
337
|
-
reqs, activated, depth, conflicts = resolve_conflict(parent, states)
|
338
|
-
end
|
339
|
-
else
|
340
|
-
matching_versions = search(current)
|
341
|
-
|
342
|
-
# If we found no versions that match the current requirement
|
343
|
-
if matching_versions.empty?
|
344
|
-
# If this is a top-level Gemfile requirement
|
345
|
-
if current.required_by.empty?
|
346
|
-
if base = @base[current.name] and !base.empty?
|
347
|
-
version = base.first.version
|
348
|
-
message = "You have requested:\n" \
|
349
|
-
" #{current.name} #{current.requirement}\n\n" \
|
350
|
-
"The bundle currently has #{current.name} locked at #{version}.\n" \
|
351
|
-
"Try running `bundle update #{current.name}`"
|
352
|
-
elsif current.source
|
353
|
-
name = current.name
|
354
|
-
versions = @source_requirements[name][name].map { |s| s.version }
|
355
|
-
message = "Could not find gem '#{current}' in #{current.source}.\n"
|
356
|
-
if versions.any?
|
357
|
-
message << "Source contains '#{name}' at: #{versions.join(', ')}"
|
358
|
-
else
|
359
|
-
message << "Source does not contain any versions of '#{current}'"
|
360
|
-
end
|
361
|
-
else
|
362
|
-
message = "Could not find gem '#{current}' "
|
363
|
-
if @index.source_types.include?(Bundler::Source::Rubygems)
|
364
|
-
message << "in any of the gem sources listed in your Gemfile."
|
365
|
-
else
|
366
|
-
message << "in the gems available on this machine."
|
367
|
-
end
|
368
|
-
end
|
369
|
-
raise GemNotFound, message
|
370
|
-
# This is not a top-level Gemfile requirement
|
371
|
-
else
|
372
|
-
@errors[current.name] = [nil, current]
|
373
|
-
parent = handle_conflict(current, states)
|
374
|
-
reqs, activated, depth = resolve_conflict(parent, states)
|
375
|
-
next
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
|
380
|
-
state = State.new(reqs.dup, activated.dup, current, matching_versions, depth, conflicts)
|
381
|
-
states << state
|
382
|
-
requirement = state.possibles.pop
|
383
|
-
activate_gem(reqs, activated, requirement, current)
|
250
|
+
def search_for(dependency)
|
251
|
+
platform = dependency.__platform
|
252
|
+
dependency = dependency.dep unless dependency.is_a? Gem::Dependency
|
253
|
+
search = @search_for[dependency] ||= begin
|
254
|
+
index = @source_requirements[dependency.name] || @index
|
255
|
+
results = index.search(dependency, @base[dependency.name])
|
256
|
+
if vertex = @base_dg.vertex_named(dependency.name)
|
257
|
+
locked_requirement = vertex.payload.requirement
|
384
258
|
end
|
385
|
-
end
|
386
|
-
successify(activated)
|
387
|
-
end
|
388
|
-
|
389
|
-
def gems_size(dep)
|
390
|
-
search(dep).size
|
391
|
-
end
|
392
|
-
|
393
|
-
def clear_search_cache
|
394
|
-
@deps_for = {}
|
395
|
-
end
|
396
|
-
|
397
|
-
def search(dep)
|
398
|
-
if base = @base[dep.name] and base.any?
|
399
|
-
reqs = [dep.requirement.as_list, base.first.version.to_s].flatten.compact
|
400
|
-
d = Gem::Dependency.new(base.first.name, *reqs)
|
401
|
-
else
|
402
|
-
d = dep.dep
|
403
|
-
end
|
404
|
-
|
405
|
-
@deps_for[d.hash] ||= begin
|
406
|
-
index = @source_requirements[d.name] || @index
|
407
|
-
results = index.search(d, @base[d.name])
|
408
|
-
|
409
259
|
if results.any?
|
410
260
|
version = results.first.version
|
411
261
|
nested = [[]]
|
@@ -416,139 +266,74 @@ module Bundler
|
|
416
266
|
end
|
417
267
|
nested.last << spec
|
418
268
|
end
|
419
|
-
|
269
|
+
groups = nested.map { |a| SpecGroup.new(a) }
|
270
|
+
!locked_requirement ? groups : groups.select { |sg| locked_requirement.satisfied_by? sg.version }
|
420
271
|
else
|
421
|
-
|
272
|
+
[]
|
422
273
|
end
|
423
274
|
end
|
275
|
+
search.select { |sg| sg.for?(platform) }.each { |sg| sg.activate_platform(platform) }
|
424
276
|
end
|
425
277
|
|
426
|
-
def
|
427
|
-
|
428
|
-
req.to_s.gsub(/ \(.*?\)$/, '')
|
429
|
-
else
|
430
|
-
req.to_s.gsub(/\, (runtime|development)\)$/, ')')
|
431
|
-
end
|
278
|
+
def name_for(dependency)
|
279
|
+
dependency.name
|
432
280
|
end
|
433
281
|
|
434
|
-
def
|
435
|
-
|
436
|
-
reset_state
|
437
|
-
start(initial_reqs, true)
|
282
|
+
def name_for_explicit_dependency_source
|
283
|
+
'Gemfile'
|
438
284
|
end
|
439
285
|
|
440
|
-
def
|
441
|
-
|
442
|
-
@errors = {}
|
286
|
+
def name_for_locking_dependency_source
|
287
|
+
'Gemfile.lock'
|
443
288
|
end
|
444
289
|
|
445
|
-
|
446
|
-
|
447
|
-
m = ""
|
448
|
-
|
449
|
-
# A requirement that is required by itself is actually in the Gemfile, and does
|
450
|
-
# not "depend on" itself
|
451
|
-
if requirement.required_by.first && requirement.required_by.first.name != requirement.name
|
452
|
-
dependency_tree(m, required_by)
|
453
|
-
m << "#{clean_req(requirement)}\n"
|
454
|
-
else
|
455
|
-
m << " #{clean_req(requirement)}\n"
|
456
|
-
end
|
457
|
-
m << "\n"
|
290
|
+
def requirement_satisfied_by?(requirement, activated, spec)
|
291
|
+
requirement.matches_spec?(spec)
|
458
292
|
end
|
459
293
|
|
460
|
-
def
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
294
|
+
def sort_dependencies(dependencies, activated, conflicts)
|
295
|
+
dependencies.sort_by do |dependency|
|
296
|
+
name = name_for(dependency)
|
297
|
+
[
|
298
|
+
activated.vertex_named(name).payload ? 0 : 1,
|
299
|
+
@prereleases_cache[dependency.requirement] ? 0 : 1,
|
300
|
+
conflicts[name] ? 0 : 1,
|
301
|
+
activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
|
302
|
+
]
|
465
303
|
end
|
466
|
-
m << " " << (" " * requirements.size)
|
467
304
|
end
|
468
305
|
|
469
|
-
def
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
end
|
489
|
-
|
490
|
-
required_by = origin.required_by[0..-2]
|
491
|
-
o << gem_message(origin, required_by)
|
492
|
-
|
493
|
-
# If the bundle wants a newer bundler than the running bundler, explain
|
494
|
-
if origin.name == "bundler" && other_bundler_required
|
495
|
-
o << "This Gemfile requires a different version of Bundler.\n"
|
496
|
-
o << "Perhaps you need to update Bundler by running `gem install bundler`?"
|
497
|
-
end
|
498
|
-
|
499
|
-
# origin is nil if the required gem and version cannot be found in any of
|
500
|
-
# the specified sources
|
501
|
-
else
|
502
|
-
|
503
|
-
# if the gem cannot be found because of a version conflict between lockfile and gemfile,
|
504
|
-
# print a useful error that suggests running `bundle update`, which may fix things
|
505
|
-
#
|
506
|
-
# @base is a SpecSet of the gems in the lockfile
|
507
|
-
# conflict is the name of the gem that could not be found
|
508
|
-
if locked = @base[conflict].first
|
509
|
-
o << "Bundler could not find compatible versions for gem #{conflict.inspect}:\n"
|
510
|
-
o << " In snapshot (Gemfile.lock):\n"
|
511
|
-
o << " #{clean_req(locked)}\n\n"
|
512
|
-
|
513
|
-
o << " In Gemfile:\n"
|
514
|
-
|
515
|
-
required_by = requirement.required_by
|
516
|
-
o << gem_message(requirement, required_by)
|
517
|
-
o << "Running `bundle update` will rebuild your snapshot from scratch, using only\n"
|
518
|
-
o << "the gems in your Gemfile, which may resolve the conflict.\n"
|
519
|
-
|
520
|
-
# the rest of the time, the gem cannot be found because it does not exist in the known sources
|
306
|
+
def verify_gemfile_dependencies_are_found!(requirements)
|
307
|
+
requirements.each do |requirement|
|
308
|
+
next if requirement.name == 'bundler'
|
309
|
+
if search_for(requirement).empty?
|
310
|
+
if base = @base[requirement.name] and !base.empty?
|
311
|
+
version = base.first.version
|
312
|
+
message = "You have requested:\n" \
|
313
|
+
" #{requirement.name} #{requirement.requirement}\n\n" \
|
314
|
+
"The bundle currently has #{requirement.name} locked at #{version}.\n" \
|
315
|
+
"Try running `bundle update #{requirement.name}`"
|
316
|
+
elsif requirement.source
|
317
|
+
name = requirement.name
|
318
|
+
versions = @source_requirements[name][name].map { |s| s.version }
|
319
|
+
message = "Could not find gem '#{requirement}' in #{requirement.source}.\n"
|
320
|
+
if versions.any?
|
321
|
+
message << "Source contains '#{name}' at: #{versions.join(', ')}"
|
322
|
+
else
|
323
|
+
message << "Source does not contain any versions of '#{requirement}'"
|
324
|
+
end
|
521
325
|
else
|
522
|
-
|
523
|
-
|
524
|
-
|
326
|
+
message = "Could not find gem '#{requirement}' "
|
327
|
+
if @index.source_types.include?(Bundler::Source::Rubygems)
|
328
|
+
message << "in any of the gem sources listed in your Gemfile."
|
525
329
|
else
|
526
|
-
|
330
|
+
message << "in the gems available on this machine."
|
527
331
|
end
|
528
332
|
end
|
529
|
-
|
333
|
+
raise GemNotFound, message
|
530
334
|
end
|
531
|
-
o
|
532
335
|
end
|
533
336
|
end
|
534
337
|
|
535
|
-
private
|
536
|
-
|
537
|
-
# Indicates progress by writing a '.' every iteration_rate time which is
|
538
|
-
# approximately every second. iteration_rate is calculated in the first
|
539
|
-
# second of resolve running.
|
540
|
-
def indicate_progress
|
541
|
-
@iteration_counter += 1
|
542
|
-
|
543
|
-
if iteration_rate.nil?
|
544
|
-
if ((Time.now - started_at) % 3600).round >= 1
|
545
|
-
@iteration_rate = iteration_counter
|
546
|
-
end
|
547
|
-
else
|
548
|
-
if ((iteration_counter % iteration_rate) == 0)
|
549
|
-
Bundler.ui.info ".", false
|
550
|
-
end
|
551
|
-
end
|
552
|
-
end
|
553
338
|
end
|
554
339
|
end
|