bundler 1.10.6 → 1.11.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +105 -0
  3. data/.rubocop_todo.yml +120 -0
  4. data/.travis.yml +8 -23
  5. data/CHANGELOG.md +69 -0
  6. data/CODE_OF_CONDUCT.md +6 -4
  7. data/DEVELOPMENT.md +4 -5
  8. data/README.md +2 -2
  9. data/Rakefile +70 -87
  10. data/bin/rake +14 -0
  11. data/bin/rspec +10 -0
  12. data/bin/rubocop +11 -0
  13. data/bundler.gemspec +17 -15
  14. data/exe/bundle +20 -0
  15. data/{bin → exe}/bundle_ruby +6 -4
  16. data/exe/bundler +20 -0
  17. data/lib/bundler.rb +98 -119
  18. data/lib/bundler/capistrano.rb +2 -2
  19. data/lib/bundler/cli.rb +85 -74
  20. data/lib/bundler/cli/binstubs.rb +1 -2
  21. data/lib/bundler/cli/cache.rb +0 -1
  22. data/lib/bundler/cli/check.rb +7 -5
  23. data/lib/bundler/cli/clean.rb +0 -1
  24. data/lib/bundler/cli/common.rb +6 -7
  25. data/lib/bundler/cli/config.rb +69 -56
  26. data/lib/bundler/cli/console.rb +8 -8
  27. data/lib/bundler/cli/exec.rb +4 -3
  28. data/lib/bundler/cli/gem.rb +50 -39
  29. data/lib/bundler/cli/init.rb +5 -6
  30. data/lib/bundler/cli/inject.rb +1 -2
  31. data/lib/bundler/cli/install.rb +18 -21
  32. data/lib/bundler/cli/lock.rb +8 -3
  33. data/lib/bundler/cli/open.rb +4 -5
  34. data/lib/bundler/cli/outdated.rb +7 -8
  35. data/lib/bundler/cli/package.rb +1 -1
  36. data/lib/bundler/cli/platform.rb +2 -3
  37. data/lib/bundler/cli/show.rb +9 -9
  38. data/lib/bundler/cli/update.rb +2 -3
  39. data/lib/bundler/cli/viz.rb +1 -2
  40. data/lib/bundler/constants.rb +1 -1
  41. data/lib/bundler/current_ruby.rb +38 -3
  42. data/lib/bundler/definition.rb +83 -88
  43. data/lib/bundler/dep_proxy.rb +11 -9
  44. data/lib/bundler/dependency.rb +26 -11
  45. data/lib/bundler/deployment.rb +2 -2
  46. data/lib/bundler/deprecate.rb +3 -3
  47. data/lib/bundler/dsl.rb +63 -44
  48. data/lib/bundler/env.rb +19 -12
  49. data/lib/bundler/environment.rb +1 -2
  50. data/lib/bundler/errors.rb +82 -0
  51. data/lib/bundler/fetcher.rb +45 -39
  52. data/lib/bundler/fetcher/base.rb +20 -7
  53. data/lib/bundler/fetcher/dependency.rb +5 -5
  54. data/lib/bundler/fetcher/downloader.rb +1 -2
  55. data/lib/bundler/fetcher/index.rb +4 -7
  56. data/lib/bundler/friendly_errors.rb +15 -8
  57. data/lib/bundler/gem_helper.rb +44 -35
  58. data/lib/bundler/gem_helpers.rb +7 -8
  59. data/lib/bundler/gem_remote_fetcher.rb +41 -0
  60. data/lib/bundler/gem_tasks.rb +4 -1
  61. data/lib/bundler/graph.rb +25 -24
  62. data/lib/bundler/index.rb +21 -18
  63. data/lib/bundler/injector.rb +2 -4
  64. data/lib/bundler/inline.rb +3 -3
  65. data/lib/bundler/installer.rb +57 -144
  66. data/lib/bundler/installer/gem_installer.rb +76 -0
  67. data/lib/bundler/installer/parallel_installer.rb +22 -13
  68. data/lib/bundler/installer/standalone.rb +48 -0
  69. data/lib/bundler/lazy_specification.rb +3 -4
  70. data/lib/bundler/lockfile_parser.rb +21 -19
  71. data/lib/bundler/match_platform.rb +4 -4
  72. data/lib/bundler/psyched_yaml.rb +3 -3
  73. data/lib/bundler/remote_specification.rb +1 -1
  74. data/lib/bundler/resolver.rb +93 -88
  75. data/lib/bundler/retry.rb +9 -10
  76. data/lib/bundler/ruby_dsl.rb +1 -1
  77. data/lib/bundler/ruby_version.rb +7 -10
  78. data/lib/bundler/rubygems_ext.rb +32 -27
  79. data/lib/bundler/{gem_installer.rb → rubygems_gem_installer.rb} +2 -2
  80. data/lib/bundler/rubygems_integration.rb +85 -70
  81. data/lib/bundler/runtime.rb +57 -61
  82. data/lib/bundler/settings.rb +27 -26
  83. data/lib/bundler/setup.rb +3 -3
  84. data/lib/bundler/shared_helpers.rb +45 -20
  85. data/lib/bundler/similarity_detector.rb +19 -21
  86. data/lib/bundler/source.rb +4 -5
  87. data/lib/bundler/source/git.rb +29 -31
  88. data/lib/bundler/source/git/git_proxy.rb +52 -26
  89. data/lib/bundler/source/path.rb +25 -28
  90. data/lib/bundler/source/path/installer.rb +4 -4
  91. data/lib/bundler/source/rubygems.rb +62 -48
  92. data/lib/bundler/source/rubygems/remote.rb +3 -3
  93. data/lib/bundler/source_list.rb +4 -4
  94. data/lib/bundler/spec_set.rb +17 -15
  95. data/lib/bundler/ssl_certs/certificate_manager.rb +5 -6
  96. data/lib/bundler/stub_specification.rb +2 -2
  97. data/lib/bundler/templates/Executable +5 -5
  98. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +42 -6
  99. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  100. data/lib/bundler/templates/newgem/Rakefile.tt +4 -2
  101. data/lib/bundler/templates/newgem/bin/setup.tt +2 -1
  102. data/lib/bundler/templates/newgem/newgem.gemspec.tt +2 -2
  103. data/lib/bundler/ui.rb +3 -3
  104. data/lib/bundler/ui/rg_proxy.rb +2 -2
  105. data/lib/bundler/ui/shell.rb +10 -6
  106. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +82 -71
  107. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  108. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +9 -0
  109. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +40 -21
  110. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -0
  111. data/lib/bundler/vendored_molinillo.rb +1 -1
  112. data/lib/bundler/vendored_persistent.rb +3 -3
  113. data/lib/bundler/vendored_thor.rb +2 -2
  114. data/lib/bundler/version.rb +1 -1
  115. data/lib/bundler/vlad.rb +1 -1
  116. data/lib/bundler/worker.rb +4 -5
  117. data/man/bundle-config.ronn +4 -2
  118. data/man/bundle-gem.ronn +77 -0
  119. data/man/bundle-install.ronn +13 -6
  120. data/man/bundle-lock.ronn +47 -0
  121. data/man/bundle.ronn +1 -1
  122. data/man/gemfile.5.ronn +8 -0
  123. data/man/index.txt +1 -0
  124. metadata +37 -8
  125. data/bin/bundle +0 -21
  126. data/bin/bundler +0 -21
