Merge RubyGems 3.5.5 and Bundler 2.5.5 (#9676)

* Merge RubyGems-3.5.4 and Bundler-2.5.4

* Merge RubyGems-3.5.5 and Bundler-2.5.5

* Make tests play with upstream Ruby tests

CI broke in https://github.com/ruby/ruby/pull/9604 because if any Ruby
tests run `require 'net/http'`, they will pollute the
`$LOADED_FEATURES` for the RubyGems tests. We can fix this by renaming
the test default gem from `net-http` to `my-http`.

See https://github.com/rubygems/rubygems/pull/7379#issuecomment-1901241299
for more details.

---------

Co-authored-by: Stan Hu <stanhu@gmail.com>
This commit is contained in:
Hiroshi SHIBATA 2024-02-05 23:51:04 +09:00 committed by GitHub
parent 7f97e3540c
commit ac526abcd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 323 additions and 128 deletions

View file

@ -42,7 +42,7 @@ module Bundler
else
file.write(response.body)
end
CacheFile.write(etag_path, etag(response))
CacheFile.write(etag_path, etag_from_response(response))
true
end
end
@ -53,13 +53,13 @@ module Bundler
response = @fetcher.call(remote_path, request_headers(etag))
return true if response.is_a?(Gem::Net::HTTPNotModified)
CacheFile.write(local_path, response.body, parse_digests(response))
CacheFile.write(etag_path, etag(response))
CacheFile.write(etag_path, etag_from_response(response))
end
def request_headers(etag, range_start = nil)
headers = {}
headers["Range"] = "bytes=#{range_start}-" if range_start
headers["If-None-Match"] = etag if etag
headers["If-None-Match"] = %("#{etag}") if etag
headers
end
@ -77,7 +77,7 @@ module Bundler
etag
end
def etag(response)
def etag_from_response(response)
return unless response["ETag"]
etag = response["ETag"].delete_prefix("W/")
return if etag.delete_prefix!('"') && !etag.delete_suffix!('"')

View file

@ -312,10 +312,6 @@ module Bundler
end
end
def should_complete_platforms?
!lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
end
def spec_git_paths
sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
end
@ -517,6 +513,10 @@ module Bundler
private
def should_add_extra_platforms?
!lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
end
def lockfile_exists?
lockfile && File.exist?(lockfile)
end
@ -600,7 +600,9 @@ module Bundler
result = SpecSet.new(resolver.start)
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
@platforms = result.complete_platforms!(platforms) if should_complete_platforms?
@platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
result.complete_platforms!(platforms)
SpecSet.new(result.for(dependencies, false, @platforms))
end

View file

@ -102,9 +102,6 @@ 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 }
# Always prefer the dependency from the Gemfile
@dependencies.delete(current) if current.gemspec_dev_dep?
if current.requirement != dep.requirement
current_requirement_open = current.requirements_list.include?(">= 0")
@ -116,8 +113,6 @@ module Bundler
Bundler.ui.warn "A gemspec development dependency (#{gemspec_dep.name}, #{gemspec_dep.requirement}) is being overridden by a Gemfile dependency (#{gemfile_dep.name}, #{gemfile_dep.requirement}).\n" \
"This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement\n"
end
return if dep.gemspec_dev_dep?
else
update_prompt = ""
@ -135,8 +130,13 @@ module Bundler
"You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
"#{update_prompt}"
end
elsif current.gemspec_dev_dep? || dep.gemspec_dev_dep?
return if dep.gemspec_dev_dep?
end
# Always prefer the dependency from the Gemfile
if current.gemspec_dev_dep?
@dependencies.delete(current)
elsif dep.gemspec_dev_dep?
return
elsif current.source != dep.source
raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
"You specified that #{dep.name} (#{dep.requirement}) should come from " \

View file

