/usr/lib/ruby/vendor_ruby/bundler/installer/parallel_installer.rb is in ruby-bundler 1.13.6-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | # 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_specs.map(&:name)).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(all_spec_names)
@dependencies ||= begin
deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
missing = deps.reject {|dep| all_spec_names.include? dep.name }
unless missing.empty?
raise Bundler::LockfileError, "Your Gemfile.lock is corrupt. The following #{missing.size > 1 ? "gems are" : "gem is"} missing " \
"from the DEPENDENCIES section: '#{missing.map(&:name).join('\' \'')}'"
end
deps
end
end
# Represents all dependencies
def all_dependencies
@spec.dependencies
end
end
def self.call(*args)
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
def initialize(installer, all_specs, size, standalone, force)
@installer = installer
@size = size
@standalone = standalone
@force = force
@specs = all_specs.map {|s| SpecInstallation.new(s) }
end
def call
enqueue_specs
process_specs until @specs.all?(&:installed?) || @specs.any?(&:failed?)
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
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
# 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
|