@@ -40,14 +40,14 @@ module Bundler
40
40
  # return an array of the deps that we added
41
41
  return @new_deps
42
42
  ensure
43
- Bundler.settings[:frozen] = '1' if frozen
43
+ Bundler.settings[:frozen] = "1" if frozen
44
44
  end
45
45
 
46
46
  private
47
47
 
48
48
  def new_gem_lines
49
49
  @new_deps.map do |d|
50
- %|gem '#{d.name}', '#{d.requirement}'|
50
+ %(gem '#{d.name}', '#{d.requirement}')
51
51
  end.join("\n")
52
52
  end
53
53
 
@@ -58,7 +58,5 @@ module Bundler
58
58
  f.puts new_gem_lines
59
59
  end
60
60
  end
61
-
62
-
63
61
  end
64
62
  end
@@ -28,12 +28,12 @@
28
28
  # puts Pod::VERSION # => "0.34.4"
29
29
  #
30
30
  def gemfile(install = false, &gemfile)
31
- require 'bundler'
31
+ require "bundler"
32
32
  old_root = Bundler.method(:root)
33
33
  def Bundler.root
34
- Pathname.pwd.expand_path
34
+ Bundler::SharedHelpers.pwd.expand_path
35
35
  end
36
- ENV['BUNDLE_GEMFILE'] ||= 'Gemfile'
36
+ ENV["BUNDLE_GEMFILE"] ||= "Gemfile"
37
37
 
38
38
  builder = Bundler::Dsl.new
39
39
  builder.instance_eval(&gemfile)
@@ -1,6 +1,9 @@
1
- require 'erb'
2
- require 'rubygems/dependency_installer'
3
- require 'bundler/worker'
1
+ require "erb"
2
+ require "rubygems/dependency_installer"
3
+ require "bundler/worker"
4
+ require "bundler/installer/parallel_installer"
5
+ require "bundler/installer/standalone"
6
+ require "bundler/installer/gem_installer"
4
7
 
5
8
  module Bundler
6
9
  class Installer < Environment
@@ -63,83 +66,11 @@ module Bundler
63
66
  return
64
67
  end
65
68
 
66
- if Bundler.default_lockfile.exist? && !options["update"]
67
- local = Bundler.ui.silence do
68
- begin
69
- tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
70
- true unless tmpdef.new_platform? || tmpdef.missing_specs.any?
71
- rescue BundlerError
72
- end
73
- end
74
- end
75
-
76
- # Since we are installing, we can resolve the definition
77
- # using remote specs
78
- unless local
79
- options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
80
- end
81
-
82
- force = options["force"]
83
-
84
- # the order that the resolver provides is significant, since
85
- # dependencies might actually affect the installation of a gem.
86
- # that said, it's a rare situation (other than rake), and parallel
87
- # installation is just SO MUCH FASTER. so we let people opt in.
88
- jobs = [Bundler.settings[:jobs].to_i-1, 1].max
89
- if jobs > 1 && can_install_in_parallel?
90
- require 'bundler/installer/parallel_installer'
91
- install_in_parallel jobs, options[:standalone], force
92
- else
93
- install_sequentially options[:standalone], force
94
- end
69
+ resolve_if_need(options)
70
+ install(options)
95
71
 
96
72
  lock unless Bundler.settings[:frozen]
97
- generate_standalone(options[:standalone]) if options[:standalone]
98
- end
99
-
100
- def install_gem_from_spec(spec, standalone = false, worker = 0, force = false)
101
- # Fetch the build settings, if there are any
102
- settings = Bundler.settings["build.#{spec.name}"]
103
- install_options = { :force => force, :ensure_builtin_gems_cached => standalone }
104
-
105
- post_install_message = nil
106
- if settings
107
- # Build arguments are global, so this is mutexed
108
- Bundler.rubygems.with_build_args [settings] do
109
- post_install_message = spec.source.install(spec, install_options)
110
- end
111
- else
112
- post_install_message = spec.source.install(spec, install_options)
113
- end
114
-
115
- Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
116
-
117
- if Bundler.settings[:bin] && standalone
118
- generate_standalone_bundler_executable_stubs(spec)
119
- elsif Bundler.settings[:bin]
120
- generate_bundler_executable_stubs(spec, :force => true)
121
- end
122
-
123
- post_install_message
124
- rescue Errno::ENOSPC
125
- raise Bundler::InstallError, "Your disk is out of space. Free some " \
126
- "space to be able to install your bundle."
127
- rescue Exception => e
128
- # if install hook failed or gem signature is bad, just die
129
- raise e if e.is_a?(Bundler::InstallHookError) || e.is_a?(Bundler::SecurityError)
130
-
131
- # other failure, likely a native extension build failure
132
- Bundler.ui.info ""
133
- Bundler.ui.warn "#{e.class}: #{e.message}"
134
- msg = "An error occurred while installing #{spec.name} (#{spec.version}),"
135
- msg << " and Bundler cannot continue."
136
-
137
- unless spec.source.options["git"]
138
- msg << "\nMake sure that `gem install"
139
- msg << " #{spec.name} -v '#{spec.version}'` succeeds before bundling."
140
- end
141
- Bundler.ui.debug e.backtrace.join("\n")
142
- raise Bundler::InstallError, msg
73
+ Standalone.new(options[:standalone], @definition).generate if options[:standalone]
143
74
  end
144
75
 
145
76
  def generate_bundler_executable_stubs(spec, options = {})
@@ -150,9 +81,9 @@ module Bundler
150
81
  options[dep.name] = bins unless bins.empty?
151
82
  end
152
83
  if options.any?
153
- Bundler.ui.warn "#{spec.name} has no executables, but you may want " +
84
+ Bundler.ui.warn "#{spec.name} has no executables, but you may want " \
154
85
  "one from a gem it depends on."