@ -302,9 +302,9 @@ Note that any configured credentials will be redacted by informative commands su
.P
Also note that to guarantee a sane mapping between valid environment variable names and valid host names, bundler makes the following transformations:
.IP "\(bu" 4
Any \fB\-\fR characters in a host name are mapped to a triple dash (\fB___\fR) in the corresponding environment variable\.
Any \fB\-\fR characters in a host name are mapped to a triple underscore (\fB___\fR) in the corresponding environment variable\.
.IP "\(bu" 4
Any \fB\.\fR characters in a host name are mapped to a double dash (\fB__\fR) in the corresponding environment variable\.
Any \fB\.\fR characters in a host name are mapped to a double underscore (\fB__\fR) in the corresponding environment variable\.
.IP "" 0
.P
This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you'll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.

View file

@ -388,10 +388,10 @@ copy-pasting bundler output.
Also note that to guarantee a sane mapping between valid environment variable
names and valid host names, bundler makes the following transformations:
* Any `-` characters in a host name are mapped to a triple dash (`___`) in the
* Any `-` characters in a host name are mapped to a triple underscore (`___`) in the
corresponding environment variable.
* Any `.` characters in a host name are mapped to a double dash (`__`) in the
* Any `.` characters in a host name are mapped to a double underscore (`__`) in the
corresponding environment variable.
This means that if you have a gem server named `my.gem-host.com`, you'll need to

View file

@ -52,32 +52,14 @@ module Bundler
specs.uniq
end
def complete_platforms!(platforms)
def add_extra_platforms!(platforms)
return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty?
new_platforms = @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq.select do |platform|
new_platforms = all_platforms.select do |platform|
next if platforms.include?(platform)
next unless GemHelpers.generic(platform) == Gem::Platform::RUBY
new_specs = []
valid_platform = lookup.all? do |_, specs|
spec = specs.first
matching_specs = spec.source.specs.search([spec.name, spec.version])
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
s.matches_current_metadata? && valid_dependencies?(s)
end
if platform_spec
new_specs << LazySpecification.from_spec(platform_spec)
true
else
false
end
end
next unless valid_platform
@specs.concat(new_specs.uniq)
complete_platform(platform)
end
return platforms if new_platforms.empty?
@ -86,12 +68,15 @@ module Bundler
less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform }
platforms.delete(Bundler.local_platform) if less_specific_platform
@sorted = nil
@lookup = nil
platforms
end
def complete_platforms!(platforms)
platforms.each do |platform|
complete_platform(platform)
end
end
def validate_deps(s)
s.runtime_dependencies.each do |dep|
next if dep.name == "bundler"
@ -110,14 +95,14 @@ module Bundler
def []=(key, value)
@specs << value
@lookup = nil
@sorted = nil
reset!
end
def delete(specs)
specs.each {|spec| @specs.delete(spec) }
@lookup = nil
@sorted = nil
reset!
end
def sort!
@ -175,8 +160,8 @@ module Bundler
def delete_by_name(name)
@specs.reject! {|spec| spec.name == name }
@lookup = nil
@sorted = nil
reset!
end
def what_required(spec)
@ -212,6 +197,42 @@ module Bundler
private
def reset!
@sorted = nil
@lookup = nil
end
def complete_platform(platform)
new_specs = []
valid_platform = lookup.all? do |_, specs|
spec = specs.first
matching_specs = spec.source.specs.search([spec.name, spec.version])
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
s.matches_current_metadata? && valid_dependencies?(s)
end
if platform_spec
new_specs << LazySpecification.from_spec(platform_spec) unless specs.include?(platform_spec)
true
else
false
end
end
if valid_platform && new_specs.any?
@specs.concat(new_specs)
reset!
end
valid_platform
end
def all_platforms
@specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq
end
def valid_dependencies?(s)
validate_deps(s) == :valid
end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
VERSION = "2.5.3".freeze
VERSION = "2.5.5".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i

View file

@ -9,7 +9,7 @@
require "rbconfig"
module Gem
VERSION = "3.5.3"
VERSION = "3.5.5"
end
# Must be first since it unloads the prelude from 1.9.2
@ -1216,6 +1216,13 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# Find a Gem::Specification of default gem from +path+
def find_default_spec(path)
@path_to_default_spec_map[path]
end
##
# Find an unresolved Gem::Specification of default gem from +path+
def find_unresolved_default_spec(path)
default_spec = @path_to_default_spec_map[path]
return default_spec if default_spec && loaded_specs[default_spec.name] != default_spec

View file

