ruby/lib/bundler/environment_preserver.rb
David Rodríguez 90085f62fb [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
2025-06-26 08:06:48 +09:00

68 lines
1.4 KiB
Ruby

# frozen_string_literal: true
module Bundler
class EnvironmentPreserver
INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL"
BUNDLER_KEYS = %w[
BUNDLE_BIN_PATH
BUNDLE_GEMFILE
BUNDLER_VERSION
BUNDLER_SETUP
GEM_HOME
GEM_PATH
MANPATH
PATH
RB_USER_INSTALL
RUBYLIB
RUBYOPT
].map(&:freeze).freeze
BUNDLER_PREFIX = "BUNDLER_ORIG_"
def self.from_env
new(ENV.to_hash, BUNDLER_KEYS)
end
# @param env [Hash]
# @param keys [Array<String>]
def initialize(env, keys)
@original = env
@keys = keys
@prefix = BUNDLER_PREFIX
end
# Replaces `ENV` with the bundler environment variables backed up
def replace_with_backup
ENV.replace(backup)
end
# @return [Hash]
def backup
env = @original.clone
@keys.each do |key|
value = env[key]
if !value.nil?
env[@prefix + key] ||= value
else
env[@prefix + key] ||= INTENTIONALLY_NIL
end
end
env
end
# @return [Hash]
def restore
env = @original.clone
@keys.each do |key|
value_original = env[@prefix + key]
next if value_original.nil?
if value_original == INTENTIONALLY_NIL
env.delete(key)
else
env[key] = value_original
end
env.delete(@prefix + key)
end
env
end
end
end