155
- options.each{|name,bins| Bundler.ui.warn " #{name} has: #{bins.join(', ')}" }
86
+ options.each {|name, bins| Bundler.ui.warn " #{name} has: #{bins.join(", ")}" }
156
87
  else
157
88
  Bundler.ui.warn "There are no executables for the gem #{spec.name}."
158
89
  end
@@ -161,7 +92,7 @@ module Bundler
161
92
 
162
93
  # double-assignment to avoid warnings about variables that will be used by ERB
163
94
  bin_path = bin_path = Bundler.bin_path
164
- template = template = File.read(File.expand_path('../templates/Executable', __FILE__))
95
+ template = template = File.read(File.expand_path("../templates/Executable", __FILE__))
165
96
  relative_gemfile_path = relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
166
97
  ruby_command = ruby_command = Thor::Util.ruby_command
167
98
 
@@ -175,8 +106,8 @@ module Bundler
175
106
  next
176
107
  end
177
108
 
178
- File.open(binstub_path, 'w', 0777 & ~File.umask) do |f|
179
- f.puts ERB.new(template, nil, '-').result(binding)
109
+ File.open(binstub_path, "w", 0777 & ~File.umask) do |f|
110
+ f.puts ERB.new(template, nil, "-").result(binding)
180
111
  end
181
112
  end
182
113
 
@@ -185,88 +116,53 @@ module Bundler
185
116
  when 1
186
117
  Bundler.ui.warn "Skipped #{exists[0]} since it already exists."
187
118
  when 2
188
- Bundler.ui.warn "Skipped #{exists.join(' and ')} since they already exist."
119
+ Bundler.ui.warn "Skipped #{exists.join(" and ")} since they already exist."
189
120
  else
190
- items = exists[0...-1].empty? ? nil : exists[0...-1].join(', ')
191
- skipped = [items, exists[-1]].compact.join(' and ')
121
+ items = exists[0...-1].empty? ? nil : exists[0...-1].join(", ")
122
+ skipped = [items, exists[-1]].compact.join(" and ")
192
123
  Bundler.ui.warn "Skipped #{skipped} since they already exist."
193
124
  end
194
125
  Bundler.ui.warn "If you want to overwrite skipped stubs, use --force."
195
126
  end
196
127
  end
197
128
 
198
- private
199
-
200
- def can_install_in_parallel?
201
- if Bundler.rubygems.provides?(">= 2.1.0")
202
- true
203
- else
204
- Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
205
- "gems must be installed one at a time. Upgrade to Rubygems 2.1.0 " \
206
- "or higher to enable parallel gem installation."
207
- false
208
- end
209
- end
210
-
211
129
  def generate_standalone_bundler_executable_stubs(spec)
212
130
  # double-assignment to avoid warnings about variables that will be used by ERB
213
131
  bin_path = Bundler.bin_path
214
- template = File.read(File.expand_path('../templates/Executable.standalone', __FILE__))
132
+ template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
215
133
  ruby_command = ruby_command = Thor::Util.ruby_command
216
134
 
217
135
  spec.executables.each do |executable|
218
136
  next if executable == "bundle"
219
137
  standalone_path = standalone_path = Pathname(Bundler.settings[:path]).expand_path.relative_path_from(bin_path)
220
138
  executable_path = executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
221
- File.open "#{bin_path}/#{executable}", 'w', 0755 do |f|
222
- f.puts ERB.new(template, nil, '-').result(binding)
139
+ File.open "#{bin_path}/#{executable}", "w", 0755 do |f|
140
+ f.puts ERB.new(template, nil, "-").result(binding)
223
141
  end
224
142
  end
225
143
  end
226
144
 
227
- def generate_standalone(groups)
228
- standalone_path = Bundler.settings[:path]
229
- bundler_path = File.join(standalone_path, "bundler")
230
- FileUtils.mkdir_p(bundler_path)
231
-
232
- paths = []
233
-
234
- if groups.empty?
235
- specs = @definition.requested_specs
236
- else
237
- specs = @definition.specs_for groups.map { |g| g.to_sym }
238
- end
239
-
240
- specs.each do |spec|
241
- next if spec.name == "bundler"
242
- next if spec.require_paths.nil? # builtin gems
243
-
244
- spec.require_paths.each do |path|
245
- full_path = File.join(spec.full_gem_path, path)
246
- gem_path = Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path))
247
- paths << gem_path.to_s.sub("#{Bundler.ruby_version.engine}/#{RbConfig::CONFIG['ruby_version']}", '#{ruby_engine}/#{ruby_version}')
248
- end
249
- end
250
-
145
+ private
251
146
 