@ -244,7 +244,7 @@ command to remove old versions.
@installer = Gem::DependencyInstaller.new update_options
say "Updating #{name}" unless options[:system] && options[:silent]
say "Updating #{name}" unless options[:system]
begin
@installer.install name, Gem::Requirement.new(version)
rescue Gem::InstallError, Gem::DependencyError => e
@ -282,7 +282,7 @@ command to remove old versions.
check_oldest_rubygems version
installed_gems = Gem::Specification.find_all_by_name "rubygems-update", requirement
installed_gems = update_gem("rubygems-update", version) if installed_gems.empty? || installed_gems.first.version != version
installed_gems = update_gem("rubygems-update", requirement) if installed_gems.empty? || installed_gems.first.version != version
return if installed_gems.empty?
install_rubygems installed_gems.first
@ -294,9 +294,7 @@ command to remove old versions.
args << "--prefix" << Gem.prefix if Gem.prefix
args << "--no-document" unless options[:document].include?("rdoc") || options[:document].include?("ri")
args << "--no-format-executable" if options[:no_format_executable]
args << "--previous-version" << Gem::VERSION if
options[:system] == true ||
Gem::Version.new(options[:system]) >= Gem::Version.new(2)
args << "--previous-version" << Gem::VERSION
args
end

View file

@ -39,7 +39,14 @@ module Kernel
RUBYGEMS_ACTIVATION_MONITOR.synchronize do
path = File.path(path)
if spec = Gem.find_unresolved_default_spec(path)
# If +path+ belongs to a default gem, we activate it and then go straight
# to normal require
if spec = Gem.find_default_spec(path)
name = spec.name
next if Gem.loaded_specs[name]
# Ensure -I beats a default gem
resolved_path = begin
rp = nil
@ -57,8 +64,10 @@ module Kernel
rp
end
Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless
Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless
resolved_path
next
end
# If there are no unresolved deps, then we can use just try

View file

@ -24,7 +24,7 @@ module Gem
default_spec_cache_dir = File.join Gem.user_home, ".gem", "specs"
unless File.exist?(default_spec_cache_dir)
default_spec_cache_dir = File.join Gem.data_home, "gem", "specs"
default_spec_cache_dir = File.join Gem.cache_home, "gem", "specs"
end
default_spec_cache_dir

View file

@ -301,7 +301,7 @@ class Gem::Specification < Gem::BasicSpecification
#
# Usage:
#
# spec.description = <<-EOF
# spec.description = <<~EOF
# Rake is a Make-like program implemented in Ruby. Tasks and
# dependencies are specified in standard Ruby syntax.
# EOF

View file

