diff options
Diffstat (limited to 'lib/bundler/installer/parallel_installer.rb')
-rw-r--r-- | lib/bundler/installer/parallel_installer.rb | 228 |
1 files changed, 0 insertions, 228 deletions
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb deleted file mode 100644 index 95d9575c44..0000000000 --- a/lib/bundler/installer/parallel_installer.rb +++ /dev/null @@ -1,228 +0,0 @@ -# frozen_string_literal: true - -require "bundler/worker" -require "bundler/installer/gem_installer" - -module Bundler - class ParallelInstaller - class SpecInstallation - attr_accessor :spec, :name, :post_install_message, :state, :error - def initialize(spec) - @spec = spec - @name = spec.name - @state = :none - @post_install_message = "" - @error = nil - end - - def installed? - state == :installed - end - - def enqueued? - state == :enqueued - end - - def failed? - state == :failed - end - - def installation_attempted? - installed? || failed? - end - - # Only true when spec in neither installed nor already enqueued - def ready_to_enqueue? - !enqueued? && !installation_attempted? - end - - def has_post_install_message? - !post_install_message.empty? - end - - def ignorable_dependency?(dep) - dep.type == :development || dep.name == @name - end - - # Checks installed dependencies against spec's dependencies to make - # sure needed dependencies have been installed. - def dependencies_installed?(all_specs) - installed_specs = all_specs.select(&:installed?).map(&:name) - dependencies.all? {|d| installed_specs.include? d.name } - end - - # Represents only the non-development dependencies, the ones that are - # itself and are in the total list. - def dependencies - @dependencies ||= begin - all_dependencies.reject {|dep| ignorable_dependency? dep } - end - end - - def missing_lockfile_dependencies(all_spec_names) - deps = all_dependencies.reject {|dep| ignorable_dependency? dep } - deps.reject {|dep| all_spec_names.include? dep.name } - end - - # Represents all dependencies - def all_dependencies - @spec.dependencies - end - - def to_s - "#<#{self.class} #{@spec.full_name} (#{state})>" - end - end - - def self.call(*args) - new(*args).call - end - - attr_reader :size - - def initialize(installer, all_specs, size, standalone, force) - @installer = installer - @size = size - @standalone = standalone - @force = force - @specs = all_specs.map {|s| SpecInstallation.new(s) } - @spec_set = all_specs - end - - def call - # Since `autoload` has the potential for threading issues on 1.8.7 - # TODO: remove in bundler 2.0 - require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9" - - check_for_corrupt_lockfile - - 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 check_for_corrupt_lockfile - missing_dependencies = @specs.map do |s| - [ - s, - s.missing_lockfile_dependencies(@specs.map(&:name)), - ] - end.reject { |a| a.last.empty? } - return if missing_dependencies.empty? - - warning = [] - warning << "Your lockfile was created by an old Bundler that left some things out." - if @size != 1 - warning << "Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing #{@size} at a time." - @size = 1 - end - warning << "You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile." - warning << "The missing gems are:" - - missing_dependencies.each do |spec, missing| - warning << "* #{missing.map(&:name).join(", ")} depended upon by #{spec.name}" - end - - 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") - tree.each_with_index do |s, depth| - t << " " * depth.succ << s.name - unless tree.last == s - t << %( was resolved to #{s.version}, which depends on) - end - t << %(\n) - end - t - end - - # Keys in the remains hash represent uninstalled gems specs. - # We enqueue all gem specs that do not have any dependencies. - # Later we call this lambda again to install specs that depended on - # previously installed specifications. We continue until all specs - # are installed. - def enqueue_specs - @specs.select(&:ready_to_enqueue?).each do |spec| - if spec.dependencies_installed? @specs - spec.state = :enqueued - worker_pool.enq spec - end - end - end - end -end |