summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2021-12-21 14:50:44 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2021-12-21 15:27:05 +0900
commit69dc2ea46538f47ff5edda3bb16863034bd19069 (patch)
treea4c545640fbdf31ab90f02a7def173840944806b
parentad450c9fe51c51626dd07f6e766f47d839cae3ba (diff)
Merge RubyGems-3.3.0 and Bundler-2.3.0
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5317
-rw-r--r--lib/bundler.rb8
-rw-r--r--lib/bundler/cli.rb2
-rw-r--r--lib/bundler/cli/install.rb2
-rw-r--r--lib/bundler/definition.rb2
-rw-r--r--lib/bundler/fetcher.rb3
-rw-r--r--lib/bundler/installer.rb2
-rw-r--r--lib/bundler/lockfile_parser.rb23
-rw-r--r--lib/bundler/plugin/installer.rb2
-rw-r--r--lib/bundler/rubygems_integration.rb33
-rw-r--r--lib/bundler/self_manager.rb73
-rw-r--r--lib/bundler/source/metadata.rb2
-rw-r--r--lib/bundler/templates/Executable.bundler2
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb2
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb2
-rw-r--r--spec/bundler/commands/binstubs_spec.rb18
-rw-r--r--spec/bundler/commands/check_spec.rb4
-rw-r--r--spec/bundler/lock/lockfile_spec.rb145
-rw-r--r--spec/bundler/runtime/platform_spec.rb2
-rw-r--r--spec/bundler/runtime/self_management_spec.rb109
-rw-r--r--spec/bundler/support/filters.rb1
-rw-r--r--spec/bundler/support/hax.rb2
-rw-r--r--spec/bundler/support/helpers.rb5
-rw-r--r--tool/bundler/rubocop_gems.rb.lock2
-rw-r--r--tool/bundler/standard_gems.rb.lock2
-rw-r--r--tool/bundler/test_gems.rb.lock2
26 files changed, 278 insertions, 174 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 81dfd05d26..89865a8254 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -66,6 +66,7 @@ module Bundler
autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__)
autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__)
autoload :Runtime, File.expand_path("bundler/runtime", __dir__)
+ autoload :SelfManager, File.expand_path("bundler/self_manager", __dir__)
autoload :Settings, File.expand_path("bundler/settings", __dir__)
autoload :SharedHelpers, File.expand_path("bundler/shared_helpers", __dir__)
autoload :Source, File.expand_path("bundler/source", __dir__)
@@ -643,6 +644,13 @@ EOF
Bundler.rubygems.clear_paths
end
+ def self_manager
+ @self_manager ||= begin
+ require_relative "bundler/self_manager"
+ Bundler::SelfManager.new
+ end
+ end
+
private
def eval_yaml_gemspec(path, contents)
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 36d0472c62..f6e20e7c67 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -61,6 +61,8 @@ module Bundler
Bundler.reset_settings_and_root!
end
+ Bundler.self_manager.restart_with_locked_bundler_if_needed
+
Bundler.settings.set_command_option_if_given :retry, options[:retry]
current_cmd = args.last[:current_command].name
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index 4c1915fea6..85f702bc64 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -12,6 +12,8 @@ module Bundler
warn_if_root
+ Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
+
Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD
# Disable color in deployment mode
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 84f0367ac7..9a94bd3ed3 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -294,7 +294,7 @@ module Bundler
if updating_major = locked_major < current_major
Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
- "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
+ "after which you will be unable to return to Bundler #{locked_major}."
end
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index 6dd6d089eb..a453157e68 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -122,7 +122,6 @@ module Bundler
# return the specs in the bundler format as an index
def specs(gem_names, source)
- old = Bundler.rubygems.sources
index = Bundler::Index.new
if Bundler::Fetcher.disable_endpoint
@@ -153,8 +152,6 @@ module Bundler
rescue CertificateFailureError
Bundler.ui.info "" if gem_names && use_api # newline after dots
raise
- ensure
- Bundler.rubygems.sources = old
end
def use_api
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 49ff177c0f..61bf1e06d4 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -239,7 +239,7 @@ module Bundler
def ensure_specs_are_compatible!
system_ruby = Bundler::RubyVersion.system
- rubygems_version = Gem::Version.create(Gem::VERSION)
+ rubygems_version = Bundler.rubygems.version
@definition.specs.each do |spec|
if required_ruby_version = spec.required_ruby_version
unless required_ruby_version.satisfied_by?(system_ruby.gem_version)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 6ff4910a36..e074cbfc33 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -46,6 +46,16 @@ module Bundler
attributes
end
+ def self.bundled_with
+ lockfile = Bundler.default_lockfile
+ return unless lockfile.file?
+
+ lockfile_contents = Bundler.read_file(lockfile)
+ return unless lockfile_contents.include?(BUNDLED)
+
+ lockfile_contents.split(BUNDLED).last.strip
+ end
+
def initialize(lockfile)
@platforms = []
@sources = []
@@ -77,25 +87,12 @@ module Bundler
end
end
@specs = @specs.values.sort_by(&:identifier)
- warn_for_outdated_bundler_version
rescue ArgumentError => e
Bundler.ui.debug(e)
raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \
"and then `bundle install` to generate a new lockfile."
end
- def warn_for_outdated_bundler_version
- return unless bundler_version
- return if bundler_version.segments.last == "dev"
- prerelease_text = bundler_version.prerelease? ? " --pre" : ""
- current_version = Gem::Version.create(Bundler::VERSION)
- return unless current_version < bundler_version
- Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \
- "than the version that created the lockfile (#{bundler_version}). We suggest you to " \
- "upgrade to the version that created the lockfile by running `gem install " \
- "bundler:#{bundler_version}#{prerelease_text}`.\n"
- end
-
private
TYPES = {
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index d7411fff45..81ecafa470 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -21,7 +21,7 @@ module Bundler
elsif options[:local_git]
install_local_git(names, version, options)
else
- sources = options[:source] || Bundler.rubygems.sources
+ sources = options[:source] || Gem.sources
install_rubygems(names, version, sources)
end
end
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index effb88c1cd..785f7fa360 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -12,25 +12,21 @@ module Bundler
EXT_LOCK = Monitor.new
end
- def self.version
- @version ||= Gem::Version.new(Gem::VERSION)
- end
-
- def self.provides?(req_str)
- Gem::Requirement.new(req_str).satisfied_by?(version)
- end
-
def initialize
@replaced_methods = {}
backport_ext_builder_monitor
end
def version
- self.class.version
+ @version ||= Gem.rubygems_version
end
def provides?(req_str)
- self.class.provides?(req_str)
+ Gem::Requirement.new(req_str).satisfied_by?(version)
+ end
+
+ def supports_bundler_trampolining?
+ provides?(">= 3.3.0.a")
end
def build_args
@@ -142,19 +138,6 @@ module Bundler
end
end
- def sources=(val)
- # Gem.configuration creates a new Gem::ConfigFile, which by default will read ~/.gemrc
- # If that file exists, its settings (including sources) will overwrite the values we
- # are about to set here. In order to avoid that, we force memoizing the config file now.
- configuration
-
- Gem.sources = val
- end
-
- def sources
- Gem.sources
- end
-
def gem_dir
Gem.dir
end
@@ -588,6 +571,10 @@ module Bundler
end
end
+ def find_bundler(version)
+ find_name("bundler").find {|s| s.version.to_s == version }
+ end
+
def find_name(name)
Gem::Specification.stubs_for(name).map(&:to_spec)
end
diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb
new file mode 100644
index 0000000000..bda2eb51f3
--- /dev/null
+++ b/lib/bundler/self_manager.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Bundler
+ #
+ # This class handles installing and switching to the version of bundler needed
+ # by an application.
+ #
+ class SelfManager
+ def restart_with_locked_bundler_if_needed
+ return unless needs_switching? && installed?
+
+ restart_with_locked_bundler
+ end
+
+ def install_locked_bundler_and_restart_with_it_if_needed
+ return unless needs_switching?
+
+ Bundler.ui.info \
+ "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \
+ "Installing Bundler #{lockfile_version} and restarting using that version."
+
+ install_and_restart_with_locked_bundler
+ end
+
+ private
+
+ def install_and_restart_with_locked_bundler
+ bundler_dep = Gem::Dependency.new("bundler", lockfile_version)
+
+ Gem.install(bundler_dep)
+ rescue StandardError => e
+ Bundler.ui.trace e
+ Bundler.ui.warn "There was an error installing the locked bundler version (#{lockfile_version}), rerun with the `--verbose` flag for more details. Going on using bundler #{current_version}."
+ else
+ restart_with_locked_bundler
+ end
+
+ def restart_with_locked_bundler
+ configured_gem_home = ENV["GEM_HOME"]
+ configured_gem_path = ENV["GEM_PATH"]
+
+ Bundler.with_original_env do
+ Kernel.exec(
+ { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => lockfile_version },
+ $PROGRAM_NAME, *ARGV
+ )
+ end
+ end
+
+ def needs_switching?
+ ENV["BUNDLER_VERSION"].nil? &&
+ Bundler.rubygems.supports_bundler_trampolining? &&
+ SharedHelpers.in_bundle? &&
+ lockfile_version &&
+ !lockfile_version.end_with?(".dev") &&
+ lockfile_version != current_version
+ end
+
+ def installed?
+ Bundler.configure
+
+ Bundler.rubygems.find_bundler(lockfile_version)
+ end
+
+ def current_version
+ @current_version ||= Bundler::VERSION
+ end
+
+ def lockfile_version
+ @lockfile_version ||= Bundler::LockfileParser.bundled_with
+ end
+ end
+end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 50b65ce0ea..8bdbaa5527 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -25,7 +25,7 @@ module Bundler
s.loaded_from = File.expand_path("..", __FILE__)
end
- if local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION }
+ if local_spec = Bundler.rubygems.find_bundler(VERSION)
idx << local_spec
end
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
index 8009412ea2..6bb5c51090 100644
--- a/lib/bundler/templates/Executable.bundler
+++ b/lib/bundler/templates/Executable.bundler
@@ -73,7 +73,7 @@ m = Module.new do
requirement = bundler_gem_version.approximate_recommendation
- return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
+ return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
requirement += ".a" if bundler_gem_version.prerelease?
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 0c0d9d360d..d987722f78 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.3.0.dev".freeze
+ VERSION = "2.3.0".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 40f3a893d8..a956e06bdb 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.3.0.dev".freeze
+ VERSION = "3.3.0".freeze
end
# Must be first since it unloads the prelude from 1.9.2
diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb
index e89720f6f7..2c50ee5afc 100644
--- a/spec/bundler/bundler/plugin/installer_spec.rb
+++ b/spec/bundler/bundler/plugin/installer_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Bundler::Plugin::Installer do
it "uses Gem.sources when non of the source is provided" do
sources = double(:sources)
Bundler.settings # initialize it before we have to touch rubygems.ext_lock
- allow(Bundler).to receive_message_chain("rubygems.sources") { sources }
+ allow(Gem).to receive(:sources) { sources }
allow(installer).to receive(:install_rubygems).
with("new-plugin", [">= 0"], sources).once
diff --git a/spec/bundler/commands/binstubs_spec.rb b/spec/bundler/commands/binstubs_spec.rb
index 1cd0e16d95..ceef07d36b 100644
--- a/spec/bundler/commands/binstubs_spec.rb
+++ b/spec/bundler/commands/binstubs_spec.rb
@@ -186,11 +186,25 @@ RSpec.describe "bundle binstubs <gem>" do
before do
lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 55.0")
+
+ update_repo2 do
+ with_built_bundler("55.0") {|gem_path| FileUtils.mv(gem_path, gem_repo2("gems")) }
+ end
+ end
+
+ it "installs and runs the exact version of bundler", :rubygems => ">= 3.3.0.dev" do
+ sys_exec "bin/bundle install --verbose", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s, "RUBYOPT" => "-r#{spec_dir}/support/hax.rb" }
+ expect(exitstatus).not_to eq(42)
+ expect(out).to include("Bundler 55.1 is running, but your lockfile was generated with 55.0. Installing Bundler 55.0 and restarting using that version.")
+ expect(out).to include("Using bundler 55.0")
+ expect(err).not_to include("Activating bundler (~> 55.0) failed:")
end
- it "runs the available version of bundler when the version is older and the same major" do
- sys_exec "bin/bundle install"
+ it "runs the available version of bundler", :rubygems => "< 3.3.0.dev" do
+ sys_exec "bin/bundle install --verbose"
expect(exitstatus).not_to eq(42)
+ expect(out).not_to include("Bundler 55.1 is running, but your lockfile was generated with 55.0. Installing Bundler 55.0 and restarting using that version.")
+ expect(out).to include("Using bundler 55.1")
expect(err).not_to include("Activating bundler (~> 55.0) failed:")
end
end
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index 1fa35136eb..e0c9a04c25 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -471,10 +471,10 @@ RSpec.describe "bundle check" do
end
context "is newer" do
- it "does not change the lock but warns" do
+ it "does not change the lock and does not warn" do
lockfile lock_with(Bundler::VERSION.succ)
bundle :check
- expect(err).to include("the running version of Bundler (#{Bundler::VERSION}) is older than the version that created the lockfile (#{Bundler::VERSION.succ})")
+ expect(err).to be_empty
expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 8befb0d400..a2a50d4cf0 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe "the lockfile format" do
G
end
- it "updates the lockfile's bundler version if current ver. is newer" do
+ it "updates the lockfile's bundler version if current ver. is newer, and version was forced through BUNDLER_VERSION" do
system_gems "bundler-1.8.2"
lockfile <<-L
@@ -64,12 +64,15 @@ RSpec.describe "the lockfile format" do
1.8.2
L
- install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ install_gemfile <<-G, :verbose => true, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.")
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -87,9 +90,13 @@ RSpec.describe "the lockfile format" do
G
end
- it "does not update the lockfile's bundler version if nothing changed during bundle install" do
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version", :rubygems => ">= 3.3.0.a" do
version = "#{Bundler::VERSION.split(".").first}.0.0.a"
+ update_repo2 do
+ with_built_bundler(version) {|gem_path| FileUtils.mv(gem_path, gem_repo2("gems")) }
+ end
+
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -106,12 +113,15 @@ RSpec.describe "the lockfile format" do
#{version}
L
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true, :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
+ expect(out).to include("Using bundler #{version}")
+
expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -129,97 +139,12 @@ RSpec.describe "the lockfile format" do
G
end
- it "updates the lockfile's bundler version if not present" do
- lockfile <<-L
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack
- L
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
-
- gem "rack", "> 0"
- G
-
- expect(lockfile).to eq <<~G
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack (> 0)
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "warns if the current version is older than lockfile's bundler version, and locked version is a final release" do
- current_version = "999.998.999"
- system_gems "bundler-#{current_version}"
- newer_minor = "999.999.0"
-
- lockfile <<-L
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{newer_minor}
- L
-
- install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
- source "#{file_uri_for(gem_repo2)}"
-
- gem "rack"
- G
-
- warning_message = "the running version of Bundler (#{current_version}) is older " \
- "than the version that created the lockfile (#{newer_minor}). " \
- "We suggest you to upgrade to the version that created the " \
- "lockfile by running `gem install bundler:#{newer_minor}`."
- expect(err).to include warning_message
-
- expect(lockfile).to eq <<~G
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{newer_minor}
- G
- end
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, and uses the latest version", :rubygems => "< 3.3.0.a" do
+ version = "#{Bundler::VERSION.split(".").first}.0.0.a"
- it "warns if the current version is older than lockfile's bundler version, and locked version is a prerelease" do
- current_version = "999.998.999"
- system_gems "bundler-#{current_version}"
- newer_minor = "999.999.0.pre1"
+ update_repo2 do
+ with_built_bundler(version) {|gem_path| FileUtils.mv(gem_path, gem_repo2("gems")) }
+ end
lockfile <<-L
GEM
@@ -234,20 +159,17 @@ RSpec.describe "the lockfile format" do
rack
BUNDLED WITH
- #{newer_minor}
+ #{version}
L
- install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
+ install_gemfile <<-G, :verbose => true, :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- warning_message = "the running version of Bundler (#{current_version}) is older " \
- "than the version that created the lockfile (#{newer_minor}). " \
- "We suggest you to upgrade to the version that created the " \
- "lockfile by running `gem install bundler:#{newer_minor} --pre`."
- expect(err).to include warning_message
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
expect(lockfile).to eq <<~G
GEM
@@ -262,15 +184,11 @@ RSpec.describe "the lockfile format" do
rack
BUNDLED WITH
- #{newer_minor}
+ #{version}
G
end
- it "doesn't warn if the current version is older than lockfile's bundler version, and locked version is a dev version" do
- current_version = "999.998.999"
- system_gems "bundler-#{current_version}"
- newer_minor = "999.999.0.dev"
-
+ it "adds the BUNDLED WITH section if not present" do
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -282,19 +200,14 @@ RSpec.describe "the lockfile format" do
DEPENDENCIES
rack
-
- BUNDLED WITH
- #{newer_minor}
L
- install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ gem "rack", "> 0"
G
- expect(err).to be_empty
-
expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -305,10 +218,10 @@ RSpec.describe "the lockfile format" do
#{lockfile_platforms}
DEPENDENCIES
- rack
+ rack (> 0)
BUNDLED WITH
- #{newer_minor}
+ #{Bundler::VERSION}
G
end
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index 433396d106..b937de8059 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -168,7 +168,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
BUNDLED WITH
- 2.1.4
+ #{Bundler::VERSION}
G
bundle "install"
diff --git a/spec/bundler/runtime/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb
new file mode 100644
index 0000000000..def9361d0f
--- /dev/null
+++ b/spec/bundler/runtime/self_management_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+RSpec.describe "Self management", :rubygems => ">= 3.3.0.dev" do
+ describe "auto switching" do
+ let(:next_minor) do
+ Bundler::VERSION.split(".").map.with_index {|s, i| i == 1 ? s.to_i + 1 : s }[0..2].join(".")
+ end
+
+ before do
+ build_repo2 do
+ with_built_bundler(next_minor) {|gem_path| FileUtils.mv(gem_path, gem_repo2("gems")) }
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rack"
+ G
+ end
+
+ it "installs locked version when using system path and uses it" do
+ lockfile_bundled_with(next_minor)
+
+ bundle "config set --local path.system true"
+ bundle "install", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{next_minor}. Installing Bundler #{next_minor} and restarting using that version.")
+
+ # It uninstalls the older system bundler
+ bundle "clean --force"
+ expect(out).to eq("Removing bundler (#{Bundler::VERSION})")
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to end_with(next_minor[0] == "2" ? "Bundler version #{next_minor}" : next_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{next_minor}")
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{next_minor}. Installing Bundler #{next_minor} and restarting using that version.")
+ end
+
+ it "installs locked version when using local path and uses it" do
+ lockfile_bundled_with(next_minor)
+
+ bundle "config set --local path vendor/bundle"
+ bundle "install", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{next_minor}. Installing Bundler #{next_minor} and restarting using that version.")
+
+ # It does not uninstall the locked bundler
+ bundle "clean"
+ expect(out).to be_empty
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to end_with(next_minor[0] == "2" ? "Bundler version #{next_minor}" : next_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{next_minor}")
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{next_minor}. Installing Bundler #{next_minor} and restarting using that version.")
+ end
+
+ it "does not try to install a development version" do
+ lockfile_bundled_with("#{next_minor}.dev")
+
+ bundle "install --verbose"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION)
+ end
+
+ it "shows a discreet message if locked bundler does not exist, and something more complete in `--verbose` mode" do
+ missing_minor ="#{Bundler::VERSION[0]}.999.999"
+
+ lockfile_bundled_with(missing_minor)
+
+ bundle "install"
+ expect(err).to eq("There was an error installing the locked bundler version (#{missing_minor}), rerun with the `--verbose` flag for more details. Going on using bundler #{Bundler::VERSION}.")
+
+ bundle "install --verbose"
+ expect(err).to include("There was an error installing the locked bundler version (#{missing_minor}), rerun with the `--verbose` flag for more details. Going on using bundler #{Bundler::VERSION}.")
+ expect(err).to include("Gem::UnsatisfiableDependencyError")
+
+ bundle "-v"
+ expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION)
+ end
+
+ private
+
+ def lockfile_bundled_with(version)
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{version}
+ L
+ end
+ end
+end
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index 3b91897a2e..96f2e2a274 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -28,6 +28,7 @@ RSpec.configure do |config|
config.filter_run_excluding :git => RequirementChecker.against(git_version)
config.filter_run_excluding :bundler => RequirementChecker.against(Bundler::VERSION.split(".")[0])
+ config.filter_run_excluding :rubygems => RequirementChecker.against(Gem::VERSION)
config.filter_run_excluding :ruby_repo => !ENV["GEM_COMMAND"].nil?
config.filter_run_excluding :no_color_tty => Gem.win_platform? || !ENV["GITHUB_ACTION"].nil?
config.filter_run_excluding :permissions => Gem.win_platform?
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index 0ad5239128..4a49ffb49f 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -32,7 +32,7 @@ module Gem
end
if ENV["BUNDLER_SPEC_GEM_SOURCES"]
- @sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
+ self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
end
# We only need this hack for rubygems versions without the BundlerVersionFinder
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index f84e68cee8..5238c8b980 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -166,7 +166,7 @@ module Spec
def gem_command(command, options = {})
env = options[:env] || {}
- env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
options[:env] = env
sys_exec("#{Path.gem_bin} #{command}", options)
end
@@ -181,7 +181,7 @@ module Spec
def sys_exec(cmd, options = {})
env = options[:env] || {}
- env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
dir = options[:dir] || bundled_app
command_execution = CommandExecution.new(cmd.to_s, dir)
@@ -348,6 +348,7 @@ module Spec
without_env_side_effects do
ENV["GEM_HOME"] = path.to_s
ENV["GEM_PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_GEM_HOME"] = nil
ENV["BUNDLER_ORIG_GEM_PATH"] = nil
yield
end
diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock
index ca0fb5c613..4c33191c9e 100644
--- a/tool/bundler/rubocop_gems.rb.lock
+++ b/tool/bundler/rubocop_gems.rb.lock
@@ -60,4 +60,4 @@ DEPENDENCIES
test-unit
BUNDLED WITH
- 2.3.0.dev
+ 2.3.0
diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock
index af22080659..b29129ed57 100644
--- a/tool/bundler/standard_gems.rb.lock
+++ b/tool/bundler/standard_gems.rb.lock
@@ -66,4 +66,4 @@ DEPENDENCIES
test-unit
BUNDLED WITH
- 2.3.0.dev
+ 2.3.0
diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock
index 2f1dab91e2..d53195b0c9 100644
--- a/tool/bundler/test_gems.rb.lock
+++ b/tool/bundler/test_gems.rb.lock
@@ -41,4 +41,4 @@ DEPENDENCIES
webrick (= 1.7.0)
BUNDLED WITH
- 2.3.0.dev
+ 2.3.0