@ -21,7 +21,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
before do
allow(response).to receive(:[]).with("Repr-Digest") { nil }
allow(response).to receive(:[]).with("Digest") { nil }
allow(response).to receive(:[]).with("ETag") { "thisisanetag" }
allow(response).to receive(:[]).with("ETag") { '"thisisanetag"' }
end
it "downloads the file without attempting append" do
@ -57,7 +57,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
let(:headers) do
{
"If-None-Match" => "LocalEtag",
"If-None-Match" => '"LocalEtag"',
"Range" => "bytes=2-",
}
end
@ -76,7 +76,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
it "appends the file if etags do not match" do
expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
allow(response).to receive(:[]).with("ETag") { "NewEtag" }
allow(response).to receive(:[]).with("ETag") { '"NewEtag"' }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
allow(response).to receive(:body) { "c123" }
@ -90,7 +90,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
it "replaces the file if response ignores range" do
expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
allow(response).to receive(:[]).with("ETag") { "NewEtag" }
allow(response).to receive(:[]).with("ETag") { '"NewEtag"' }
allow(response).to receive(:body) { full_body }
updater.update(remote_path, local_path, etag_path)
@ -107,8 +107,8 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
full_response = double(:full_response, body: full_body, is_a?: false)
allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
allow(full_response).to receive(:[]).with("ETag") { "NewEtag" }
expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => "LocalEtag" }).and_return(full_response)
allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
updater.update(remote_path, local_path, etag_path)
@ -123,7 +123,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
"Range" => "bytes=2-",
# This MD5 feature should be deleted after sufficient time has passed since release.
# From then on, requests that still don't have a saved etag will be made without this header.
"If-None-Match" => Digest::MD5.hexdigest(local_body),
"If-None-Match" => %("#{Digest::MD5.hexdigest(local_body)}"),
}
end
@ -135,13 +135,13 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
updater.update(remote_path, local_path, etag_path)
expect(local_path.read).to eq("abc")
expect(etag_path.read).to eq(headers["If-None-Match"])
expect(%("#{etag_path.read}")).to eq(headers["If-None-Match"])
end
it "appends the file" do
expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
allow(response).to receive(:[]).with("ETag") { "OpaqueEtag" }
allow(response).to receive(:[]).with("ETag") { '"OpaqueEtag"' }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
allow(response).to receive(:body) { "c123" }
@ -156,7 +156,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
allow(response).to receive(:[]).with("Repr-Digest") { nil }
allow(response).to receive(:[]).with("Digest") { nil }
allow(response).to receive(:[]).with("ETag") { "OpaqueEtag" }
allow(response).to receive(:[]).with("ETag") { '"OpaqueEtag"' }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { false }
allow(response).to receive(:is_a?).with(Gem::Net::HTTPNotModified) { false }
allow(response).to receive(:body) { full_body }
@ -180,8 +180,8 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
full_response = double(:full_response, body: full_body, is_a?: false)
allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
allow(full_response).to receive(:[]).with("ETag") { "NewEtag" }
expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => "LocalEtag" }).and_return(full_response)
allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
updater.update(remote_path, local_path, etag_path)

View file

@ -460,6 +460,35 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems("rubocop 1.37.1")
end
it "includes the gem without warning if two gemspecs add it with the same requirement" do
gem1 = tmp.join("my-gem-1")
gem2 = tmp.join("my-gem-2")
build_lib "my-gem", path: gem1 do |s|
s.add_development_dependency "rubocop", "~> 1.36.0"
end
build_lib "my-gem-2", path: gem2 do |s|
s.add_development_dependency "rubocop", "~> 1.36.0"
end
build_repo4 do
build_gem "rubocop", "1.36.0"
end
gemfile <<~G
source "#{file_uri_for(gem_repo4)}"
gemspec path: "#{gem1}"
gemspec path: "#{gem2}"
G
bundle :install
expect(err).to be_empty
expect(the_bundle).to include_gems("rubocop 1.36.0")
end
it "warns when a Gemfile dependency is overriding a gemspec development dependency, with different requirements" do
build_lib "my-gem", path: bundled_app do |s|
s.add_development_dependency "rails", ">= 5"

View file

