mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[rubygems/rubygems] Simulate Bundler 4 in a better way
Overriding the version constant feels too magic and creates a set of
problems. For example, Bundler will lock the simulated version, and that
can cause issues when the lockfile is used under an environment not
simulating Bundler 4 (it will try to auto-install and auto-switch to a
version that does not exist).
On top of that, it can only be configured with an ENV variable which is
not too flexible.
This commit takes a different approach of using a setting, which is
configurable through ENV or `bundle config`, and pass the simulated
version to `Bundler::FeatureFlag`. The real version is still the one set
by `VERSION`, but anything that `Bundler::FeatureFlag` controls will use
the logic of the "simulated version".
In particular, all feature flags and deprecation messages will respect
the simulated version, and this is exactly the set of functionality that
we want users to be able to easily try before releasing it.
8129402193
This commit is contained in:
parent
938ab128a4
commit
90085f62fb
12 changed files with 36 additions and 29 deletions
|
@ -567,7 +567,7 @@ module Bundler
|
||||||
end
|
end
|
||||||
|
|
||||||
def feature_flag
|
def feature_flag
|
||||||
@feature_flag ||= FeatureFlag.new(VERSION)
|
@feature_flag ||= FeatureFlag.new(settings[:simulate_version] || VERSION)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset!
|
def reset!
|
||||||
|
|
|
@ -6,7 +6,6 @@ module Bundler
|
||||||
BUNDLER_KEYS = %w[
|
BUNDLER_KEYS = %w[
|
||||||
BUNDLE_BIN_PATH
|
BUNDLE_BIN_PATH
|
||||||
BUNDLE_GEMFILE
|
BUNDLE_GEMFILE
|
||||||
BUNDLER_4_MODE
|
|
||||||
BUNDLER_VERSION
|
BUNDLER_VERSION
|
||||||
BUNDLER_SETUP
|
BUNDLER_SETUP
|
||||||
GEM_HOME
|
GEM_HOME
|
||||||
|
|
|
@ -50,6 +50,8 @@ module Bundler
|
||||||
@major_version >= target_major_version
|
@major_version >= target_major_version
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr_reader :bundler_version
|
||||||
|
|
||||||
def initialize(bundler_version)
|
def initialize(bundler_version)
|
||||||
@bundler_version = Gem::Version.create(bundler_version)
|
@bundler_version = Gem::Version.create(bundler_version)
|
||||||
@major_version = @bundler_version.segments.first
|
@major_version = @bundler_version.segments.first
|
||||||
|
|
|
@ -98,7 +98,6 @@ module Bundler
|
||||||
|
|
||||||
def autoswitching_applies?
|
def autoswitching_applies?
|
||||||
ENV["BUNDLER_VERSION"].nil? &&
|
ENV["BUNDLER_VERSION"].nil? &&
|
||||||
ENV["BUNDLER_4_MODE"].nil? &&
|
|
||||||
ruby_can_restart_with_same_arguments? &&
|
ruby_can_restart_with_same_arguments? &&
|
||||||
lockfile_version
|
lockfile_version
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: false
|
# frozen_string_literal: false
|
||||||
|
|
||||||
module Bundler
|
module Bundler
|
||||||
VERSION = (ENV["BUNDLER_4_MODE"] == "true" ? "4.0.0" : "2.7.0.dev").freeze
|
VERSION = "2.7.0.dev".freeze
|
||||||
|
|
||||||
def self.bundler_major_version
|
def self.bundler_major_version
|
||||||
@bundler_major_version ||= gem_version.segments.first
|
@bundler_major_version ||= gem_version.segments.first
|
||||||
|
|
|
@ -333,7 +333,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
|
||||||
C
|
C
|
||||||
|
|
||||||
expect(Bundler.ui).not_to receive(:warn)
|
expect(Bundler.ui).not_to receive(:warn)
|
||||||
expect(settings.all).to be_empty
|
expect(settings.all).to eq(simulated_version ? ["simulate_version"] : [])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "converts older keys with dashes" do
|
it "converts older keys with dashes" do
|
||||||
|
|
|
@ -453,7 +453,7 @@ E
|
||||||
it "does not make bundler crash and ignores the configuration" do
|
it "does not make bundler crash and ignores the configuration" do
|
||||||
bundle "config list --parseable"
|
bundle "config list --parseable"
|
||||||
|
|
||||||
expect(out).to be_empty
|
expect(out).to eq(simulated_version ? "simulate_version=#{simulated_version}" : "")
|
||||||
expect(err).to be_empty
|
expect(err).to be_empty
|
||||||
|
|
||||||
ruby(<<~RUBY)
|
ruby(<<~RUBY)
|
||||||
|
@ -476,26 +476,38 @@ E
|
||||||
describe "subcommands" do
|
describe "subcommands" do
|
||||||
it "list" do
|
it "list" do
|
||||||
bundle "config list", env: { "BUNDLE_FOO" => "bar" }
|
bundle "config list", env: { "BUNDLE_FOO" => "bar" }
|
||||||
expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nfoo\nSet via BUNDLE_FOO: \"bar\""
|
expected = "Settings are listed in order of priority. The top value will be used.\nfoo\nSet via BUNDLE_FOO: \"bar\""
|
||||||
|
expected += "\n\nsimulate_version\nSet via BUNDLE_SIMULATE_VERSION: \"#{simulated_version}\"" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
|
|
||||||
bundle "config list", env: { "BUNDLE_FOO" => "bar" }, parseable: true
|
bundle "config list", env: { "BUNDLE_FOO" => "bar" }, parseable: true
|
||||||
expect(out).to eq "foo=bar"
|
expected = "foo=bar"
|
||||||
|
expected += "\nsimulate_version=#{simulated_version}" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list with credentials" do
|
it "list with credentials" do
|
||||||
bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
|
bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
|
||||||
expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\""
|
expected = "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\""
|
||||||
|
expected += "\n\nsimulate_version\nSet via BUNDLE_SIMULATE_VERSION: \"#{simulated_version}\"" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
|
|
||||||
bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
|
bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
|
||||||
expect(out).to eq "gems.myserver.com=user:password"
|
expected = "gems.myserver.com=user:password"
|
||||||
|
expected += "\nsimulate_version=#{simulated_version}" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list with API token credentials" do
|
it "list with API token credentials" do
|
||||||
bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
|
bundle "config list", env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
|
||||||
expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\""
|
expected = "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\""
|
||||||
|
expected += "\n\nsimulate_version\nSet via BUNDLE_SIMULATE_VERSION: \"#{simulated_version}\"" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
|
|
||||||
bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
|
bundle "config list", parseable: true, env: { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
|
||||||
expect(out).to eq "gems.myserver.com=api_token:x-oauth-basic"
|
expected = "gems.myserver.com=api_token:x-oauth-basic"
|
||||||
|
expected += "\nsimulate_version=#{simulated_version}" if simulated_version
|
||||||
|
expect(out).to eq(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "get" do
|
it "get" do
|
||||||
|
|
|
@ -109,7 +109,7 @@ RSpec.describe "the lockfile format" do
|
||||||
#{version}
|
#{version}
|
||||||
L
|
L
|
||||||
|
|
||||||
install_gemfile <<-G, verbose: true, env: { "BUNDLER_4_MODE" => nil }
|
install_gemfile <<-G, verbose: true
|
||||||
source "https://gem.repo4"
|
source "https://gem.repo4"
|
||||||
|
|
||||||
gem "myrack"
|
gem "myrack"
|
||||||
|
|
|
@ -131,14 +131,8 @@ RSpec.describe "bundle install with complex dependencies", realworld: true do
|
||||||
end
|
end
|
||||||
G
|
G
|
||||||
|
|
||||||
if Bundler.feature_flag.bundler_4_mode?
|
bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
|
||||||
bundle "lock", env: { "DEBUG_RESOLVER" => "1" }, raise_on_error: false
|
|
||||||
|
|
||||||
expect(out).to include("backtracking").exactly(26).times
|
expect(out).to include("Solution found after 10 attempts")
|
||||||
else
|
|
||||||
bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
|
|
||||||
|
|
||||||
expect(out).to include("Solution found after 10 attempts")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe "Self management" do
|
||||||
"9.4.0"
|
"9.4.0"
|
||||||
end
|
end
|
||||||
|
|
||||||
around do |example|
|
before do
|
||||||
build_repo4 do
|
build_repo4 do
|
||||||
build_bundler previous_minor
|
build_bundler previous_minor
|
||||||
|
|
||||||
|
@ -26,8 +26,6 @@ RSpec.describe "Self management" do
|
||||||
G
|
G
|
||||||
|
|
||||||
pristine_system_gems "bundler-#{current_version}"
|
pristine_system_gems "bundler-#{current_version}"
|
||||||
|
|
||||||
with_env_vars("BUNDLER_4_MODE" => nil, &example)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "installs locked version when using system path and uses it" do
|
it "installs locked version when using system path and uses it" do
|
||||||
|
|
|
@ -9,5 +9,9 @@ module Spec
|
||||||
def rubylib
|
def rubylib
|
||||||
ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR)
|
ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def simulated_version
|
||||||
|
ENV["BUNDLE_SIMULATE_VERSION"]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RequirementChecker < Proc
|
class RequirementChecker < Proc
|
||||||
def self.against(present, major_only: false)
|
def self.against(provided, major_only: false)
|
||||||
present = present.split(".")[0] if major_only
|
provided = Gem::Version.new(provided.segments.first) if major_only
|
||||||
provided = Gem::Version.new(present)
|
|
||||||
|
|
||||||
new do |required|
|
new do |required|
|
||||||
requirement = Gem::Requirement.new(required)
|
requirement = Gem::Requirement.new(required)
|
||||||
|
@ -28,8 +27,8 @@ end
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.filter_run_excluding realworld: true
|
config.filter_run_excluding realworld: true
|
||||||
|
|
||||||
config.filter_run_excluding bundler: RequirementChecker.against(Bundler::VERSION, major_only: true)
|
config.filter_run_excluding bundler: RequirementChecker.against(Bundler.feature_flag.bundler_version, major_only: true)
|
||||||
config.filter_run_excluding rubygems: RequirementChecker.against(Gem::VERSION)
|
config.filter_run_excluding rubygems: RequirementChecker.against(Gem.rubygems_version)
|
||||||
config.filter_run_excluding ruby_repo: !ENV["GEM_COMMAND"].nil?
|
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 no_color_tty: Gem.win_platform? || !ENV["GITHUB_ACTION"].nil?
|
||||||
config.filter_run_excluding permissions: Gem.win_platform?
|
config.filter_run_excluding permissions: Gem.win_platform?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue