summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler.rb9
-rw-r--r--lib/bundler/definition.rb59
-rw-r--r--lib/bundler/dsl.rb36
-rw-r--r--lib/bundler/index.rb6
-rw-r--r--lib/bundler/installer/standalone.rb2
-rw-r--r--lib/bundler/plugin/installer.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb28
-rw-r--r--lib/bundler/runtime.rb4
-rw-r--r--lib/bundler/settings.rb8
-rw-r--r--lib/bundler/spec_set.rb9
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb113
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb66
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb36
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb2
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb57
-rw-r--r--lib/bundler/vendor/uri/lib/uri.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/common.rb97
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ftp.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/generic.rb11
-rw-r--r--lib/bundler/vendor/uri/lib/uri/http.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/https.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ldap.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/mailto.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb15
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb13
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ws.rb84
-rw-r--r--lib/bundler/vendor/uri/lib/uri/wss.rb22
-rw-r--r--lib/rubygems/exceptions.rb2
-rw-r--r--lib/rubygems/gemcutter_utilities.rb3
-rw-r--r--lib/rubygems/package/io_source.rb4
-rw-r--r--spec/bundler/bundler/bundler_spec.rb21
-rw-r--r--spec/bundler/bundler/settings_spec.rb9
-rw-r--r--spec/bundler/commands/check_spec.rb28
-rw-r--r--spec/bundler/commands/exec_spec.rb10
-rw-r--r--spec/bundler/commands/install_spec.rb96
-rw-r--r--spec/bundler/commands/newgem_spec.rb12
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb32
-rw-r--r--spec/bundler/plugins/install_spec.rb7
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb15
-rw-r--r--spec/bundler/runtime/setup_spec.rb19
-rw-r--r--spec/bundler/support/artifice/vcr.rb13
-rw-r--r--spec/bundler/support/hax.rb4
-rw-r--r--test/rubygems/test_exit.rb11
-rw-r--r--test/rubygems/test_gem_package.rb7
45 files changed, 535 insertions, 446 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index a7d5d1e64a..b88bab8f0a 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -236,8 +236,9 @@ module Bundler
end
if warning
- user_home = tmp_home_path(warning)
- Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n"
+ Bundler.ui.warn "#{warning}\n"
+ user_home = tmp_home_path
+ Bundler.ui.warn "Bundler will use `#{user_home}' as your home directory temporarily.\n"
user_home
else
Pathname.new(home)
@@ -684,15 +685,13 @@ EOF
Bundler.rubygems.clear_paths
end
- def tmp_home_path(warning)
+ def tmp_home_path
Kernel.send(:require, "tmpdir")
SharedHelpers.filesystem_access(Dir.tmpdir) do
path = Bundler.tmp
at_exit { Bundler.rm_rf(path) }
path
end
- rescue RuntimeError => e
- raise e.exception("#{warning}\nBundler also failed to create a temporary home directory':\n#{e}")
end
# @param env [Hash]
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 8998e3b3ae..b585b06df1 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -138,7 +138,7 @@ module Bundler
@unlock[:gems] ||= @dependencies.map(&:name)
else
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
- @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, false, false).map(&:name)
end
@dependency_changes = converge_dependencies
@@ -190,25 +190,15 @@ module Bundler
#
# @return [Bundler::SpecSet]
def specs
- @specs ||= begin
- begin
- specs = resolve.materialize(requested_dependencies)
- rescue GemNotFound => e # Handle yanked gem
- gem_name, gem_version = extract_gem_info(e)
- locked_gem = @locked_specs[gem_name].last
- raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
- raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
- "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
- "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
- "removed in order to install."
- end
- unless specs["bundler"].any?
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
- specs["bundler"] = bundler
- end
-
- specs
- end
+ @specs ||= add_bundler_to(resolve.materialize(requested_dependencies))
+ rescue GemNotFound => e # Handle yanked gem
+ gem_name, gem_version = extract_gem_info(e)
+ locked_gem = @locked_specs[gem_name].last
+ raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
+ "removed in order to install."
end
def new_specs
@@ -240,17 +230,11 @@ module Bundler
end
def requested_specs
- @requested_specs ||= begin
- groups = requested_groups
- groups.map!(&:to_sym)
- specs_for(groups)
- end
+ specs_for(requested_groups)
end
def requested_dependencies
- groups = requested_groups
- groups.map!(&:to_sym)
- dependencies_for(groups)
+ dependencies_for(requested_groups)
end
def current_dependencies
@@ -260,11 +244,13 @@ module Bundler
end
def specs_for(groups)
+ groups = requested_groups if groups.empty?
deps = dependencies_for(groups)
- SpecSet.new(specs.for(expand_dependencies(deps)))
+ add_bundler_to(resolve.materialize(expand_dependencies(deps)))
end
def dependencies_for(groups)
+ groups.map!(&:to_sym)
current_dependencies.reject do |d|
(d.groups & groups).empty?
end
@@ -514,6 +500,15 @@ module Bundler
private
+ def add_bundler_to(specs)
+ unless specs["bundler"].any?
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
+ specs["bundler"] = bundler
+ end
+
+ specs
+ end
+
def precompute_source_requirements_for_indirect_dependencies?
sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
@@ -742,7 +737,7 @@ module Bundler
# if we won't need the source (according to the lockfile),
# don't error if the path/git source isn't available
next if @locked_specs.
- for(requested_dependencies, [], false, true, false).
+ for(requested_dependencies, false, true, false).
none? {|locked_spec| locked_spec.source == s.source }
raise
@@ -761,8 +756,8 @@ module Bundler
end
resolve = SpecSet.new(converged)
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
- resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), [], false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
+ @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
+ resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
diff = nil
# Now, we unlock any sources that do not have anymore gems pinned to it
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index dc72bf0d93..1605210e55 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -102,28 +102,26 @@ module Bundler
# if there's already a dependency with this name we try to prefer one
if current = @dependencies.find {|d| d.name == dep.name }
deleted_dep = @dependencies.delete(current) if current.type == :development
+ return if deleted_dep
if current.requirement != dep.requirement
- unless deleted_dep
- return if dep.type == :development
+ return if dep.type == :development
- update_prompt = ""
+ update_prompt = ""
- if File.basename(@gemfile) == Injector::INJECTED_GEMS
- if dep.requirements_list.include?(">= 0") && !current.requirements_list.include?(">= 0")
- update_prompt = ". Gem already added"
- else
- update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`"
+ if File.basename(@gemfile) == Injector::INJECTED_GEMS
+ if dep.requirements_list.include?(">= 0") && !current.requirements_list.include?(">= 0")
+ update_prompt = ". Gem already added"
+ else
+ update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`"
- update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current.requirements_list.include?(">= 0")
- end
+ update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current.requirements_list.include?(">= 0")
end
-
- raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
- "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
- "#{update_prompt}"
end
+ raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
+ "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
+ "#{update_prompt}"
else
Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
"You should probably keep only one of them.\n" \
@@ -132,12 +130,10 @@ module Bundler
end
if current.source != dep.source
- unless deleted_dep
- return if dep.type == :development
- raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
- "You specified that #{dep.name} (#{dep.requirement}) should come from " \
- "#{current.source || "an unspecified source"} and #{dep.source}\n"
- end
+ return if dep.type == :development
+ raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
+ "You specified that #{dep.name} (#{dep.requirement}) should come from " \
+ "#{current.source || "an unspecified source"} and #{dep.source}\n"
end
end
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index 36520c0a43..8930fca6d0 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -195,11 +195,7 @@ module Bundler
if base # allow all platforms when searching from a lockfile
dependency.matches_spec?(spec)
else
- if Gem::Platform.respond_to? :match_spec?
- dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
- else
- dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform)
- end
+ dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
end
end
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index 2a3f5cfe35..f16135cb48 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -3,7 +3,7 @@
module Bundler
class Standalone
def initialize(groups, definition)
- @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym))
+ @specs = definition.specs_for(groups)
end
def generate
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 4cb7ddf5d6..54ce8528cf 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.add_global_rubygems_remote(rubygems_source) if rubygems_source
+ Array(rubygems_source).each {|remote| source_list.add_global_rubygems_remote(remote) } 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 9828fc885c..2613207826 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -176,20 +176,36 @@ module Gem
end
end
+ require "rubygems/platform"
+
class Platform
JAVA = Gem::Platform.new("java") unless defined?(JAVA)
MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)
MSWIN64 = Gem::Platform.new("mswin64") unless defined?(MSWIN64)
MINGW = Gem::Platform.new("x86-mingw32") unless defined?(MINGW)
X64_MINGW = Gem::Platform.new("x64-mingw32") unless defined?(X64_MINGW)
+ end
- undef_method :hash if method_defined? :hash
- def hash
- @cpu.hash ^ @os.hash ^ @version.hash
- end
+ Platform.singleton_class.module_eval do
+ unless Platform.singleton_methods.include?(:match_spec?)
+ def match_spec?(spec)
+ match_gem?(spec.platform, spec.name)
+ end
- undef_method :eql? if method_defined? :eql?
- alias_method :eql?, :==
+ def match_gem?(platform, gem_name)
+ match_platforms?(platform, Gem.platforms)
+ end
+
+ private
+
+ def match_platforms?(platform, platforms)
+ platforms.any? do |local_platform|
+ platform.nil? ||
+ local_platform == platform ||
+ (local_platform != Gem::Platform::RUBY && local_platform =~ platform)
+ end
+ end
+ end
end
require "rubygems/util"
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index e259b590bf..287fa1cfe9 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -12,12 +12,10 @@ module Bundler
def setup(*groups)
@definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?
- groups.map!(&:to_sym)
-
# Has to happen first
clean_load_path
- specs = groups.any? ? @definition.specs_for(groups) : requested_specs
+ specs = @definition.specs_for(groups)
SharedHelpers.set_bundle_environment
Bundler.rubygems.replace_entrypoints(specs)
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index 95da31a765..de42cc16af 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -428,12 +428,8 @@ module Bundler
def global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
Pathname.new(ENV["BUNDLE_CONFIG"])
- else
- begin
- Bundler.user_bundle_path("config")
- rescue PermissionError, GenericSystemCallError
- nil
- end
+ elsif Bundler.rubygems.user_home && !Bundler.rubygems.user_home.empty?
+ Pathname.new(Bundler.rubygems.user_home).join(".bundle/config")
end
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index af16984454..1a8906c47e 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -11,15 +11,14 @@ module Bundler
@specs = specs
end
- def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
+ def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true)
handled = []
deps = dependencies.dup
specs = []
- skip += ["bundler"]
loop do
break unless dep = deps.shift
- next if handled.include?(dep) || skip.include?(dep.name)
+ next if handled.any?{|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler"
handled << dep
@@ -73,7 +72,7 @@ module Bundler
end
def materialize(deps, missing_specs = nil)
- materialized = self.for(deps, [], false, true, !missing_specs)
+ materialized = self.for(deps, false, true, !missing_specs)
materialized.group_by(&:source).each do |source, specs|
next unless specs.any?{|s| s.is_a?(LazySpecification) }
@@ -195,7 +194,7 @@ module Bundler
def spec_for_dependency(dep, match_current_platform)
specs_for_platforms = lookup[dep.name]
if match_current_platform
- GemHelpers.select_best_platform_match(specs_for_platforms, Bundler.local_platform)
+ GemHelpers.select_best_platform_match(specs_for_platforms.select{|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
else
GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform)
end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
index fbcd26c765..984c1c3dcb 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
@@ -1,14 +1,18 @@
-require_relative 'connection_pool/version'
-require_relative 'connection_pool/timed_stack'
+require "timeout"
+require_relative "connection_pool/version"
+class Bundler::ConnectionPool
+ class Error < ::RuntimeError; end
+ class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
+ class TimeoutError < ::Timeout::Error; end
+end
-# Generic connection pool class for e.g. sharing a limited number of network connections
-# among many threads. Note: Connections are lazily created.
+# Generic connection pool class for sharing a limited number of objects or network connections
+# among many threads. Note: pool elements are lazily created.
#
# Example usage with block (faster):
#
# @pool = Bundler::ConnectionPool.new { Redis.new }
-#
# @pool.with do |redis|
# redis.lpop('my-list') if redis.llen('my-list') > 0
# end
@@ -34,29 +38,23 @@ require_relative 'connection_pool/timed_stack'
class Bundler::ConnectionPool
DEFAULTS = {size: 5, timeout: 5}
- class Error < RuntimeError
- end
-
def self.wrap(options, &block)
Wrapper.new(options, &block)
end
def initialize(options = {}, &block)
- raise ArgumentError, 'Connection pool requires a block' unless block
+ raise ArgumentError, "Connection pool requires a block" unless block
options = DEFAULTS.merge(options)
- @size = options.fetch(:size)
+ @size = Integer(options.fetch(:size))
@timeout = options.fetch(:timeout)
@available = TimedStack.new(@size, &block)
- @key = :"current-#{@available.object_id}"
- @key_count = :"current-#{@available.object_id}-count"
+ @key = :"pool-#{@available.object_id}"
+ @key_count = :"pool-#{@available.object_id}-count"
end
-if Thread.respond_to?(:handle_interrupt)
-
- # MRI
def with(options = {})
Thread.handle_interrupt(Exception => :never) do
conn = checkout(options)
@@ -69,28 +67,15 @@ if Thread.respond_to?(:handle_interrupt)
end
end
end
-
-else
-
- # jruby 1.7.x
- def with(options = {})
- conn = checkout(options)
- begin
- yield conn
- ensure
- checkin
- end
- end
-
-end
+ alias then with
def checkout(options = {})
if ::Thread.current[@key]
- ::Thread.current[@key_count]+= 1
+ ::Thread.current[@key_count] += 1
::Thread.current[@key]
else
- ::Thread.current[@key_count]= 1
- ::Thread.current[@key]= @available.pop(options[:timeout] || @timeout)
+ ::Thread.current[@key_count] = 1
+ ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout)
end
end
@@ -98,64 +83,44 @@ end
if ::Thread.current[@key]
if ::Thread.current[@key_count] == 1
@available.push(::Thread.current[@key])
- ::Thread.current[@key]= nil
+ ::Thread.current[@key] = nil
+ ::Thread.current[@key_count] = nil
else
- ::Thread.current[@key_count]-= 1
+ ::Thread.current[@key_count] -= 1
end
else
- raise Bundler::ConnectionPool::Error, 'no connections are checked out'
+ raise Bundler::ConnectionPool::Error, "no connections are checked out"
end
nil
end
+ ##
+ # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
+ # then removing it from the pool. Attempting to checkout a connection after
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
+
def shutdown(&block)
@available.shutdown(&block)
end
- # Size of this connection pool
- def size
- @size
+ ##
+ # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
+ # removing it the pool. Subsequent checkouts will create new connections as
+ # needed.
+
+ def reload(&block)
+ @available.shutdown(reload: true, &block)
end
+ # Size of this connection pool
+ attr_reader :size
+
# Number of pool entries available for checkout at this instant.
def available
@available.length
end
-
- private
-
- class Wrapper < ::BasicObject
- METHODS = [:with, :pool_shutdown]
-
- def initialize(options = {}, &block)
- @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
- end
-
- def with(&block)
- @pool.with(&block)
- end
-
- def pool_shutdown(&block)
- @pool.shutdown(&block)
- end
-
- def pool_size
- @pool.size
- end
-
- def pool_available
- @pool.available
- end
-
- def respond_to?(id, *args)
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
- end
-
- def method_missing(name, *args, &block)
- with do |connection|
- connection.send(name, *args, &block)
- end
- end
- end
end
+
+require_relative "connection_pool/timed_stack"
+require_relative "connection_pool/wrapper"
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
deleted file mode 100644
index 8210ab4c41..0000000000
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# Global monotonic clock from Concurrent Ruby 1.0.
-# Copyright (c) Jerry D'Antonio -- released under the MIT license.
-# Slightly modified; used with permission.
-# https://github.com/ruby-concurrency/concurrent-ruby
-
-require 'thread'
-
-class Bundler::ConnectionPool
-
- class_definition = Class.new do
-
- if defined?(Process::CLOCK_MONOTONIC)
-
- # @!visibility private
- def get_time
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
- end
-
- elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
-
- # @!visibility private
- def get_time
- java.lang.System.nanoTime() / 1_000_000_000.0
- end
-
- else
-
- # @!visibility private
- def initialize
- @mutex = Thread::Mutex.new
- @last_time = Time.now.to_f
- end
-
- # @!visibility private
- def get_time
- @mutex.synchronize do
- now = Time.now.to_f
- if @last_time < now
- @last_time = now
- else # clock has moved back in time
- @last_time += 0.000_001
- end
- end
- end
- end
- end
-
- ##
- # Clock that cannot be set and represents monotonic time since
- # some unspecified starting point.
- #
- # @!visibility private
- GLOBAL_MONOTONIC_CLOCK = class_definition.new
- private_constant :GLOBAL_MONOTONIC_CLOCK
-
- class << self
- ##
- # Returns the current time a tracked by the application monotonic clock.
- #
- # @return [Float] The current monotonic time when `since` not given else
- # the elapsed monotonic time between `since` and the current time
- def monotonic_time
- GLOBAL_MONOTONIC_CLOCK.get_time
- end
- end
-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 cff8477c1f..a7b1cf06a8 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
@@ -1,13 +1,3 @@
-require 'thread'
-require 'timeout'
-require_relative 'monotonic_time'
-
-##
-# Raised when you attempt to retrieve a connection from a pool that has been
-# shut down.
-
-class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
-
##
# The TimedStack manages a pool of homogeneous connections (or any resource
# you wish to manage). Connections are created lazily up to a given maximum
@@ -25,7 +15,7 @@ class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
#
# conn = ts.pop
# ts.pop timeout: 5
-# #=> raises Timeout::Error after 5 seconds
+# #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
class Bundler::ConnectionPool::TimedStack
attr_reader :max
@@ -59,12 +49,12 @@ class Bundler::ConnectionPool::TimedStack
@resource.broadcast
end
end
- alias_method :<<, :push
+ alias << push
##
# Retrieves a connection from the stack. If a connection is available it is
# immediately returned. If no connection is available within the given
- # timeout a Timeout::Error is raised.
+ # timeout a Bundler::ConnectionPool::TimeoutError is raised.
#
# +:timeout+ is the only checked entry in +options+ and is preferred over
# the +timeout+ argument (which will be removed in a future release). Other
@@ -74,7 +64,7 @@ class Bundler::ConnectionPool::TimedStack
options, timeout = timeout, 0.5 if Hash === timeout
timeout = options.fetch :timeout, timeout
- deadline = Bundler::ConnectionPool.monotonic_time + timeout
+ deadline = current_time + timeout
@mutex.synchronize do
loop do
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
@@ -83,18 +73,20 @@ class Bundler::ConnectionPool::TimedStack
connection = try_create(options)
return connection if connection
- to_wait = deadline - Bundler::ConnectionPool.monotonic_time
- raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
+ to_wait = deadline - current_time
+ raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0
@resource.wait(@mutex, to_wait)
end
end
end
##
- # Shuts down the TimedStack which prevents connections from being checked
- # out. The +block+ is called once for each connection on the stack.
+ # Shuts down the TimedStack by passing each connection to +block+ and then
+ # removing it from the pool. Attempting to checkout a connection after
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
+ # +:reload+ is +true+.
- def shutdown(&block)
+ def shutdown(reload: false, &block)
raise ArgumentError, "shutdown must receive a block" unless block_given?
@mutex.synchronize do
@@ -102,6 +94,7 @@ class Bundler::ConnectionPool::TimedStack
@resource.broadcast
shutdown_connections
+ @shutdown_block = nil if reload
end
end
@@ -121,6 +114,10 @@ class Bundler::ConnectionPool::TimedStack
private
+ def current_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+
##
# This is an extension point for TimedStack and is called with a mutex.
#
@@ -149,6 +146,7 @@ class Bundler::ConnectionPool::TimedStack
conn = fetch_connection(options)
@shutdown_block.call(conn)
end
+ @created = 0
end
##
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
index b149c0e242..56ebf69902 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
@@ -1,3 +1,3 @@
class Bundler::ConnectionPool
- VERSION = "2.2.2"
+ VERSION = "2.3.0"
end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
new file mode 100644
index 0000000000..880170c06b
--- /dev/null
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
@@ -0,0 +1,57 @@
+class Bundler::ConnectionPool
+ class Wrapper < ::BasicObject
+ METHODS = [:with, :pool_shutdown, :wrapped_pool]
+
+ def initialize(options = {}, &block)
+ @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
+ end
+
+ def wrapped_pool
+ @pool
+ end
+
+ def with(&block)
+ @pool.with(&block)
+ end
+
+ def pool_shutdown(&block)
+ @pool.shutdown(&block)
+ end
+
+ def pool_size
+ @pool.size
+ end
+
+ def pool_available
+ @pool.available
+ end
+
+ def respond_to?(id, *args)
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
+ end
+
+ # rubocop:disable Style/MethodMissingSuper
+ # rubocop:disable Style/MissingRespondToMissing
+ if ::RUBY_VERSION >= "3.0.0"
+ def method_missing(name, *args, **kwargs, &block)
+ with do |connection|
+ connection.send(name, *args, **kwargs, &block)
+ end
+ end
+ elsif ::RUBY_VERSION >= "2.7.0"
+ ruby2_keywords def method_missing(name, *args, &block)
+ with do |connection|
+ connection.send(name, *args, &block)
+ end
+ end
+ else
+ def method_missing(name, *args, &block)
+ with do |connection|
+ connection.send(name, *args, &block)
+ end
+ end
+ end
+ # rubocop:enable Style/MethodMissingSuper
+ # rubocop:enable Style/MissingRespondToMissing
+ end
+end
diff --git a/lib/bundler/vendor/uri/lib/uri.rb b/lib/bundler/vendor/uri/lib/uri.rb
index 00c01bd07b..0e574dd2b1 100644
--- a/lib/bundler/vendor/uri/lib/uri.rb
+++ b/lib/bundler/vendor/uri/lib/uri.rb
@@ -86,7 +86,6 @@
# License::
# Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
# You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
module Bundler::URI
diff --git a/lib/bundler/vendor/uri/lib/uri/common.rb b/lib/bundler/vendor/uri/lib/uri/common.rb
index cc1ab86c2f..6539e1810f 100644
--- a/lib/bundler/vendor/uri/lib/uri/common.rb
+++ b/lib/bundler/vendor/uri/lib/uri/common.rb
@@ -3,7 +3,6 @@
# = uri/common.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
-# Revision:: $Id$
# License::
# You can redistribute it and/or modify it under the same term as Ruby.
#
@@ -61,82 +60,6 @@ module Bundler::URI
module_function :make_components_hash
end
- # Module for escaping unsafe characters with codes.
- module Escape
- #
- # == Synopsis
- #
- # Bundler::URI.escape(str [, unsafe])
- #
- # == Args
- #
- # +str+::
- # String to replaces in.
- # +unsafe+::
- # Regexp that matches all symbols that must be replaced with codes.
- # By default uses <tt>UNSAFE</tt>.
- # When this argument is a String, it represents a character set.
- #
- # == Description
- #
- # Escapes the string, replacing all unsafe characters with codes.
- #
- # This method is obsolete and should not be used. Instead, use
- # CGI.escape, Bundler::URI.encode_www_form or Bundler::URI.encode_www_form_component
- # depending on your specific use case.
- #
- # == Usage
- #
- # require 'bundler/vendor/uri/lib/uri'
- #
- # enc_uri = Bundler::URI.escape("http://example.com/?a=\11\15")
- # # => "http://example.com/?a=%09%0D"
- #
- # Bundler::URI.unescape(enc_uri)
- # # => "http://example.com/?a=\t\r"
- #
- # Bundler::URI.escape("@?@!", "!?")
- # # => "@%3F@%21"
- #
- def escape(*arg)
- warn "Bundler::URI.escape is obsolete", uplevel: 1
- DEFAULT_PARSER.escape(*arg)
- end
- alias encode escape
- #
- # == Synopsis
- #
- # Bundler::URI.unescape(str)
- #
- # == Args
- #
- # +str+::
- # String to unescape.
- #
- # == Description
- #
- # This method is obsolete and should not be used. Instead, use
- # CGI.unescape, Bundler::URI.decode_www_form or Bundler::URI.decode_www_form_component
- # depending on your specific use case.
- #
- # == Usage
- #
- # require 'bundler/vendor/uri/lib/uri'
- #
- # enc_uri = Bundler::URI.escape("http://example.com/?a=\11\15")
- # # => "http://example.com/?a=%09%0D"
- #
- # Bundler::URI.unescape(enc_uri)
- # # => "http://example.com/?a=\t\r"
- #
- def unescape(*arg)
- warn "Bundler::URI.unescape is obsolete", uplevel: 1
- DEFAULT_PARSER.unescape(*arg)
- end
- alias decode unescape
- end # module Escape
-
- extend Escape
include REGEXP
@@schemes = {}
@@ -146,6 +69,20 @@ module Bundler::URI
end
#
+ # Construct a Bundler::URI instance, using the scheme to detect the appropriate class
+ # from +Bundler::URI.scheme_list+.
+ #
+ def self.for(scheme, *arguments, default: Generic)
+ if scheme
+ uri_class = @@schemes[scheme.upcase] || default
+ else
+ uri_class = default
+ end
+
+ return uri_class.new(scheme, *arguments)
+ end
+
+ #
# Base class for all Bundler::URI exceptions.
#
class Error < StandardError; end
@@ -315,7 +252,7 @@ module Bundler::URI
#
# Returns a Regexp object which matches to Bundler::URI-like strings.
# The Regexp object returned by this method includes arbitrary
- # number of capture group (parentheses). Never rely on it's number.
+ # number of capture group (parentheses). Never rely on its number.
#
# == Usage
#
@@ -362,7 +299,7 @@ module Bundler::URI
# If +enc+ is given, convert +str+ to the encoding before percent encoding.
#
# This is an implementation of
- # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
+ # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
#
# See Bundler::URI.decode_www_form_component, Bundler::URI.encode_www_form.
def self.encode_www_form_component(str, enc=nil)
@@ -403,7 +340,7 @@ module Bundler::URI
# This method doesn't handle files. When you send a file, use
# multipart/form-data.
#
- # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer
+ # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer
#
# Bundler::URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
# #=> "q=ruby&lang=en"
diff --git a/lib/bundler/vendor/uri/lib/uri/ftp.rb b/lib/bundler/vendor/uri/lib/uri/ftp.rb
index ad39f57d7b..2252e405d5 100644
--- a/lib/bundler/vendor/uri/lib/uri/ftp.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ftp.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
diff --git a/lib/bundler/vendor/uri/lib/uri/generic.rb b/lib/bundler/vendor/uri/lib/uri/generic.rb
index 56b09e1d7f..f29ba6cf18 100644
--- a/lib/bundler/vendor/uri/lib/uri/generic.rb
+++ b/lib/bundler/vendor/uri/lib/uri/generic.rb
@@ -4,7 +4,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
@@ -1098,7 +1097,7 @@ module Bundler::URI
# # => "http://my.example.com/main.rbx?page=1"
#
def merge(oth)
- rel = parser.send(:convert_to_uri, oth)
+ rel = parser.__send__(:convert_to_uri, oth)
if rel.absolute?
#raise BadURIError, "both Bundler::URI are absolute" if absolute?
@@ -1183,7 +1182,7 @@ module Bundler::URI
# :stopdoc:
def route_from0(oth)
- oth = parser.send(:convert_to_uri, oth)
+ oth = parser.__send__(:convert_to_uri, oth)
if self.relative?
raise BadURIError,
"relative Bundler::URI: #{self}"
@@ -1291,7 +1290,7 @@ module Bundler::URI
# #=> #<Bundler::URI::Generic /main.rbx?page=1>
#
def route_to(oth)
- parser.send(:convert_to_uri, oth).route_from(self)
+ parser.__send__(:convert_to_uri, oth).route_from(self)
end
#
@@ -1405,7 +1404,7 @@ module Bundler::URI
# Returns an Array of the components defined from the COMPONENT Array.
def component_ary
component.collect do |x|
- self.send(x)
+ self.__send__(x)
end
end
protected :component_ary
@@ -1430,7 +1429,7 @@ module Bundler::URI
def select(*components)
components.collect do |c|
if component.include?(c)
- self.send(c)
+ self.__send__(c)
else
raise ArgumentError,
"expected of components of #{self.class} (#{self.class.component.join(', ')})"
diff --git a/lib/bundler/vendor/uri/lib/uri/http.rb b/lib/bundler/vendor/uri/lib/uri/http.rb
index b6ca1c51de..50d7e427a5 100644
--- a/lib/bundler/vendor/uri/lib/uri/http.rb
+++ b/lib/bundler/vendor/uri/lib/uri/http.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
diff --git a/lib/bundler/vendor/uri/lib/uri/https.rb b/lib/bundler/vendor/uri/lib/uri/https.rb
index 78dc6bf532..4fd4e9af7b 100644
--- a/lib/bundler/vendor/uri/lib/uri/https.rb
+++ b/lib/bundler/vendor/uri/lib/uri/https.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
diff --git a/lib/bundler/vendor/uri/lib/uri/ldap.rb b/lib/bundler/vendor/uri/lib/uri/ldap.rb
index b707bedb97..6e9e1918f6 100644
--- a/lib/bundler/vendor/uri/lib/uri/ldap.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ldap.rb
@@ -7,7 +7,6 @@
# License::
# Bundler::URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada.
# You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
@@ -119,6 +118,7 @@ module Bundler::URI
# Private method to cleanup +dn+ from using the +path+ component attribute.
def parse_dn
+ raise InvalidURIError, 'bad LDAP URL' unless @path
@dn = @path[1..-1]
end
private :parse_dn
diff --git a/lib/bundler/vendor/uri/lib/uri/mailto.rb b/lib/bundler/vendor/uri/lib/uri/mailto.rb
index 5b2a4765c8..ff7ab7e114 100644
--- a/lib/bundler/vendor/uri/lib/uri/mailto.rb
+++ b/lib/bundler/vendor/uri/lib/uri/mailto.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See Bundler::URI for general documentation
#
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
index a0d62ede64..e48e164f4c 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
@@ -3,7 +3,6 @@
# = uri/common.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
-# Revision:: $Id$
# License::
# You can redistribute it and/or modify it under the same term as Ruby.
#
@@ -208,21 +207,9 @@ module Bundler::URI
# #=> #<Bundler::URI::LDAP ldap://ldap.example.com/dc=example?user=john>
#
def parse(uri)
- scheme, userinfo, host, port,
- registry, path, opaque, query, fragment = self.split(uri)
-
- if scheme && Bundler::URI.scheme_list.include?(scheme.upcase)
- Bundler::URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- else
- Generic.new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- end
+ Bundler::URI.for(*self.split(uri), self)
end
-
#
# == Args
#
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
index 07ef4391c0..2029cfd056 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -69,18 +69,7 @@ module Bundler::URI
end
def parse(uri) # :nodoc:
- scheme, userinfo, host, port,
- registry, path, opaque, query, fragment = self.split(uri)
- scheme_list = Bundler::URI.scheme_list
- if scheme && scheme_list.include?(uc = scheme.upcase)
- scheme_list[uc].new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- else
- Generic.new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- end
+ Bundler::URI.for(*self.split(uri), self)
end
diff --git a/lib/bundler/vendor/uri/lib/uri/version.rb b/lib/bundler/vendor/uri/lib/uri/version.rb
index 56177ef194..f2bb0ebad2 100644
--- a/lib/bundler/vendor/uri/lib/uri/version.rb
+++ b/lib/bundler/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Bundler::URI
# :stopdoc:
- VERSION_CODE = '001000'.freeze
+ VERSION_CODE = '001001'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/bundler/vendor/uri/lib/uri/ws.rb b/lib/bundler/vendor/uri/lib/uri/ws.rb
new file mode 100644
index 0000000000..58e08bf98e
--- /dev/null
+++ b/lib/bundler/vendor/uri/lib/uri/ws.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: false
+# = uri/ws.rb
+#
+# Author:: Matt Muller <mamuller@amazon.com>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+#
+# See Bundler::URI for general documentation
+#
+
+require_relative 'generic'
+
+module Bundler::URI
+
+ #
+ # The syntax of WS URIs is defined in RFC6455 section 3.
+ #
+ # Note that the Ruby Bundler::URI library allows WS URLs containing usernames and
+ # passwords. This is not legal as per the RFC, but used to be
+ # supported in Internet Explorer 5 and 6, before the MS04-004 security
+ # update. See <URL:http://support.microsoft.com/kb/834489>.
+ #
+ class WS < Generic
+ # A Default port of 80 for Bundler::URI::WS.
+ DEFAULT_PORT = 80
+
+ # An Array of the available components for Bundler::URI::WS.
+ COMPONENT = %i[
+ scheme
+ userinfo host port
+ path
+ query
+ ].freeze
+
+ #
+ # == Description
+ #
+ # Creates a new Bundler::URI::WS object from components, with syntax checking.
+ #
+ # The components accepted are userinfo, host, port, path, and query.
+ #
+ # The components should be provided either as an Array, or as a Hash
+ # with keys formed by preceding the component names with a colon.
+ #
+ # If an Array is used, the components must be passed in the
+ # order <code>[userinfo, host, port, path, query]</code>.
+ #
+ # Example:
+ #
+ # uri = Bundler::URI::WS.build(host: 'www.example.com', path: '/foo/bar')
+ #
+ # uri = Bundler::URI::WS.build([nil, "www.example.com", nil, "/path", "query"])
+ #
+ # Currently, if passed userinfo components this method generates
+ # invalid WS URIs as per RFC 1738.
+ #
+ def self.build(args)
+ tmp = Util.make_components_hash(self, args)
+ super(tmp)
+ end
+
+ #
+ # == Description
+ #
+ # Returns the full path for a WS Bundler::URI, as required by Net::HTTP::Get.
+ #
+ # If the Bundler::URI contains a query, the full path is Bundler::URI#path + '?' + Bundler::URI#query.
+ # Otherwise, the path is simply Bundler::URI#path.
+ #
+ # Example:
+ #
+ # uri = Bundler::URI::WS.build(path: '/foo/bar', query: 'test=true')
+ # uri.request_uri # => "/foo/bar?test=true"
+ #
+ def request_uri
+ return unless @path
+
+ url = @query ? "#@path?#@query" : @path.dup
+ url.start_with?(?/.freeze) ? url : ?/ + url
+ end
+ end
+
+ @@schemes['WS'] = WS
+
+end
diff --git a/lib/bundler/vendor/uri/lib/uri/wss.rb b/lib/bundler/vendor/uri/lib/uri/wss.rb
new file mode 100644
index 0000000000..3827053c7b
--- /dev/null
+++ b/lib/bundler/vendor/uri/lib/uri/wss.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: false
+# = uri/wss.rb
+#
+# Author:: Matt Muller <mamuller@amazon.com>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+#
+# See Bundler::URI for general documentation
+#
+
+require_relative 'ws'
+
+module Bundler::URI
+
+ # The default port for WSS URIs is 443, and the scheme is 'wss:' rather
+ # than 'ws:'. Other than that, WSS URIs are identical to WS URIs;
+ # see Bundler::URI::WS.
+ class WSS < WS
+ # A Default port of 443 for Bundler::URI::WSS
+ DEFAULT_PORT = 443
+ end
+ @@schemes['WSS'] = WSS
+end
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 55755ddfba..185efdb6ab 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -225,7 +225,7 @@ class Gem::SystemExitException < SystemExit
def initialize(exit_code)
@exit_code = exit_code
- super "Exiting RubyGems with exit_code #{exit_code}"
+ super exit_code, "Exiting RubyGems with exit_code #{exit_code}"
end
end
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 00e68916c4..f465881041 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -31,7 +31,8 @@ module Gem::GemcutterUtilities
def add_otp_option
add_option('--otp CODE',
- 'Digit code for multifactor authentication') do |value, options|
+ 'Digit code for multifactor authentication',
+ 'You can also use the environment variable GEM_HOST_OTP_CODE') do |value, options|
options[:otp] = value
end
end
diff --git a/lib/rubygems/package/io_source.rb b/lib/rubygems/package/io_source.rb
index 7d7383110b..03d7714524 100644
--- a/lib/rubygems/package/io_source.rb
+++ b/lib/rubygems/package/io_source.rb
@@ -32,10 +32,14 @@ class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all
def with_read_io
yield io
+ ensure
+ io.rewind
end
def with_write_io
yield io
+ ensure
+ io.rewind
end
def path
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 56ef4ce75a..d164b5d3c6 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -249,11 +249,8 @@ EOF
allow(Bundler.rubygems).to receive(:user_home).and_return(path)
allow(File).to receive(:directory?).with(path).and_return false
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
- message = <<EOF
-`/home/oggy` is not a directory.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not a directory.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
@@ -268,11 +265,8 @@ EOF
allow(File).to receive(:writable?).with(path).and_return false
allow(File).to receive(:directory?).with(dotbundle).and_return false
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
- message = <<EOF
-`/home/oggy` is not writable.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not writable.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
@@ -293,11 +287,8 @@ EOF
it "should issue warning and return a temporary user home" do
allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
- message = <<EOF
-Your home directory is not set.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("Your home directory is not set.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 0f1a9c2a6f..24e3de7ba8 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -64,13 +64,10 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "#global_config_file" do
context "when $HOME is not accessible" do
- context "when $TMPDIR is not writable" do
- it "does not raise" do
- expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(Bundler).to receive(:tmp).twice.and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
+ it "does not raise" do
+ expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(subject.send(:global_config_file)).to be_nil
- end
+ expect(subject.send(:global_config_file)).to be_nil
end
end
end
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index 2860c82a12..88950cef85 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -288,6 +288,34 @@ RSpec.describe "bundle check" do
end
end
+ describe "when locked with multiple dependents with different requirements" do
+ before :each do
+ build_repo4 do
+ build_gem "depends_on_rack" do |s|
+ s.add_dependency "rack", ">= 1.0"
+ end
+ build_gem "also_depends_on_rack" do |s|
+ s.add_dependency "rack", "~> 1.0"
+ end
+ build_gem "rack"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "depends_on_rack"
+ gem "also_depends_on_rack"
+ G
+
+ bundle "lock"
+ end
+
+ it "shows what is missing with the current Gemfile without duplications" do
+ bundle :check, :raise_on_error => false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* rack (1.0").once
+ end
+ end
+
describe "when using only scoped rubygems sources" do
before do
gemfile <<~G
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 0d104ad304..39430d52a4 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -24,6 +24,16 @@ RSpec.describe "bundle exec" do
expect(out).to eq("0.9.1")
end
+ it "works and prints no warnings when HOME is not writable" do
+ gemfile <<-G
+ gem "rack", "0.9.1"
+ G
+
+ bundle "exec rackup", :env => { "HOME" => "/" }
+ expect(out).to eq("0.9.1")
+ expect(err).to be_empty
+ end
+
it "works when the bins are in ~/.bundle" do
install_gemfile <<-G
gem "rack"
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index c91864dbb8..3c0c35d844 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -344,54 +344,72 @@ RSpec.describe "bundle install with gem sources" do
expect(File.exist?(bundled_app_lock)).to eq(true)
end
- context "throws a warning if a gem is added twice in Gemfile" do
- it "without version requirements" do
- install_gemfile <<-G, :raise_on_error => false
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "rack"
- G
+ it "throws a warning if a gem is added twice in Gemfile without version requirements" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+ gem "rack"
+ G
- expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
- expect(err).to include("Remove any duplicate entries and specify the gem only once.")
- expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
- end
+ expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
- it "with same versions" do
- install_gemfile <<-G, :raise_on_error => false
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
- gem "rack", "1.0"
- G
+ it "throws a warning if a gem is added twice in Gemfile with same versions" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack", "1.0"
+ gem "rack", "1.0"
+ G
- expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
- expect(err).to include("Remove any duplicate entries and specify the gem only once.")
- expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
- end
+ expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
end
- context "throws an error if a gem is added twice in Gemfile" do
- it "when version of one dependency is not specified" do
- install_gemfile <<-G, :raise_on_error => false
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "rack", "1.0"
- G
+ it "does not throw a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency" do
+ build_lib "my-gem", :path => bundled_app do |s|
+ s.add_development_dependency "my-private-gem"
+ end
- expect(err).to include("You cannot specify the same gem twice with different version requirements")
- expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ build_repo2 do
+ build_gem "my-private-gem"
end
- it "when different versions of both dependencies are specified" do
- install_gemfile <<-G, :raise_on_error => false
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
- gem "rack", "1.1"
- G
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
- expect(err).to include("You cannot specify the same gem twice with different version requirements")
- expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).")
- end
+ gemspec
+
+ gem "my-private-gem", :group => :development
+ G
+
+ bundle :install
+
+ expect(err).to be_empty
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when version of one dependency is not specified" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+ gem "rack", "1.0"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when different versions of both dependencies are specified" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack", "1.0"
+ gem "rack", "1.1"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).")
end
it "gracefully handles error when rubygems server is unavailable" do
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 00bd009c5a..56fea008ec 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -307,42 +307,42 @@ RSpec.describe "bundle gem" do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --linter=rubocop"
bundle_exec_rubocop
- expect(err).to be_empty
+ expect(last_command).to be_success
end
it "has no rubocop offenses when using --ext and --linter=rubocop flag", :readline do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --ext --linter=rubocop"
bundle_exec_rubocop
- expect(err).to be_empty
+ expect(last_command).to be_success
end
it "has no rubocop offenses when using --ext, --test=minitest, and --linter=rubocop flag", :readline do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --ext --test=minitest --linter=rubocop"
bundle_exec_rubocop
- expect(err).to be_empty
+ expect(last_command).to be_success
end
it "has no rubocop offenses when using --ext, --test=rspec, and --linter=rubocop flag", :readline do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --ext --test=rspec --linter=rubocop"
bundle_exec_rubocop
- expect(err).to be_empty
+ expect(last_command).to be_success
end
it "has no rubocop offenses when using --ext, --ext=test-unit, and --linter=rubocop flag", :readline do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --ext --test=test-unit --linter=rubocop"
bundle_exec_rubocop
- expect(err).to be_empty
+ expect(last_command).to be_success
end
it "has no standard offenses when using --linter=standard flag", :readline do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
bundle "gem #{gem_name} --linter=standard"
bundle_exec_standardrb
- expect(err).to be_empty
+ expect(last_command).to be_success
end
shared_examples_for "CI config is absent" do
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index c6e526a95e..a6d8318fe4 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -249,6 +249,38 @@ RSpec.describe "bundle install with specific platforms" do
end
end
+ it "installs sorbet-static, which does not provide a pure ruby variant, just fine on truffleruby", :truffleruby do
+ build_repo2 do
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "sorbet-static", "0.5.6403"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ sorbet-static (0.5.6403-universal-darwin-20)
+ sorbet-static (0.5.6403-x86_64-linux)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.6403)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ end
+
private
def setup_multiplatform_gem
diff --git a/spec/bundler/plugins/install_spec.rb b/spec/bundler/plugins/install_spec.rb
index 308f9c79fc..2175610b10 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -22,6 +22,13 @@ RSpec.describe "bundler plugin install" do
plugin_should_be_installed("foo")
end
+ it "installs from sources configured as Gem.sources without any flags" do
+ bundle "plugin install foo", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
context "plugin is already installed" do
before do
bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index 556a11d2f3..f031e2f354 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -196,21 +196,6 @@ RSpec.describe "real world edgecases", :realworld => true do
expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
end
- # https://github.com/rubygems/bundler/issues/1500
- it "does not fail install because of gem plugins" do
- realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2")
- gemfile <<-G
- source "https://rubygems.org"
-
- gem 'rack', '1.0.1'
- G
-
- bundle "config set --local path vendor/bundle"
- bundle :install
- expect(err).not_to include("Could not find rake")
- 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'
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index d8ba569f0a..380db99136 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -644,6 +644,25 @@ RSpec.describe "Bundler.setup" do
expect(err).to be_empty
end
+ it "doesn't re-resolve when a pre-release bundler is used and a dependency includes a dependency on bundler" do
+ system_gems "bundler-9.99.9.beta1"
+
+ build_repo4 do
+ build_gem "depends_on_bundler", "1.0" do |s|
+ s.add_dependency "bundler", ">= 1.5.0"
+ end
+ end
+
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "depends_on_bundler"
+ G
+
+ ruby "require '#{system_gem_path("gems/bundler-9.99.9.beta1/lib/bundler.rb")}'; Bundler.setup", :env => { "DEBUG" => "1" }
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ expect(err).to be_empty
+ end
+
it "remembers --without and does not include groups passed to Bundler.setup" do
bundle "config set --local without rails"
install_gemfile <<-G
diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb
index 88c33d93dc..0d51201bef 100644
--- a/spec/bundler/support/artifice/vcr.rb
+++ b/spec/bundler/support/artifice/vcr.rb
@@ -133,6 +133,19 @@ class BundlerVCRHTTP < Net::HTTP
end
end
+ def start_with_vcr
+ if ENV["BUNDLER_SPEC_PRE_RECORDED"]
+ raise IOError, "HTTP session already opened" if @started
+ @socket = nil
+ @started = true
+ else
+ start_without_vcr
+ end
+ end
+
+ alias_method :start_without_vcr, :start
+ alias_method :start, :start_with_vcr
+
def request_with_vcr(request, *args, &block)
handler = request.instance_eval do
remove_instance_variable(:@__vcr_request_handler) if defined?(@__vcr_request_handler)
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index ddb62f7d53..aaf8c74894 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -28,6 +28,10 @@ module Gem
end
end
+ if ENV["BUNDLER_SPEC_GEM_SOURCES"]
+ @sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
+ end
+
# We only need this hack for rubygems versions without the BundlerVersionFinder
if Gem.rubygems_version < Gem::Version.new("2.7.0")
@path_to_default_spec_map.delete_if do |_path, spec|
diff --git a/test/rubygems/test_exit.rb b/test/rubygems/test_exit.rb
new file mode 100644
index 0000000000..9557fe5d06
--- /dev/null
+++ b/test/rubygems/test_exit.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require_relative 'helper'
+require 'rubygems'
+
+class TestExit < Gem::TestCase
+ def test_exit
+ system(*ruby_with_rubygems_in_load_path, "-e", "raise Gem::SystemExitException.new(2)")
+ assert_equal 2, $?.exitstatus
+ end
+end
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
index dbb037fd80..3fa2c1911c 100644
--- a/test/rubygems/test_gem_package.rb
+++ b/test/rubygems/test_gem_package.rb
@@ -1145,6 +1145,13 @@ class TestGemPackage < Gem::Package::TarTestCase
end
end
+ def test_contents_from_io
+ io = StringIO.new Gem.read_binary @gem
+ package = Gem::Package.new io
+
+ assert_equal %w[lib/code.rb], package.contents
+ end
+
def util_tar
tar_io = StringIO.new