@ -1380,7 +1380,7 @@ RSpec.describe "bundle update --bundler" do
build_bundler "999.0.0"
end
install_gemfile <<-G
install_gemfile <<-G, artifice: nil, env: { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
source "#{file_uri_for(gem_repo4)}"
gem "rack"
G

View file

@ -924,15 +924,19 @@ RSpec.describe "compact index api" do
gem 'rack', '0.9.1'
G
rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
bundle :install, artifice: "compact_index"
# We must remove the etag so that we don't ignore the range and get a 304 Not Modified.
rake_info_etag_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info-etags", "rack-11690b09f16021ff06a6857d784a1870")
File.unlink(rake_info_etag_path) if File.exist?(rake_info_etag_path)
rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
expected_rack_info_content = File.read(rake_info_path)
# Modify the cache files. We expect them to be reset to the normal ones when we re-run :install
File.open(rake_info_path, "a") {|f| f << "this is different" }
# Modify the cache files to make the range not satisfiable
File.open(rake_info_path, "a") {|f| f << "0.9.2 |checksum:c55b525b421fd833a93171ad3d7f04528ca8e87d99ac273f8933038942a5888c" }
# Update the Gemfile so the next install does its normal things
gemfile <<-G

View file

@ -1195,6 +1195,46 @@ RSpec.describe "the lockfile format" do
G
end
it "adds compatible platform specific variants to the lockfile, even if resolution fallback to RUBY due to some other incompatible platform specific variant" do
simulate_platform "arm64-darwin-23" do
build_repo4 do
build_gem "google-protobuf", "3.25.1"
build_gem "google-protobuf", "3.25.1" do |s|
s.platform = "arm64-darwin-23"
end
build_gem "google-protobuf", "3.25.1" do |s|
s.platform = "x64-mingw-ucrt"
s.required_ruby_version = "> #{Gem.ruby_version}"
end
end
gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "google-protobuf"
G
bundle "lock --add-platform x64-mingw-ucrt"
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
google-protobuf (3.25.1)
google-protobuf (3.25.1-arm64-darwin-23)
PLATFORMS
arm64-darwin-23
ruby
x64-mingw-ucrt
DEPENDENCIES
google-protobuf
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
it "persists the spec's specific platform to the lockfile" do
build_repo2 do
build_gem "platform_specific", "1.0" do |s|

View file

@ -2,7 +2,7 @@
require_relative "../path"
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
require "sinatra/base"

View file

@ -19,8 +19,8 @@ class CompactIndexAPI < Endpoint
def etag_response
response_body = yield
etag = Digest::MD5.hexdigest(response_body)
return if not_modified?(etag)
headers "ETag" => quote(etag)
return if not_modified?(etag)
headers "Repr-Digest" => "sha-256=:#{Digest::SHA256.base64digest(response_body)}:"
headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
content_type "text/plain"
@ -35,7 +35,6 @@ class CompactIndexAPI < Endpoint
etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
return unless etags.include?(etag)
headers "ETag" => quote(etag)
status 304
body ""
end

View file

@ -2,7 +2,7 @@
require_relative "../../path"
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
require "sinatra/base"

View file

@ -2,7 +2,7 @@
require_relative "../path"
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
require "sinatra/base"

View file

@ -86,7 +86,7 @@ module Spec
puts success_message
puts
else
system("git status --porcelain")
system("git diff")
puts
puts error_message

View file

@ -105,14 +105,8 @@ class Gem::TestCase < Test::Unit::TestCase
refute File.directory?(path), msg
end
# https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188
def _synchronize
yield
end
# https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546
# Originally copied from minitest/assertions.rb
def capture_subprocess_io
_synchronize do
require "tempfile"
captured_stdout = Tempfile.new("out")
@ -128,7 +122,7 @@ class Gem::TestCase < Test::Unit::TestCase
$stdout.rewind
$stderr.rewind
return captured_stdout.read, captured_stderr.read
[captured_stdout.read, captured_stderr.read]
ensure
$stdout.reopen orig_stdout
$stderr.reopen orig_stderr
@ -138,7 +132,6 @@ class Gem::TestCase < Test::Unit::TestCase
captured_stdout.close!
captured_stderr.close!
end
end
##
# Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores

View file

@ -79,7 +79,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@ -123,7 +122,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_empty out
err = @ui.error.split "\n"
@ -132,6 +130,34 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
assert_empty err
end
def test_execute_system_when_latest_does_not_support_your_ruby_but_previous_one_does
spec_fetcher do |fetcher|
fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
s.required_ruby_version = "> 9"
end
fetcher.download "rubygems-update", 8 do |s|
s.files = %w[setup.rb]
end
end
@cmd.options[:args] = []
@cmd.options[:system] = true
use_ui @ui do
@cmd.execute
end
err = @ui.error.split "\n"
assert_empty err
out = @ui.output.split "\n"
assert_equal "Installing RubyGems 8", out.shift
assert_equal "RubyGems system software updated", out.shift
assert_empty out
end
def test_execute_system_multiple
spec_fetcher do |fetcher|
fetcher.download "rubygems-update", 8 do |s|
@ -151,7 +177,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@ -185,7 +210,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@ -242,7 +266,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 8", out.shift
assert_equal "RubyGems system software updated", out.shift
@ -353,7 +376,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift

View file

@ -152,18 +152,18 @@ dependencies = [
[[package]]
name = "rb-sys"
version = "0.9.84"
version = "0.9.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3def04a96a36ef8681a2b2e26c01683b93a8630175c845fa06cab76c5a8c7ce0"
checksum = "7285f2a7b92f58ab198e3fd59a71d2861478f9c4642f41e83582385818941697"
dependencies = [
"rb-sys-build",
]
[[package]]
name = "rb-sys-build"
version = "0.9.84"
version = "0.9.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c017d134afd764dd43c2faa91aa50b698a3bb4ff30e83113da483c789e74be8c"
checksum = "71583945f94dabb6c0dfa63f1b71e929c1901e1e288ef3739ab8bed3b7069550"
dependencies = [
"bindgen",
"lazy_static",

View file

@ -7,4 +7,4 @@ edition = "2021"
crate-type = ["cdylib"]
[dependencies]
rb-sys = "0.9.84"
rb-sys = "0.9.86"

View file

@ -145,18 +145,18 @@ dependencies = [
[[package]]
name = "rb-sys"
version = "0.9.83"
version = "0.9.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e5b8d560b60790a3e60e56e73a8c7be88ac14e6af39fc82b5eca72c71753840"
checksum = "7285f2a7b92f58ab198e3fd59a71d2861478f9c4642f41e83582385818941697"
dependencies = [
"rb-sys-build",
]
[[package]]
name = "rb-sys-build"
version = "0.9.83"
version = "0.9.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2d2bfd00002007d7e9ad93d0397437933040caf452d260c26dbef5fd95ae1a6"
checksum = "71583945f94dabb6c0dfa63f1b71e929c1901e1e288ef3739ab8bed3b7069550"
dependencies = [
"bindgen",
"lazy_static",

View file

@ -7,4 +7,4 @@ edition = "2021"
crate-type = ["cdylib"]
[dependencies]
rb-sys = "0.9.83"
rb-sys = "0.9.86"

View file

@ -489,6 +489,17 @@ class TestGemRequire < Gem::TestCase
assert_equal %w[default-3.0], loaded_spec_names
end
def test_normal_gem_does_not_shadow_default_gem
default_gem_spec = new_default_spec("foo", "2.0", nil, "foo.rb")
install_default_gems(default_gem_spec)
normal_gem_spec = util_spec("fake-foo", "3.0", nil, "lib/foo.rb")
install_specs(normal_gem_spec)
assert_require "foo"
assert_equal %w[foo-2.0], loaded_spec_names
end
def test_normal_gems_with_overridden_load_error_message
normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb")
@ -529,6 +540,65 @@ class TestGemRequire < Gem::TestCase
assert_equal %w[default-3.0.0.rc2], loaded_spec_names
end
def test_default_gem_with_unresolved_gems_depending_on_it
my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb"
install_gem my_http_old
my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb"
install_default_gems my_http_default
faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" }
install_gem faraday_1
faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" }
install_gem faraday_2
chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
install_gem chef
assert_require "chef"
assert_require "my/http"
end
def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it
my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb"
install_gem my_http_old
my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb"
my_http_default_path = File.join(@tempdir, "default_gems", "lib", "my/http.rb")
install_default_gems my_http_default
File.write(my_http_default_path, 'require "my/http"')
faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" }
install_gem faraday_1
faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" }
install_gem faraday_2
chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
install_gem chef
assert_require "chef"
out, err = capture_output do
assert_require "my/http"
end
assert_empty out
circular_require_warning = false
err_lines = err.split("\n").reject do |line|
if line.include?("circular require")
circular_require_warning = true
elsif circular_require_warning # ignore backtrace lines for circular require warning
circular_require_warning = line.start_with?(/[\s]/)
end
end
assert_empty err_lines
end
def loaded_spec_names
Gem.loaded_specs.values.map(&:full_name).sort
end

View file

@ -13,7 +13,7 @@ gem "parallel", "~> 1.19"
gem "rspec-core", "~> 3.12"
gem "rspec-expectations", "~> 3.12"
gem "rspec-mocks", "~> 3.12"
gem "uri", "~> 0.12.0"
gem "uri", "~> 0.13.0"
group :doc do
gem "nronn", "~> 0.11.1", platform: :ruby

View file

@ -3,6 +3,7 @@
source "https://rubygems.org"
gem "rack", "~> 2.0"
gem "base64"
gem "webrick", "1.7.0"
gem "rack-test", "~> 1.1"
gem "compact_index", "~> 0.15.0"