summaryrefslogtreecommitdiff
path: root/lib/bundler/installer.rb
diff options
context:
space:
mode:
authorhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-01 23:29:38 +0000
committerhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-11-01 23:29:38 +0000
commitbe7b5929126cb3e696ef222339237faba9b8fe5a (patch)
tree51eae376f93c09bc82dde5a657a91df2c89062e4 /lib/bundler/installer.rb
parentae49dbd392083f69026f2a0fff4a1d5f42d172a7 (diff)
Update bundled bundler to 1.16.0.
* lib/bundler, spec/bundler: Merge bundler-1.16.0. * common.mk: rspec examples of bundler-1.16.0 needs require option. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60603 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/bundler/installer.rb')
-rw-r--r--lib/bundler/installer.rb154
1 files changed, 104 insertions, 50 deletions
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index bce0e46393..d1066c9c19 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
require "erb"
require "rubygems/dependency_installer"
require "bundler/worker"
@@ -33,25 +34,26 @@ module Bundler
# Runs the install procedures for a specific Gemfile.
#
- # Firstly, this method will check to see if Bundler.bundle_path exists
- # and if not then will create it. This is usually the location of gems
- # on the system, be it RVM or at a system path.
+ # Firstly, this method will check to see if `Bundler.bundle_path` exists
+ # and if not then Bundler will create the directory. This is usually the same
+ # location as RubyGems which typically is the `~/.gem` directory
+ # unless other specified.
#
- # Secondly, it checks if Bundler has been configured to be "frozen"
+ # Secondly, it checks if Bundler has been configured to be "frozen".
# Frozen ensures that the Gemfile and the Gemfile.lock file are matching.
# This stops a situation where a developer may update the Gemfile but may not run
# `bundle install`, which leads to the Gemfile.lock file not being correctly updated.
# If this file is not correctly updated then any other developer running
# `bundle install` will potentially not install the correct gems.
#
- # Thirdly, Bundler checks if there are any dependencies specified in the Gemfile using
- # Bundler::Environment#dependencies. If there are no dependencies specified then
- # Bundler returns a warning message stating so and this method returns.
+ # Thirdly, Bundler checks if there are any dependencies specified in the Gemfile.
+ # If there are no dependencies specified then Bundler returns a warning message stating
+ # so and this method returns.
#
- # Fourthly, Bundler checks if the default lockfile (Gemfile.lock) exists, and if so
- # then proceeds to set up a definition based on the default gemfile (Gemfile) and the
- # default lock file (Gemfile.lock). However, this is not the case if the platform is different
- # to that which is specified in Gemfile.lock, or if there are any missing specs for the gems.
+ # Fourthly, Bundler checks if the Gemfile.lock exists, and if so
+ # then proceeds to set up a definition based on the Gemfile and the Gemfile.lock.
+ # During this step Bundler will also download information about any new gems
+ # that are not in the Gemfile.lock and resolve any dependencies if needed.
#
# Fifthly, Bundler resolves the dependencies either through a cache of gems or by remote.
# This then leads into the gems being installed, along with stubs for their executables,
@@ -61,26 +63,36 @@ module Bundler
# Sixthly, a new Gemfile.lock is created from the installed gems to ensure that the next time
# that a user runs `bundle install` they will receive any updates from this process.
#
- # Finally: TODO add documentation for how the standalone process works.
+ # Finally, if the user has specified the standalone flag, Bundler will generate the needed
+ # require paths and save them in a `setup.rb` file. See `bundle standalone --help` for more
+ # information.
def run(options)
create_bundle_path
- if Bundler.settings[:frozen]
- @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
- end
+ ProcessLock.lock do
+ if Bundler.frozen?
+ @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
+ end
- if @definition.dependencies.empty?
- Bundler.ui.warn "The Gemfile specifies no dependencies"
- lock
- return
- end
+ if @definition.dependencies.empty?
+ Bundler.ui.warn "The Gemfile specifies no dependencies"
+ lock
+ return
+ end
- resolve_if_need(options)
- ensure_specs_are_compatible!
- install(options)
+ if resolve_if_needed(options)
+ ensure_specs_are_compatible!
+ warn_on_incompatible_bundler_deps
+ load_plugins
+ options.delete(:jobs)
+ else
+ options[:jobs] = 1 # to avoid the overhead of Bundler::Worker
+ end
+ install(options)
- lock unless Bundler.settings[:frozen]
- Standalone.new(options[:standalone], @definition).generate if options[:standalone]
+ lock unless Bundler.frozen?
+ Standalone.new(options[:standalone], @definition).generate if options[:standalone]
+ end
end
def generate_bundler_executable_stubs(spec, options = {})
@@ -101,15 +113,21 @@ module Bundler
end
# double-assignment to avoid warnings about variables that will be used by ERB
- bin_path = bin_path = Bundler.bin_path
- template = template = File.read(File.expand_path("../templates/Executable", __FILE__))
- relative_gemfile_path = relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
- ruby_command = ruby_command = Thor::Util.ruby_command
+ bin_path = Bundler.bin_path
+ bin_path = bin_path
+ relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
+ relative_gemfile_path = relative_gemfile_path
+ ruby_command = Thor::Util.ruby_command
+ ruby_command = ruby_command
+ template_path = File.expand_path("../templates/Executable", __FILE__)
+ if spec.name == "bundler"
+ template_path += ".bundler"
+ spec.executables = %(bundle)
+ end
+ template = File.read(template_path)
exists = []
spec.executables.each do |executable|
- next if executable == "bundle"
-
binstub_path = "#{bin_path}/#{executable}"
if File.exist?(binstub_path) && !options[:force]
exists << executable
@@ -139,13 +157,19 @@ module Bundler
def generate_standalone_bundler_executable_stubs(spec)
# double-assignment to avoid warnings about variables that will be used by ERB
bin_path = Bundler.bin_path
- standalone_path = standalone_path = Bundler.root.join(Bundler.settings[:path]).relative_path_from(bin_path)
+ unless path = Bundler.settings[:path]
+ raise "Can't standalone without an explicit path set"
+ end
+ standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
+ standalone_path = standalone_path
template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
- ruby_command = ruby_command = Thor::Util.ruby_command
+ ruby_command = Thor::Util.ruby_command
+ ruby_command = ruby_command
spec.executables.each do |executable|
next if executable == "bundle"
- executable_path = executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
+ executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
+ executable_path = executable_path
File.open "#{bin_path}/#{executable}", "w", 0o755 do |f|
f.puts ERB.new(template, nil, "-").result(binding)
end
@@ -159,13 +183,32 @@ module Bundler
# that said, it's a rare situation (other than rake), and parallel
# installation is SO MUCH FASTER. so we let people opt in.
def install(options)
- Bundler.rubygems.load_plugins
force = options["force"]
- jobs = 1
- jobs = [Bundler.settings[:jobs].to_i - 1, 1].max if can_install_in_parallel?
+ jobs = options.delete(:jobs) do
+ if can_install_in_parallel?
+ [Bundler.settings[:jobs].to_i - 1, 1].max
+ else
+ 1
+ end
+ end
install_in_parallel jobs, options[:standalone], force
end
+ def load_plugins
+ Bundler.rubygems.load_plugins
+
+ requested_path_gems = @definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
+ path_plugin_files = requested_path_gems.map do |spec|
+ begin
+ Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
+ rescue TypeError
+ error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
+ raise Gem::InvalidSpecificationException, error_message
+ end
+ end.flatten
+ Bundler.rubygems.load_plugin_files(path_plugin_files)
+ end
+
def ensure_specs_are_compatible!
system_ruby = Bundler::RubyVersion.system
rubygems_version = Gem::Version.create(Gem::VERSION)
@@ -184,12 +227,28 @@ module Bundler
end
end
+ def warn_on_incompatible_bundler_deps
+ bundler_version = Gem::Version.create(Bundler::VERSION)
+ @definition.specs.each do |spec|
+ spec.dependencies.each do |dep|
+ next if dep.type == :development
+ next unless dep.name == "bundler".freeze
+ next if dep.requirement.satisfied_by?(bundler_version)
+
+ Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \
+ " #{SharedHelpers.pretty_dependency(dep)}" \
+ ", which is unsatisfied by the current bundler version #{VERSION}" \
+ ", so the dependency is being ignored"
+ end
+ end
+ end
+
def can_install_in_parallel?
if Bundler.rubygems.provides?(">= 2.1.0")
true
else
- Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
- "gems will be installed one at a time. Upgrade to Rubygems 2.1.0 " \
+ Bundler.ui.warn "RubyGems #{Gem::VERSION} is not threadsafe, so your "\
+ "gems will be installed one at a time. Upgrade to RubyGems 2.1.0 " \
"or higher to enable parallel gem installation."
false
end
@@ -207,23 +266,18 @@ module Bundler
Bundler.mkdir_p(p)
end unless Bundler.bundle_path.exist?
rescue Errno::EEXIST
- raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " \
+ raise PathError, "Could not install to path `#{Bundler.bundle_path}` " \
"because a file already exists at that path. Either remove or rename the file so the directory can be created."
end
- def resolve_if_need(options)
- if !options["update"] && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
- local = Bundler.ui.silence do
- begin
- tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
- true unless tmpdef.new_platform? || tmpdef.missing_dependencies.any?
- rescue BundlerError
- end
- end
+ # returns whether or not a re-resolve was needed
+ def resolve_if_needed(options)
+ if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
+ return false if @definition.nothing_changed? && !@definition.missing_specs?
end
- return if local
options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
+ true
end
def lock(opts = {})