252
- File.open File.join(bundler_path, "setup.rb"), "w" do |file|
253
- file.puts "require 'rbconfig'"
254
- file.puts "# ruby 1.8.7 doesn't define RUBY_ENGINE"
255
- file.puts "ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'"
256
- file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
257
- file.puts "path = File.expand_path('..', __FILE__)"
258
- paths.each do |path|
259
- file.puts %{$:.unshift "\#{path}/#{path}"}
260
- end
261
- end
147
+ # the order that the resolver provides is significant, since
148
+ # dependencies might actually affect the installation of a gem.
149
+ # that said, it's a rare situation (other than rake), and parallel
150
+ # installation is just SO MUCH FASTER. so we let people opt in.
151
+ def install(options)
152
+ force = options["force"]
153
+ jobs = 1
154
+ jobs = [Bundler.settings[:jobs].to_i - 1, 1].max if can_install_in_parallel?
155
+ install_in_parallel jobs, options[:standalone], force
262
156
  end
263
157
 
264
- def install_sequentially(standalone, force = false)
265
- specs.each do |spec|
266
- message = install_gem_from_spec spec, standalone, 0, force
267
- if message
268
- Installer.post_install_messages[spec.name] = message
269
- end
158
+ def can_install_in_parallel?
159
+ if Bundler.rubygems.provides?(">= 2.1.0")
160
+ true
161
+ else
162
+ Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
163
+ "gems will be installed one at a time. Upgrade to Rubygems 2.1.0 " \
164
+ "or higher to enable parallel gem installation."
165
+ false
270
166
  end
271
167
  end
272
168
 
@@ -275,11 +171,28 @@ module Bundler
275
171
  end
276
172
 
277
173
  def create_bundle_path
278
- Bundler.mkdir_p(Bundler.bundle_path.to_s) unless Bundler.bundle_path.exist?
174
+ SharedHelpers.filesystem_access(Bundler.bundle_path.to_s) do |p|
175
+ Bundler.mkdir_p(p)
176
+ end unless Bundler.bundle_path.exist?
279
177
  rescue Errno::EEXIST
280
- raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " +
178
+ raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " \
281
179
  "because of an invalid symlink. Remove the symlink so the directory can be created."
282
180
  end
283
181
 
182
+ def resolve_if_need(options)
183
+ if Bundler.default_lockfile.exist? && !options["update"]
184
+ local = Bundler.ui.silence do
185
+ begin
186
+ tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
187
+ true unless tmpdef.new_platform? || tmpdef.missing_specs.any?
188
+ rescue BundlerError
189
+ end
190
+ end
191
+ end
192
+
193
+ unless local
194
+ options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
195
+ end
196
+ end
284
197
  end
285
198
  end
