diff options
Diffstat (limited to 'lib/bundler/installer')
-rw-r--r-- | lib/bundler/installer/gem_installer.rb | 2 | ||||
-rw-r--r-- | lib/bundler/installer/parallel_installer.rb | 115 | ||||
-rw-r--r-- | lib/bundler/installer/standalone.rb | 1 |
3 files changed, 76 insertions, 42 deletions
diff --git a/lib/bundler/installer/gem_installer.rb b/lib/bundler/installer/gem_installer.rb index a4d9bcaa07..086b763d20 100644 --- a/lib/bundler/installer/gem_installer.rb +++ b/lib/bundler/installer/gem_installer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Bundler class GemInstaller attr_reader :spec, :standalone, :worker, :force, :installer @@ -65,6 +66,7 @@ module Bundler end def generate_executable_stubs + return if Bundler.feature_flag.forget_cli_options? return if Bundler.settings[:inline] if Bundler.settings[:bin] && standalone installer.generate_standalone_bundler_executable_stubs(spec) diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb index 97c124e015..95d9575c44 100644 --- a/lib/bundler/installer/parallel_installer.rb +++ b/lib/bundler/installer/parallel_installer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "bundler/worker" require "bundler/installer/gem_installer" @@ -77,11 +78,6 @@ module Bundler new(*args).call end - # Returns max number of threads machine can handle with a min of 1 - def self.max_threads - [Bundler.settings[:jobs].to_i - 1, 1].max - end - attr_reader :size def initialize(installer, all_specs, size, standalone, force) @@ -99,49 +95,19 @@ module Bundler require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9" check_for_corrupt_lockfile - enqueue_specs - process_specs until @specs.all?(&:installed?) || @specs.any?(&:failed?) + + if @size > 1 + install_with_worker + else + install_serially + end + handle_error if @specs.any?(&:failed?) @specs ensure worker_pool && worker_pool.stop end - def worker_pool - @worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda { |spec_install, worker_num| - gem_installer = Bundler::GemInstaller.new( - spec_install.spec, @installer, @standalone, worker_num, @force - ) - success, message = gem_installer.install_from_spec - if success && !message.nil? - spec_install.post_install_message = message - elsif !success - spec_install.state = :failed - spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}" - end - spec_install - } - end - - # Dequeue a spec and save its post-install message and then enqueue the - # remaining specs. - # Some specs might've had to wait til this spec was installed to be - # processed so the call to `enqueue_specs` is important after every - # dequeue. - def process_specs - spec = worker_pool.deq - spec.state = :installed unless spec.failed? - enqueue_specs - end - - def handle_error - errors = @specs.select(&:failed?).map(&:error) - if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) } - raise exception - end - raise Bundler::InstallError, errors.map(&:to_s).join("\n\n") - end - def check_for_corrupt_lockfile missing_dependencies = @specs.map do |s| [ @@ -167,6 +133,71 @@ module Bundler Bundler.ui.warn(warning.join("\n")) end + private + + def install_with_worker + enqueue_specs + process_specs until finished_installing? + end + + def install_serially + until finished_installing? + raise "failed to find a spec to enqueue while installing serially" unless spec_install = @specs.find(&:ready_to_enqueue?) + spec_install.state = :enqueued + do_install(spec_install, 0) + end + end + + def worker_pool + @worker_pool ||= Bundler::Worker.new @size, "Parallel Installer", lambda { |spec_install, worker_num| + do_install(spec_install, worker_num) + } + end + + def do_install(spec_install, worker_num) + gem_installer = Bundler::GemInstaller.new( + spec_install.spec, @installer, @standalone, worker_num, @force + ) + success, message = begin + gem_installer.install_from_spec + rescue => e + raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}" + end + if success + spec_install.state = :installed + spec_install.post_install_message = message unless message.nil? + else + spec_install.state = :failed + spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}" + end + spec_install + end + + # Dequeue a spec and save its post-install message and then enqueue the + # remaining specs. + # Some specs might've had to wait til this spec was installed to be + # processed so the call to `enqueue_specs` is important after every + # dequeue. + def process_specs + worker_pool.deq + enqueue_specs + end + + def finished_installing? + @specs.all? do |spec| + return true if spec.failed? + spec.installed? + end + end + + def handle_error + errors = @specs.select(&:failed?).map(&:error) + if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) } + raise exception + end + raise Bundler::InstallError, errors.map(&:to_s).join("\n\n") + end + def require_tree_for_spec(spec) tree = @spec_set.what_required(spec) t = String.new("In #{File.basename(SharedHelpers.default_gemfile)}:\n") diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb index 03411d85e2..ce0c9df1eb 100644 --- a/lib/bundler/installer/standalone.rb +++ b/lib/bundler/installer/standalone.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module Bundler class Standalone def initialize(groups, definition) |