summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler.rb2
-rw-r--r--lib/bundler/cli/doctor.rb12
-rw-r--r--lib/bundler/cli/install.rb2
-rw-r--r--lib/bundler/compact_index_client.rb4
-rw-r--r--lib/bundler/current_ruby.rb8
-rw-r--r--lib/bundler/definition.rb44
-rw-r--r--lib/bundler/dsl.rb14
-rw-r--r--lib/bundler/installer.rb8
-rw-r--r--lib/bundler/lockfile_parser.rb22
-rw-r--r--lib/bundler/plugin/installer.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb2
-rw-r--r--lib/bundler/source/rubygems.rb13
-rw-r--r--lib/bundler/source_list.rb55
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb2
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb4
-rw-r--r--lib/bundler/worker.rb4
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/core_ext/tcpsocket_init.rb4
-rw-r--r--lib/rubygems/deprecate.rb59
-rw-r--r--lib/rubygems/gemcutter_utilities.rb13
-rw-r--r--lib/rubygems/installer.rb2
-rw-r--r--lib/rubygems/remote_fetcher.rb15
-rw-r--r--lib/rubygems/request/connection_pools.rb2
-rw-r--r--lib/rubygems/request/http_pool.rb2
-rw-r--r--lib/rubygems/request_set.rb2
-rw-r--r--lib/rubygems/specification.rb2
-rw-r--r--lib/rubygems/uri_parser.rb8
-rw-r--r--lib/rubygems/uri_parsing.rb23
-rw-r--r--lib/rubygems/user_interaction.rb2
-rw-r--r--spec/bundler/bundler/cli_spec.rb34
-rw-r--r--spec/bundler/bundler/definition_spec.rb2
-rw-r--r--spec/bundler/bundler/source_list_spec.rb42
-rw-r--r--spec/bundler/commands/doctor_spec.rb24
-rw-r--r--spec/bundler/commands/update_spec.rb88
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb32
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb70
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb4
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb4
-rw-r--r--spec/bundler/install/global_cache_spec.rb7
-rw-r--r--spec/bundler/lock/lockfile_spec.rb82
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb133
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb10
-rw-r--r--spec/bundler/spec_helper.rb2
-rw-r--r--spec/bundler/support/api_request_limit_hax.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index_rate_limited.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint.rb2
-rw-r--r--spec/bundler/support/hax.rb25
-rw-r--r--spec/bundler/support/helpers.rb4
-rw-r--r--spec/bundler/support/matchers.rb8
-rw-r--r--spec/bundler/support/path.rb4
-rw-r--r--test/rubygems/helper.rb2
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb12
52 files changed, 477 insertions, 466 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 8b9e870f7b..a7d5d1e64a 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -37,7 +37,7 @@ module Bundler
environment_preserver = EnvironmentPreserver.from_env
ORIGINAL_ENV = environment_preserver.restore
environment_preserver.replace_with_backup
- SUDO_MUTEX = Mutex.new
+ SUDO_MUTEX = Thread::Mutex.new
autoload :Definition, File.expand_path("bundler/definition", __dir__)
autoload :Dependency, File.expand_path("bundler/dependency", __dir__)
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index 2986ddbc99..959b1b5e04 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -100,8 +100,11 @@ module Bundler
files_not_readable_or_writable = []
files_not_rw_and_owned_by_different_user = []
files_not_owned_by_current_user_but_still_rw = []
+ broken_symlinks = []
Find.find(Bundler.bundle_path.to_s).each do |f|
- if !File.writable?(f) || !File.readable?(f)
+ if !File.exist?(f)
+ broken_symlinks << f
+ elsif !File.writable?(f) || !File.readable?(f)
if File.stat(f).uid != Process.uid
files_not_rw_and_owned_by_different_user << f
else
@@ -113,6 +116,13 @@ module Bundler
end
ok = true
+
+ if broken_symlinks.any?
+ Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
+
+ ok = false
+ end
+
if files_not_owned_by_current_user_but_still_rw.any?
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
"user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}"
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index 47c1da10e7..5e39e2a36d 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -104,7 +104,7 @@ module Bundler
private
def warn_if_root
- return if Bundler.settings[:silence_root_warning] || Bundler::WINDOWS || !Process.uid.zero?
+ return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \
"if it is needed, and installing your bundle as root will break this " \
"application for all non-root users on this machine.", :wrap => true
diff --git a/lib/bundler/compact_index_client.rb b/lib/bundler/compact_index_client.rb
index cf67f0e7a0..d5dbeb3b10 100644
--- a/lib/bundler/compact_index_client.rb
+++ b/lib/bundler/compact_index_client.rb
@@ -5,7 +5,7 @@ require "set"
module Bundler
class CompactIndexClient
- DEBUG_MUTEX = Mutex.new
+ DEBUG_MUTEX = Thread::Mutex.new
def self.debug
return unless ENV["DEBUG_COMPACT_INDEX"]
DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
@@ -25,7 +25,7 @@ module Bundler
@endpoints = Set.new
@info_checksums_by_name = {}
@parsed_checksums = false
- @mutex = Mutex.new
+ @mutex = Thread::Mutex.new
end
def execution_mode=(block)
diff --git a/lib/bundler/current_ruby.rb b/lib/bundler/current_ruby.rb
index b8c7cada1c..f84d68e262 100644
--- a/lib/bundler/current_ruby.rb
+++ b/lib/bundler/current_ruby.rb
@@ -65,19 +65,19 @@ module Bundler
end
def mswin?
- Bundler::WINDOWS
+ Gem.win_platform?
end
def mswin64?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
end
def mingw?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
end
def x64_mingw?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
end
(KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version|
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 0d7630e20d..8998e3b3ae 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -61,10 +61,8 @@ module Bundler
@unlocking_bundler = false
@unlocking = unlock
else
- unlock = unlock.dup
@unlocking_bundler = unlock.delete(:bundler)
- unlock.delete_if {|_k, v| Array(v).empty? }
- @unlocking = !unlock.empty?
+ @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
end
@dependencies = dependencies
@@ -111,8 +109,8 @@ module Bundler
@locked_platforms = []
end
- @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
- @multisource_allowed = @locked_gem_sources.any?(&:multiple_remotes?) && Bundler.frozen_bundle?
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
+ @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
if @multisource_allowed
unless sources.aggregate_global_source?
@@ -121,7 +119,7 @@ module Bundler
Bundler::SharedHelpers.major_deprecation 2, msg
end
- @sources.merged_gem_lockfile_sections!
+ @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
end
@unlock[:sources] ||= []
@@ -506,9 +504,6 @@ module Bundler
attr_reader :sources
private :sources
- attr_reader :locked_gem_sources
- private :locked_gem_sources
-
def nothing_changed?
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
end
@@ -636,35 +631,11 @@ module Bundler
end
end
- def converge_rubygems_sources
- return false unless multisource_allowed?
-
- return false if locked_gem_sources.empty?
-
- # Get the RubyGems remotes from the Gemfile
- actual_remotes = sources.rubygems_remotes
- return false if actual_remotes.empty?
-
- changes = false
-
- # If there is a RubyGems source in both
- locked_gem_sources.each do |locked_gem_source|
- # Merge the remotes from the Gemfile into the Gemfile.lock
- changes |= locked_gem_source.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
- end
-
- changes
- end
-
def converge_sources
- changes = false
-
- changes |= converge_rubygems_sources
-
# Replace the sources from the Gemfile with the sources from the Gemfile.lock,
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
# source in the Gemfile.lock, use the one from the Gemfile.
- changes |= sources.replace_sources!(@locked_sources)
+ changes = sources.replace_sources!(@locked_sources)
sources.all_sources.each do |source|
# If the source is unlockable and the current command allows an unlock of
@@ -913,14 +884,13 @@ module Bundler
end
def additional_base_requirements_for_resolve
- return [] unless @locked_gems
+ return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
@locked_gems.specs.reduce({}) do |requirements, locked_spec|
name = locked_spec.name
dependency = dependencies_by_name[name]
- next requirements unless dependency
next requirements if @locked_gems.dependencies[name] != dependency
- next requirements if dependency.source.is_a?(Source::Path)
+ next requirements if dependency && dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
requirements
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 313d1a9a41..dc72bf0d93 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -24,9 +24,6 @@ module Bundler
def initialize
@source = nil
@sources = SourceList.new
-
- @global_rubygems_sources = []
-
@git_sources = {}
@dependencies = []
@groups = []
@@ -48,7 +45,6 @@ module Bundler
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
- check_primary_source_safety
rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -168,7 +164,7 @@ module Bundler
elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
- @global_rubygems_sources << source
+ @sources.add_global_rubygems_remote(source)
end
end
@@ -222,6 +218,7 @@ module Bundler
end
def to_definition(lockfile, unlock)
+ check_primary_source_safety
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
end
@@ -453,12 +450,7 @@ repo_name ||= user_name
end
def check_rubygems_source_safety
- @sources.global_rubygems_source = @global_rubygems_sources.shift
- return if @global_rubygems_sources.empty?
-
- @global_rubygems_sources.each do |source|
- @sources.add_rubygems_remote(source)
- end
+ return unless @sources.aggregate_global_source?
if Bundler.feature_flag.bundler_3_mode?
msg = "This Gemfile contains multiple primary sources. " \
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index a88fb91cb5..2624ac4b18 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -135,7 +135,7 @@ module Bundler
next
end
- mode = Bundler::WINDOWS ? "wb:UTF-8" : "w"
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb"
content = if RUBY_VERSION >= "2.6"
ERB.new(template, :trim_mode => "-").result(binding)
@@ -144,7 +144,7 @@ module Bundler
end
File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
- if Bundler::WINDOWS || options[:all_platforms]
+ if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
File.write("#{binstub_path}.cmd", prefix + content, :mode => mode)
end
@@ -182,7 +182,7 @@ module Bundler
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
executable_path = executable_path
- mode = Bundler::WINDOWS ? "wb:UTF-8" : "w"
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb"
content = if RUBY_VERSION >= "2.6"
ERB.new(template, :trim_mode => "-").result(binding)
@@ -191,7 +191,7 @@ module Bundler
end
File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
- if Bundler::WINDOWS || options[:all_platforms]
+ if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode)
end
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index f87faff70c..afc21fd006 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -1,16 +1,5 @@
# frozen_string_literal: true
-#--
-# Some versions of the Bundler 1.1 RC series introduced corrupted
-# lockfiles. There were two major problems:
-#
-# * multiple copies of the same GIT section appeared in the lockfile
-# * when this happened, those sections got multiple copies of gems
-# in those sections.
-#
-# As a result, Bundler 1.1 contains code that fixes the earlier
-# corruption. We will remove this fix-up code in Bundler 1.2.
-
module Bundler
class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
@@ -124,12 +113,7 @@ module Bundler
@sources << @current_source
when GIT
@current_source = TYPES[@type].from_lock(@opts)
- # Strip out duplicate GIT sections
- if @sources.include?(@current_source)
- @current_source = @sources.find {|s| s == @current_source }
- else
- @sources << @current_source
- end
+ @sources << @current_source
when GEM
@opts["remotes"] = Array(@opts.delete("remote")).reverse
@current_source = TYPES[@type].from_lock(@opts)
@@ -212,9 +196,7 @@ module Bundler
@current_spec = LazySpecification.new(name, version, platform)
@current_spec.source = @current_source
- # Avoid introducing multiple copies of the same spec (caused by
- # duplicate GIT sections)
- @specs[@current_spec.identifier] ||= @current_spec
+ @specs[@current_spec.identifier] = @current_spec
elsif spaces.size == 6
version = version.split(",").map(&:strip) if version
dep = Gem::Dependency.new(name, version)
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 980b0e29b8..4cb7ddf5d6 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -77,7 +77,7 @@ module Bundler
source_list = SourceList.new
source_list.add_git_source(git_source_options) if git_source_options
- source_list.global_rubygems_source = rubygems_source if rubygems_source
+ source_list.add_global_rubygems_remote(rubygems_source) if rubygems_source
deps = names.map {|name| Dependency.new name, version }
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index c95664965c..9828fc885c 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -134,6 +134,8 @@ module Gem
class Requirement
module OrderIndependentComparison
def ==(other)
+ return unless Gem::Requirement === other
+
if _requirements_sorted? && other._requirements_sorted?
super
else
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index b4bb3d1980..43b193cf1c 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -252,19 +252,6 @@ module Bundler
other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
end
- def replace_remotes(other_remotes, allow_equivalent = false)
- return false if other_remotes == @remotes
-
- equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
-
- @remotes = []
- other_remotes.reverse_each do |r|
- add_remote r.to_s
- end
-
- !equivalent
- end
-
def spec_names
if @allow_remote && dependency_api_available?
remote_specs.spec_names
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 9a7f0ea0a2..113d49ba72 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -28,8 +28,9 @@ module Bundler
@merged_gem_lockfile_sections
end
- def merged_gem_lockfile_sections!
+ def merged_gem_lockfile_sections!(replacement_source)
@merged_gem_lockfile_sections = true
+ @global_rubygems_source = replacement_source
end
def aggregate_global_source?
@@ -53,18 +54,17 @@ module Bundler
end
def add_rubygems_source(options = {})
- add_source_to_list Source::Rubygems.new(options), @rubygems_sources
+ new_source = Source::Rubygems.new(options)
+ return @global_rubygems_source if @global_rubygems_source == new_source
+
+ add_source_to_list new_source, @rubygems_sources
end
def add_plugin_source(source, options = {})
add_source_to_list Plugin.source(source).new(options), @plugin_sources
end
- def global_rubygems_source=(uri)
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri, "allow_local" => true)
- end
-
- def add_rubygems_remote(uri)
+ def add_global_rubygems_remote(uri)
global_rubygems_source.add_remote(uri)
global_rubygems_source
end
@@ -109,27 +109,26 @@ module Bundler
if merged_gem_lockfile_sections?
[combine_rubygems_sources]
else
- rubygems_sources.sort_by(&:to_s).uniq
+ rubygems_sources.sort_by(&:to_s)
end
end
# Returns true if there are changes
def replace_sources!(replacement_sources)
- return true if replacement_sources.empty?
+ return false if replacement_sources.empty?
- [path_sources, git_sources, plugin_sources].each do |source_list|
- source_list.map! do |source|
- replacement_sources.find {|s| s == source } || source
- end
- end
+ @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+
+ different_sources?(lock_sources, replacement_sources)
+ end
- replacement_rubygems = merged_gem_lockfile_sections? &&
- replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
- @global_rubygems_source = replacement_rubygems if replacement_rubygems
+ # Returns true if there are changes
+ def expired_sources?(replacement_sources)
+ return false if replacement_sources.empty?
- return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
+ lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
- false
+ different_sources?(lock_sources, replacement_sources)
end
def local_only!
@@ -146,6 +145,24 @@ module Bundler
private
+ def dup_with_replaced_sources(replacement_sources)
+ new_source_list = dup
+ new_source_list.replace_sources!(replacement_sources)
+ new_source_list
+ end
+
+ def map_sources(replacement_sources)
+ [path_sources, git_sources, plugin_sources].map do |sources|
+ sources.map do |source|
+ replacement_sources.find {|s| s == source } || source
+ end
+ end
+ end
+
+ def different_sources?(lock_sources, replacement_sources)
+ !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
+ end
+
def rubygems_aggregate_class
Source::Rubygems
end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
index 5a9c4a27bb..8210ab4c41 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
@@ -27,7 +27,7 @@ class Bundler::ConnectionPool
# @!visibility private
def initialize
- @mutex = Mutex.new
+ @mutex = Thread::Mutex.new
@last_time = Time.now.to_f
end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
index f3fe1e04ad..cff8477c1f 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
@@ -39,8 +39,8 @@ class Bundler::ConnectionPool::TimedStack
@created = 0
@que = []
@max = size
- @mutex = Mutex.new
- @resource = ConditionVariable.new
+ @mutex = Thread::Mutex.new
+ @resource = Thread::ConditionVariable.new
@shutdown_block = nil
end
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb
index 10139ed25b..0380096523 100644
--- a/lib/bundler/worker.rb
+++ b/lib/bundler/worker.rb
@@ -21,8 +21,8 @@ module Bundler
# @param func [Proc] job to run in inside the worker pool
def initialize(size, name, func)
@name = name
- @request_queue = Queue.new
- @response_queue = Queue.new
+ @request_queue = Thread::Queue.new
+ @response_queue = Thread::Queue.new
@func = func
@size = size
@threads = nil
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 3585defd2d..1c5a25fd7f 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -178,7 +178,7 @@ module Gem
@configuration = nil
@gemdeps = nil
@loaded_specs = {}
- LOADED_SPECS_MUTEX = Mutex.new
+ LOADED_SPECS_MUTEX = Thread::Mutex.new
@path_to_default_spec_map = {}
@platforms = []
@ruby = nil
diff --git a/lib/rubygems/core_ext/tcpsocket_init.rb b/lib/rubygems/core_ext/tcpsocket_init.rb
index 3d9740c579..2a79b63bd6 100644
--- a/lib/rubygems/core_ext/tcpsocket_init.rb
+++ b/lib/rubygems/core_ext/tcpsocket_init.rb
@@ -11,10 +11,10 @@ module CoreExtensions
IPV4_DELAY_SECONDS = 0.1
def initialize(host, serv, *rest)
- mutex = Mutex.new
+ mutex = Thread::Mutex.new
addrs = []
threads = []
- cond_var = ConditionVariable.new
+ cond_var = Thread::ConditionVariable.new
Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb
index 8c822cda95..5fe0afb6b0 100644
--- a/lib/rubygems/deprecate.rb
+++ b/lib/rubygems/deprecate.rb
@@ -1,23 +1,70 @@
# frozen_string_literal: true
##
-# Provides a single method +deprecate+ to be used to declare when
-# something is going away.
+# Provides 3 methods for declaring when something is going away.
+#
+# +deprecate(name, repl, year, month)+:
+# Indicate something may be removed on/after a certain date.
+#
+# +rubygems_deprecate(name, replacement=:none)+:
+# Indicate something will be removed in the next major RubyGems version,
+# and (optionally) a replacement for it.
+#
+# +rubygems_deprecate_command+:
+# Indicate a RubyGems command (in +lib/rubygems/commands/*.rb+) will be
+# removed in the next RubyGems version.
+#
+# Also provides +skip_during+ for temporarily turning off deprecation warnings.
+# This is intended to be used in the test suite, so deprecation warnings
+# don't cause test failures if you need to make sure stderr is otherwise empty.
+#
+#
+# Example usage of +deprecate+ and +rubygems_deprecate+:
#
# class Legacy
-# def self.klass_method
+# def self.some_class_method
# # ...
# end
#
-# def instance_method
+# def some_instance_method
+# # ...
+# end
+#
+# def some_old_method
# # ...
# end
#
# extend Gem::Deprecate
-# deprecate :instance_method, "X.z", 2011, 4
+# deprecate :some_instance_method, "X.z", 2011, 4
+# rubygems_deprecate :some_old_method, "Modern#some_new_method"
#
# class << self
# extend Gem::Deprecate
-# deprecate :klass_method, :none, 2011, 4
+# deprecate :some_class_method, :none, 2011, 4
+# end
+# end
+#
+#
+# Example usage of +rubygems_deprecate_command+:
+#
+# class Gem::Commands::QueryCommand < Gem::Command
+# extend Gem::Deprecate
+# rubygems_deprecate_command
+#
+# # ...
+# end
+#
+#
+# Example usage of +skip_during+:
+#
+# class TestSomething < Gem::Testcase
+# def test_some_thing_with_deprecations
+# Gem::Deprecate.skip_during do
+# actual_stdout, actual_stderr = capture_output do
+# Gem.something_deprecated
+# end
+# assert_empty actual_stdout
+# assert_equal(expected, actual_stderr)
+# end
# end
# end
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 3687e776e2..00e68916c4 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -52,6 +52,13 @@ module Gem::GemcutterUtilities
end
##
+ # The OTP code from the command options or from the user's configuration.
+
+ def otp
+ options[:otp] || ENV["GEM_HOST_OTP_CODE"]
+ end
+
+ ##
# The host to connect to either from the RUBYGEMS_HOST environment variable
# or from the user's configuration
@@ -126,7 +133,7 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:put, "api/v1/api_key",
sign_in_host, scope: scope) do |request|
request.basic_auth email, password
- request["OTP"] = options[:otp] if options[:otp]
+ request["OTP"] = otp if otp
request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params))
end
@@ -159,7 +166,7 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:post, "api/v1/api_key",
sign_in_host, scope: scope) do |request|
request.basic_auth email, password
- request["OTP"] = options[:otp] if options[:otp]
+ request["OTP"] = otp if otp
request.body = URI.encode_www_form({ name: key_name }.merge(scope_params))
end
@@ -224,7 +231,7 @@ module Gem::GemcutterUtilities
request_method = Net::HTTP.const_get method.to_s.capitalize
Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req|
- req["OTP"] = options[:otp] if options[:otp]
+ req["OTP"] = otp if otp
block.call(req)
end
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 8c286605e1..7cc9bc6a0b 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -68,7 +68,7 @@ class Gem::Installer
@path_warning = false
- @install_lock = Mutex.new
+ @install_lock = Thread::Mutex.new
class << self
##
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index e3d4bfbeba..717cb59779 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -4,7 +4,7 @@ require 'rubygems/request'
require 'rubygems/request/connection_pools'
require 'rubygems/s3_uri_signer'
require 'rubygems/uri_formatter'
-require 'rubygems/uri_parsing'
+require 'rubygems/uri_parser'
require 'rubygems/user_interaction'
require 'resolv'
@@ -14,15 +14,12 @@ require 'resolv'
class Gem::RemoteFetcher
include Gem::UserInteraction
- include Gem::UriParsing
##
# A FetchError exception wraps up the various possible IO and HTTP failures
# that could happen while downloading from the internet.
class FetchError < Gem::Exception
- include Gem::UriParsing
-
##
# The URI which was being accessed when the exception happened.
@@ -31,7 +28,7 @@ class Gem::RemoteFetcher
def initialize(message, uri)
super message
- uri = parse_uri(uri)
+ uri = Gem::UriParser.parse_uri(uri)
@original_uri = uri.dup
@@ -88,7 +85,7 @@ class Gem::RemoteFetcher
@proxy = proxy
@pools = {}
- @pool_lock = Mutex.new
+ @pool_lock = Thread::Mutex.new
@cert_files = Gem::Request.get_cert_files
@headers = headers
@@ -133,7 +130,7 @@ class Gem::RemoteFetcher
require "fileutils"
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
- source_uri = parse_uri(source_uri)
+ source_uri = Gem::UriParser.parse_uri(source_uri)
scheme = source_uri.scheme
@@ -228,7 +225,7 @@ class Gem::RemoteFetcher
unless location = response['Location']
raise FetchError.new("redirecting but no redirect location was given", uri)
end
- location = parse_uri location
+ location = Gem::UriParser.parse_uri location
if https?(uri) && !https?(location)
raise FetchError.new("redirecting to non-https resource: #{location}", uri)
@@ -246,7 +243,7 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- uri = parse_uri uri
+ uri = Gem::UriParser.parse_uri uri
unless uri.scheme
raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb
index 7f3988952c..a4c2929b38 100644
--- a/lib/rubygems/request/connection_pools.rb
+++ b/lib/rubygems/request/connection_pools.rb
@@ -11,7 +11,7 @@ class Gem::Request::ConnectionPools # :nodoc:
@proxy_uri = proxy_uri
@cert_files = cert_files
@pools = {}
- @pool_mutex = Mutex.new
+ @pool_mutex = Thread::Mutex.new
end
def pool_for(uri)
diff --git a/lib/rubygems/request/http_pool.rb b/lib/rubygems/request/http_pool.rb
index 9985bbafa6..f028516db8 100644
--- a/lib/rubygems/request/http_pool.rb
+++ b/lib/rubygems/request/http_pool.rb
@@ -12,7 +12,7 @@ class Gem::Request::HTTPPool # :nodoc:
@http_args = http_args
@cert_files = cert_files
@proxy_uri = proxy_uri
- @queue = SizedQueue.new 1
+ @queue = Thread::SizedQueue.new 1
@queue << nil
end
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index 5190cfc904..36ec87e1f7 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -151,7 +151,7 @@ class Gem::RequestSet
@prerelease = options[:prerelease]
requests = []
- download_queue = Queue.new
+ download_queue = Thread::Queue.new
# Create a thread-safe list of gems to download
sorted_requests.each do |req|
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 23a37e966b..14226796f1 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -105,7 +105,7 @@ class Gem::Specification < Gem::BasicSpecification
# rubocop:disable Style/MutableConstant
LOAD_CACHE = {} # :nodoc:
# rubocop:enable Style/MutableConstant
- LOAD_CACHE_MUTEX = Mutex.new
+ LOAD_CACHE_MUTEX = Thread::Mutex.new
private_constant :LOAD_CACHE if defined? private_constant
diff --git a/lib/rubygems/uri_parser.rb b/lib/rubygems/uri_parser.rb
index f350edec8c..f51d77a4af 100644
--- a/lib/rubygems/uri_parser.rb
+++ b/lib/rubygems/uri_parser.rb
@@ -5,10 +5,18 @@
#
class Gem::UriParser
+ def self.parse_uri(source_uri)
+ return source_uri unless source_uri.is_a?(String)
+
+ new.parse(source_uri)
+ end
+
##
# Parses the #uri, raising if it's invalid
def parse!(uri)
+ require "uri"
+
raise URI::InvalidURIError unless uri
# Always escape URI's to deal with potential spaces and such
diff --git a/lib/rubygems/uri_parsing.rb b/lib/rubygems/uri_parsing.rb
deleted file mode 100644
index 941d7e023a..0000000000
--- a/lib/rubygems/uri_parsing.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require "rubygems/uri_parser"
-
-module Gem::UriParsing
-
- def parse_uri(source_uri)
- return source_uri unless source_uri.is_a?(String)
-
- uri_parser.parse(source_uri)
- end
-
- private :parse_uri
-
- def uri_parser
- require "uri"
-
- Gem::UriParser.new
- end
-
- private :uri_parser
-
-end
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 27a9957117..6376ea7cf8 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -543,7 +543,7 @@ class Gem::StreamUI
# A progress reporter that behaves nicely with threaded downloading.
class ThreadedDownloadReporter
- MUTEX = Mutex.new
+ MUTEX = Thread::Mutex.new
##
# The current file name being displayed
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index e49066f7dc..cc8949d27d 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -2,16 +2,6 @@
require "bundler/cli"
-using Module.new {
- # Some `man` (e.g., on macOS) always highlights the output even to
- # non-tty.
- refine Spec::Helpers do
- def out
- super.gsub(/.[\b]/, "")
- end
- end
-} if RUBY_VERSION >= "2.4"
-
RSpec.describe "bundle executable" do
it "returns non-zero exit status when passed unrecognized options" do
bundle "--invalid_argument", :raise_on_error => false
@@ -42,49 +32,57 @@ RSpec.describe "bundle executable" do
it "aliases e to exec" do
bundle "e --help"
- expect(out).to include("bundle-exec")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases ex to exec" do
bundle "ex --help"
- expect(out).to include("bundle-exec")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases exe to exec" do
bundle "exe --help"
- expect(out).to include("bundle-exec")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases c to check" do
bundle "c --help"
- expect(out).to include("bundle-check")
+ expect(out_with_macos_man_workaround).to include("bundle-check")
end
it "aliases i to install" do
bundle "i --help"
- expect(out).to include("bundle-install")
+ expect(out_with_macos_man_workaround).to include("bundle-install")
end
it "aliases ls to list" do
bundle "ls --help"
- expect(out).to include("bundle-list")
+ expect(out_with_macos_man_workaround).to include("bundle-list")
end
it "aliases package to cache" do
bundle "package --help"
- expect(out).to include("bundle-cache")
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
end
it "aliases pack to cache" do
bundle "pack --help"
- expect(out).to include("bundle-cache")
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
+ end
+
+ private
+
+ # Some `man` (e.g., on macOS) always highlights the output even to
+ # non-tty.
+ def out_with_macos_man_workaround
+ out.gsub(/.[\b]/, "")
end
end
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb
index 78c7dc79b9..bf000c468a 100644
--- a/spec/bundler/bundler/definition_spec.rb
+++ b/spec/bundler/bundler/definition_spec.rb
@@ -204,7 +204,7 @@ RSpec.describe Bundler::Definition do
context "eager unlock" do
let(:source_list) do
Bundler::SourceList.new.tap do |source_list|
- source_list.global_rubygems_source = file_uri_for(gem_repo4)
+ source_list.add_global_rubygems_remote(file_uri_for(gem_repo4))
end
end
diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb
index 0c40ba8a77..c2d1978b29 100644
--- a/spec/bundler/bundler/source_list_spec.rb
+++ b/spec/bundler/bundler/source_list_spec.rb
@@ -115,15 +115,15 @@ RSpec.describe Bundler::SourceList do
end
end
- describe "#add_rubygems_remote", :bundler => "< 3" do
- let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") }
+ describe "#add_global_rubygems_remote" do
+ let!(:returned_source) { source_list.add_global_rubygems_remote("https://rubygems.org/") }
it "returns the aggregate rubygems source" do
expect(returned_source).to be_instance_of(Bundler::Source::Rubygems)
end
it "adds the provided remote to the beginning of the aggregate source" do
- source_list.add_rubygems_remote("https://othersource.org")
+ source_list.add_global_rubygems_remote("https://othersource.org")
expect(returned_source.remotes).to eq [
Bundler::URI("https://othersource.org/"),
Bundler::URI("https://rubygems.org/"),
@@ -212,22 +212,22 @@ RSpec.describe Bundler::SourceList do
describe "#path_sources" do
it "returns an empty array when no path sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_git_source("uri" => "git://host/path.git")
expect(source_list.path_sources).to be_empty
end
it "returns path sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.path_sources).to eq [
@@ -240,7 +240,7 @@ RSpec.describe Bundler::SourceList do
describe "#git_sources" do
it "returns an empty array when no git sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.git_sources).to be_empty
@@ -248,15 +248,15 @@ RSpec.describe Bundler::SourceList do
it "returns git sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.git_sources).to eq [
@@ -269,7 +269,7 @@ RSpec.describe Bundler::SourceList do
describe "#plugin_sources" do
it "returns an empty array when no plugin sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.plugin_sources).to be_empty
@@ -279,13 +279,13 @@ RSpec.describe Bundler::SourceList do
source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git")
source_list.add_git_source("https://new-git.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git")
expect(source_list.plugin_sources).to eq [
@@ -339,7 +339,7 @@ RSpec.describe Bundler::SourceList do
describe "#get" do
context "when it includes an equal source" do
let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) }
- before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") }
+ before { @equal_source = source_list.add_global_rubygems_remote("https://rubygems.org") }
it "returns the equal source" do
expect(source_list.get(rubygems_source)).to be @equal_source
diff --git a/spec/bundler/commands/doctor_spec.rb b/spec/bundler/commands/doctor_spec.rb
index d8e9674a24..a59ccc540a 100644
--- a/spec/bundler/commands/doctor_spec.rb
+++ b/spec/bundler/commands/doctor_spec.rb
@@ -32,6 +32,8 @@ RSpec.describe "bundle doctor" do
unwritable_file = double("file")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(unwritable_file).and_return(true)
allow(File).to receive(:stat).with(unwritable_file) { stat }
allow(stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(unwritable_file) { true }
@@ -47,7 +49,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
- allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true)
expect { doctor.run }.not_to(raise_error, @stdout.string)
expect(@stdout.string).to be_empty
@@ -57,7 +58,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
- allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false)
expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string
The following gems are missing OS dependencies:
@@ -67,12 +67,32 @@ RSpec.describe "bundle doctor" do
end
end
+ context "when home contains broken symlinks" do
+ before(:each) do
+ @broken_symlink = double("file")
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@broken_symlink] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(@broken_symlink) { false }
+ end
+
+ it "exits with an error if home contains files that are not readable/writable" do
+ expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect(@stdout.string).to include(
+ "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{@unwritable_file}"
+ )
+ expect(@stdout.string).not_to include("No issues")
+ end
+ end
+
context "when home contains files that are not readable/writable" do
before(:each) do
@stat = double("stat")
@unwritable_file = double("file")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(@unwritable_file) { true }
allow(File).to receive(:stat).with(@unwritable_file) { @stat }
end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 86314952ad..f9548238e9 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -241,6 +241,94 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
end
+ it "does not go to an older version, even if the version upgrade that could cause another gem to downgrade is activated first" do
+ build_repo4 do
+ # countries is processed before country_select by the resolver due to having less spec groups (groups of versions with the same dependencies) (2 vs 3)
+
+ build_gem "countries", "2.1.4"
+ build_gem "countries", "3.1.0"
+
+ build_gem "countries", "4.0.0" do |s|
+ s.add_dependency "sixarm_ruby_unaccent", "~> 1.1"
+ end
+
+ build_gem "country_select", "1.2.0"
+
+ build_gem "country_select", "2.1.4" do |s|
+ s.add_dependency "countries", "~> 2.0"
+ end
+ build_gem "country_select", "3.1.1" do |s|
+ s.add_dependency "countries", "~> 2.0"
+ end
+
+ build_gem "country_select", "5.1.0" do |s|
+ s.add_dependency "countries", "~> 3.0"
+ end
+
+ build_gem "sixarm_ruby_unaccent", "1.1.0"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "country_select"
+ gem "countries"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ countries (3.1.0)
+ country_select (5.1.0)
+ countries (~> 3.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ countries
+ country_select
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ previous_lockfile = lockfile
+
+ bundle "lock --update"
+
+ expect(lockfile).to eq(previous_lockfile)
+ end
+
+ it "does not downgrade indirect dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "a" do |s|
+ s.add_dependency "b"
+ s.add_dependency "c"
+ end
+ build_gem "b"
+ build_gem "c"
+ build_gem "c", "2.0"
+ end
+
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo4)}"
+ gem "a"
+ G
+
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+
+ update_repo4 do
+ build_gem "b", "2.0" do |s|
+ s.add_dependency "c", "< 2"
+ end
+ end
+
+ bundle "update", :all => true, :verbose => true
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+ end
+
it "should still downgrade if forced by the Gemfile" do
build_repo4 do
build_gem "a"
diff --git a/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
index 102f61dc12..8303e6284e 100644
--- a/spec/bundler/install/gemfile/eval_gemfile_spec.rb
+++ b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
@@ -26,6 +26,38 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
end
end
+ context "eval-ed Gemfile points to an internal gemspec and uses a scoped source that duplicates the main Gemfile global source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "6.1.3.2"
+
+ build_gem "zip-zip", "0.3"
+ end
+
+ create_file bundled_app("gems/Gemfile"), <<-G
+ gemspec :path => "\#{__dir__}/gunks"
+
+ source "#{file_uri_for(gem_repo2)}" do
+ gem "zip-zip"
+ end
+ G
+ end
+
+ it "installs and finds gems correctly" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rails"
+
+ eval_gemfile File.join(__dir__, "gems/Gemfile")
+ G
+ expect(out).to include("Resolving dependencies")
+ expect(out).to include("Bundle complete")
+
+ expect(the_bundle).to include_gem "rails 6.1.3.2"
+ end
+ end
+
context "eval-ed Gemfile has relative-path gems" do
before do
build_lib("a", :path => bundled_app("gems/a"))
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 16c5b232da..0739285a5d 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -1355,4 +1355,74 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(the_bundle).not_to be_locked
end
end
+
+ context "when upgrading a lockfile suffering from dependency confusion" do
+ before do
+ build_repo4 do
+ build_gem "mime-types", "3.0.0"
+ end
+
+ build_repo2 do
+ build_gem "capybara", "2.5.0" do |s|
+ s.add_dependency "mime-types", ">= 1.16"
+ end
+
+ build_gem "mime-types", "3.3.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "capybara", "~> 2.5.0"
+
+ source "https://gem.repo4" do
+ gem "mime-types", "~> 3.0"
+ end
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ remote: https://gem.repo4/
+ specs:
+ capybara (2.5.0)
+ mime-types (>= 1.16)
+ mime-types (3.3.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ capybara (~> 2.5.0)
+ mime-types (~> 3.0)!
+ L
+ end
+
+ it "upgrades the lockfile correctly" do
+ bundle "lock --update", :artifice => "compact_index"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ capybara (2.5.0)
+ mime-types (>= 1.16)
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mime-types (3.0.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ capybara (~> 2.5.0)
+ mime-types (~> 3.0)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
end
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 8be97ed5d2..6257cf4f71 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -399,7 +399,7 @@ The checksum of /versions does not match the checksum provided by the server! So
api_request_limit = low_api_request_limit_for(gem_repo2)
- install_gemfile <<-G, :artifice => "compact_index_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, :artifice => "compact_index_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -421,7 +421,7 @@ The checksum of /versions does not match the checksum provided by the server! So
api_request_limit = low_api_request_limit_for(gem_repo4)
- install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index eae8daa682..9738a75474 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -371,7 +371,7 @@ RSpec.describe "gemcutter's dependency API" do
api_request_limit = low_api_request_limit_for(gem_repo2)
- install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra"
gem "back_deps"
@@ -392,7 +392,7 @@ RSpec.describe "gemcutter's dependency API" do
api_request_limit = low_api_request_limit_for(gem_repo2)
- install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index 68ebef2d89..9bc243e7cf 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -181,8 +181,11 @@ RSpec.describe "global gem caching" do
bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2
# activesupport is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
- expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
+ expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2
+ end
+
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 0fbe9ee80d..0ab31eabc6 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -1178,83 +1178,6 @@ RSpec.describe "the lockfile format" do
G
end
- # Some versions of the Bundler 1.1 RC series introduced corrupted
- # lockfiles. There were two major problems:
- #
- # * multiple copies of the same GIT section appeared in the lockfile
- # * when this happened, those sections got multiple copies of gems
- # in those sections.
- it "fixes corrupted lockfiles" do
- build_git "omg", :path => lib_path("omg")
- revision = revision_for(lib_path("omg"))
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "omg", :git => "#{lib_path("omg")}", :branch => 'master'
- G
-
- bundle "config set --local path vendor"
- bundle :install
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Create a Gemfile.lock that has duplicate GIT sections
- lockfile <<-L
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install"
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Confirm that duplicate specs do not appear
- lockfile_should_be(<<-L)
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
it "raises a helpful error message when the lockfile is missing deps" do
lockfile <<-L
GEM
@@ -1326,7 +1249,10 @@ RSpec.describe "the lockfile format" do
expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) }
expect(File.read(bundled_app_lock)).to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
+
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ expect(the_bundle).to include_gems "rack 1.2"
+ end
end
end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index e0844bbeba..556a11d2f3 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -211,133 +211,6 @@ RSpec.describe "real world edgecases", :realworld => true do
expect(err).to be_empty
end
- it "checks out git repos when the lockfile is corrupted" do
- gemfile <<-G
- source "https://rubygems.org"
- git_source(:github) {|repo| "https://github.com/\#{repo}.git" }
-
- gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- G
-
- lockfile <<-L
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GEM
- remote: https://rubygems.org/
- specs:
- arel (3.0.2)
- builder (3.0.0)
- erubis (2.7.0)
- hike (1.2.1)
- i18n (0.6.0)
- journey (1.0.3)
- multi_json (1.1.0)
- rack (1.4.1)
- rack-cache (1.2)
- rack (>= 0.4)
- rack-test (0.6.1)
- rack (>= 1.0)
- sprockets (2.1.2)
- hike (~> 1.2)
- rack (~> 1.0)
- tilt (~> 1.1, != 1.3.0)
- tilt (1.3.3)
- tzinfo (0.3.32)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- actionpack!
- activerecord!
- activesupport!
- L
-
- bundle :lock
- expect(err).to be_empty
- end
-
it "outputs a helpful error message when gems have invalid gemspecs" do
install_gemfile <<-G, :standalone => true, :raise_on_error => false
source 'https://rubygems.org'
@@ -349,7 +222,7 @@ RSpec.describe "real world edgecases", :realworld => true do
end
it "doesn't hang on big gemfile" do
- skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3"
+ skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G
# frozen_string_literal: true
@@ -461,7 +334,7 @@ RSpec.describe "real world edgecases", :realworld => true do
end
it "doesn't hang on tricky gemfile" do
- skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3"
+ skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G
source 'https://rubygems.org'
@@ -487,7 +360,7 @@ RSpec.describe "real world edgecases", :realworld => true do
end
it "doesn't hang on nix gemfile" do
- skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1"
+ skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G
source "https://rubygems.org" do
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
index 518da2800b..aced5a1641 100644
--- a/spec/bundler/realworld/slow_perf_spec.rb
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -4,17 +4,19 @@ require "spec_helper"
RSpec.describe "bundle install with complex dependencies", :realworld => true do
it "resolves quickly" do
- start_time = Time.now
-
- install_gemfile <<-G
+ gemfile <<-G
source 'https://rubygems.org'
gem "actionmailer"
gem "mongoid", ">= 0.10.2"
G
+ start_time = Time.now
+
+ bundle "lock"
+
duration = Time.now - start_time
- expect(duration.to_f).to be < 120 # seconds
+ expect(duration.to_f).to be < 12 # seconds
end
end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index dc4121cb70..80b0ccff4d 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -13,7 +13,7 @@ require "bundler"
require "rspec/core"
require "rspec/expectations"
require "rspec/mocks"
-require "diff/lcs"
+require "rspec/support/differ"
require_relative "support/builders"
require_relative "support/build_metadata"
diff --git a/spec/bundler/support/api_request_limit_hax.rb b/spec/bundler/support/api_request_limit_hax.rb
new file mode 100644
index 0000000000..37ff0203b3
--- /dev/null
+++ b/spec/bundler/support/api_request_limit_hax.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"]
+ require_relative "path"
+ require "bundler/source"
+ require "bundler/source/rubygems"
+
+ module Bundler
+ class Source
+ class Rubygems < Source
+ remove_const :API_REQUEST_LIMIT
+ API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i
+ end
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/compact_index_rate_limited.rb b/spec/bundler/support/artifice/compact_index_rate_limited.rb
index ba17476045..570105e2a0 100644
--- a/spec/bundler/support/artifice/compact_index_rate_limited.rb
+++ b/spec/bundler/support/artifice/compact_index_rate_limited.rb
@@ -7,7 +7,7 @@ Artifice.deactivate
class CompactIndexRateLimited < CompactIndexAPI
class RequestCounter
def self.queue
- @queue ||= Queue.new
+ @queue ||= Thread::Queue.new
end
def self.size
diff --git a/spec/bundler/support/artifice/endpoint.rb b/spec/bundler/support/artifice/endpoint.rb
index 37ca378ef9..4a820e5a3f 100644
--- a/spec/bundler/support/artifice/endpoint.rb
+++ b/spec/bundler/support/artifice/endpoint.rb
@@ -8,7 +8,7 @@ require "artifice"
require "sinatra/base"
ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
-ALL_REQUESTS_MUTEX = Mutex.new
+ALL_REQUESTS_MUTEX = Thread::Mutex.new
at_exit do
if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index 8fd35890ae..ddb62f7d53 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -35,28 +35,3 @@ module Gem
end
end
end
-
-if ENV["BUNDLER_SPEC_WINDOWS"] == "true"
- require_relative "path"
- require "bundler/constants"
-
- module Bundler
- remove_const :WINDOWS if defined?(WINDOWS)
- WINDOWS = true
- end
-end
-
-if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"]
- require_relative "path"
- require "bundler/source"
- require "bundler/source/rubygems"
-
- module Bundler
- class Source
- class Rubygems < Source
- remove_const :API_REQUEST_LIMIT
- API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i
- end
- end
- end
-end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index 2df41028fc..13fa36fbc2 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -457,15 +457,11 @@ module Spec
end
def simulate_windows(platform = mswin)
- old = ENV["BUNDLER_SPEC_WINDOWS"]
- ENV["BUNDLER_SPEC_WINDOWS"] = "true"
simulate_platform platform do
simulate_bundler_version_when_missing_prerelease_default_gem_activation do
yield
end
end
- ensure
- ENV["BUNDLER_SPEC_WINDOWS"] = old
end
def simulate_bundler_version_when_missing_prerelease_default_gem_activation
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 3c1014edc7..180ad54c5b 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -118,14 +118,14 @@ module Spec
opts[:raise_on_error] = false
@errors = names.map do |full_name|
name, version, platform = full_name.split(/\s+/)
- require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/")
+ require_path = name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
ruby <<~R, opts
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup(#{groups})
- require '#{require_path}.rb'
+ require '#{require_path}'
actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
puts actual_version
@@ -170,7 +170,7 @@ module Spec
name, version = name.split(/\s+/, 2)
ruby <<-R, opts
begin
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup(#{groups})
rescue Bundler::GemNotFound, Bundler::GitError
exit 0
diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb
index 000b3f87b8..a98ef7c6cf 100644
--- a/spec/bundler/support/path.rb
+++ b/spec/bundler/support/path.rb
@@ -71,6 +71,10 @@ module Spec
@spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec")
end
+ def api_request_limit_hack_file
+ spec_dir.join("support/api_request_limit_hax.rb")
+ end
+
def man_dir
@man_dir ||= lib_dir.join("bundler/man")
end
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index fbdc34e357..36be6a25b7 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -1595,7 +1595,7 @@ class Object
metaclass.send :undef_method, name
metaclass.send :alias_method, name, new_name
metaclass.send :undef_method, new_name
- end
+ end unless method_defined?(:stub) # lib/resolv/test_dns.rb also has the same method definition
end
require_relative 'utilities'
diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb
index 23aff00cbe..0bcd1504e9 100644
--- a/test/rubygems/test_gem_gemcutter_utilities.rb
+++ b/test/rubygems/test_gem_gemcutter_utilities.rb
@@ -14,6 +14,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
Gem.configuration.disable_default_gem_server = nil
ENV['RUBYGEMS_HOST'] = nil
+ ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil
@cmd = Gem::Command.new '', 'summary'
@@ -22,6 +23,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
def teardown
ENV['RUBYGEMS_HOST'] = nil
+ ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil
credential_teardown
@@ -186,6 +188,16 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert_match %r{Access Denied.}, @sign_in_ui.output
end
+ def test_signin_with_env_otp_code
+ ENV['GEM_HOST_OTP_CODE'] = '111111'
+ api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
+
+ util_sign_in [api_key, 200, 'OK']
+
+ assert_match 'Signed in with API key:', @sign_in_ui.output
+ assert_equal '111111', @fetcher.last_request['OTP']
+ end
+
def test_sign_in_with_correct_otp_code
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."