@@ -0,0 +1,76 @@
1
+ module Bundler
2
+ class GemInstaller
3
+ attr_reader :spec, :standalone, :worker, :force, :installer
4
+
5
+ def initialize(spec, installer, standalone = false, worker = 0, force = false)
6
+ @spec = spec
7
+ @installer = installer
8
+ @standalone = standalone
9
+ @worker = worker
10
+ @force = force
11
+ end
12
+
13
+ def install_from_spec
14
+ post_install_message = spec_settings ? install_with_settings : install
15
+ Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
16
+ generate_executable_stubs
17
+ post_install_message
18
+
19
+ rescue Errno::ENOSPC
20
+ raise Bundler::InstallError, out_of_space_message
21
+ rescue => e
22
+ handle_exception(e)
23
+ end
24
+
25
+ private
26
+
27
+ def failure_message
28
+ return install_error_message if spec.source.options["git"]
29
+ "#{install_error_message}\n#{gem_install_message}"
30
+ end
31
+
32
+ def install_error_message
33
+ "An error occurred while installing #{spec.name} (#{spec.version}), and Bundler cannot continue."
34
+ end
35
+
36
+ def gem_install_message
37
+ "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
38
+ end
39
+
40
+ def handle_exception(e)
41
+ # if install hook failed or gem signature is bad, just die
42
+ raise e if e.is_a?(Bundler::InstallHookError) || e.is_a?(Bundler::SecurityError)
43
+ # other failure, likely a native extension build failure
44
+ Bundler.ui.info ""
45
+ Bundler.ui.warn "#{e.class}: #{e.message}"
46
+ Bundler.ui.debug e.backtrace.join("\n")
47
+ raise Bundler::InstallError, failure_message
48
+ end
49
+
50
+ def spec_settings
51
+ # Fetch the build settings, if there are any
52
+ Bundler.settings["build.#{spec.name}"]
53
+ end
54
+
55
+ def install
56
+ spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone)
57
+ end
58
+
59
+ def install_with_settings
60
+ # Build arguments are global, so this is mutexed
61
+ Bundler.rubygems.with_build_args([spec_settings]) { install }
62
+ end
63
+
64
+ def out_of_space_message
65
+ "Your disk is out of space. Free some space to be able to install your bundle."
66
+ end
67
+
68
+ def generate_executable_stubs
69
+ if Bundler.settings[:bin] && standalone
70
+ installer.generate_standalone_bundler_executable_stubs(spec)
71
+ elsif Bundler.settings[:bin]
72
+ installer.generate_bundler_executable_stubs(spec, :force => true)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,13 +1,12 @@
1
- require 'bundler/worker'
2
-
1
+ require "bundler/worker"
2
+ require "bundler/installer/gem_installer"
3
3
 
4
4
  class ParallelInstaller
5
-
6
5
  class SpecInstallation
7
-
8
6
  attr_accessor :spec, :name, :post_install_message, :state
9
7
  def initialize(spec)
10
- @spec, @name = spec, spec.name
8
+ @spec = spec
9
+ @name = spec.name
11
10
  @state = :none
12
11
  @post_install_message = ""
13
12
  end
@@ -37,13 +36,21 @@ class ParallelInstaller
37
36
  # sure needed dependencies have been installed.
38
37
  def dependencies_installed?(all_specs)
39
38
  installed_specs = all_specs.select(&:installed?).map(&:name)
40
- dependencies.all? {|d| installed_specs.include? d.name }
39
+ dependencies(all_specs.map(&:name)).all? {|d| installed_specs.include? d.name }
41
40
  end
42
41
 
43
- # Represents only the non-development dependencies and the ones that
44
- # are itself.
45
- def dependencies
46
- @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
42
+ # Represents only the non-development dependencies, the ones that are
43
+ # itself and are in the total list.
44
+ def dependencies(all_spec_names)
45
+ @dependencies ||= begin
46
+ deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
47
+ missing = deps.reject {|dep| all_spec_names.include? dep.name }
48
+ if missing.size > 0
49
+ raise Bundler::LockfileError, "Your Gemfile.lock is corrupt. The following #{missing.size > 1 ? "gems are" : "gem is"} missing " \
50
+ "from the DEPENDENCIES section: '#{missing.map(&:name).join('\' \'')}'"
51
+ end
52
+ deps
53
+ end
47
54
  end
48
55
 
49
56
  # Represents all dependencies
@@ -58,7 +65,7 @@ class ParallelInstaller
58
65
 
59
66
  # Returns max number of threads machine can handle with a min of 1
60
67
  def self.max_threads
61
- [Bundler.settings[:jobs].to_i-1, 1].max
68
+ [Bundler.settings[:jobs].to_i - 1, 1].max
62
69
  end
63
70
 
64
71
  def initialize(installer, all_specs, size, standalone, force)
@@ -66,7 +73,7 @@ class ParallelInstaller
66
73
  @size = size
67
74
  @standalone = standalone
68
75
  @force = force
69
- @specs = all_specs.map { |s| SpecInstallation.new(s) }
76
+ @specs = all_specs.map {|s| SpecInstallation.new(s) }
70
77
  end
71
78
 
72
79
  def call
@@ -78,7 +85,9 @@ class ParallelInstaller
78
85
 
79
86
  def worker_pool
80
87
  @worker_pool ||= Bundler::Worker.new @size, lambda { |spec_install, worker_num|
81
- message = @installer.install_gem_from_spec spec_install.spec, @standalone, worker_num, @force
88
+ message = Bundler::GemInstaller.new(
89
+ spec_install.spec, @installer, @standalone, worker_num, @force
90
+ ).install_from_spec
82
91
  spec_install.post_install_message = message unless message.nil?
83
92
  spec_install
84
93
  }