summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2024-02-05 23:51:04 +0900
committerGitHub <noreply@github.com>2024-02-05 14:51:04 +0000
commitac526abcd6d82545b8dc3586efb55d75f45f7417 (patch)
tree437dbd39424f87611523feed739b788a4b4a118b
parent7f97e3540ce448b501bcbee15afac5f94bb22dd9 (diff)
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>
-rw-r--r--lib/bundler/compact_index_client/updater.rb8
-rw-r--r--lib/bundler/definition.rb12
-rw-r--r--lib/bundler/dsl.rb14
-rw-r--r--lib/bundler/man/bundle-config.14
-rw-r--r--lib/bundler/man/bundle-config.1.ronn4
-rw-r--r--lib/bundler/spec_set.rb81
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb9
-rw-r--r--lib/rubygems/commands/update_command.rb8
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb13
-rw-r--r--lib/rubygems/defaults.rb2
-rw-r--r--lib/rubygems/specification.rb2
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb24
-rw-r--r--spec/bundler/commands/install_spec.rb29
-rw-r--r--spec/bundler/commands/update_spec.rb2
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb14
-rw-r--r--spec/bundler/lock/lockfile_spec.rb40
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb2
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb3
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb2
-rw-r--r--spec/bundler/support/artifice/windows.rb2
-rw-r--r--spec/bundler/support/rubygems_ext.rb2
-rw-r--r--test/rubygems/helper.rb45
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb34
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock8
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml2
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock8
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml2
-rw-r--r--test/rubygems/test_require.rb70
-rw-r--r--tool/bundler/dev_gems.rb2
-rw-r--r--tool/bundler/test_gems.rb1
31 files changed, 323 insertions, 128 deletions
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 84a606dc34..36f6b81db8 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -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!('"')
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 9b905db1f9..0b0e63f77e 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -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
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 1eca749617..1460b9f52f 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -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 " \
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 8090e03f7d..c5a976da46 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -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\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index b935329b4e..587d31dbad 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -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
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index ceaac2cec5..cc649abaf8 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -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
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index a0ef931d07..05b6c66ce4 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -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
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index fa3da5cc1a..d4138b2d8f 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -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
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 10ae6d9a93..3d6fecaa40 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -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
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index bbd7852e92..073966b696 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -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
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index 00dc5707c3..19cf306f88 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -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
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index a0c7faa133..169002d7c7 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -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
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index 51b838d2d2..6eed88ca9e 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -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)
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index 7c016ff3d8..f0c9aaea8e 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -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"
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 59e7c3867c..2bde5a1586 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -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
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index e3c891e4c1..1375d8cab1 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -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
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 5e996f5aac..7f664abc4d 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -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|
diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb
index d8ab6b65bc..b1ed1964c8 100644
--- a/spec/bundler/support/artifice/endpoint_500.rb
+++ b/spec/bundler/support/artifice/endpoint_500.rb
@@ -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"
diff --git a/spec/bundler/support/artifice/helpers/compact_index.rb b/spec/bundler/support/artifice/helpers/compact_index.rb
index cf8bb34c5a..a803a2d30a 100644
--- a/spec/bundler/support/artifice/helpers/compact_index.rb
+++ b/spec/bundler/support/artifice/helpers/compact_index.rb
@@ -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
diff --git a/spec/bundler/support/artifice/helpers/endpoint.rb b/spec/bundler/support/artifice/helpers/endpoint.rb
index be52df6936..83ba1be0fc 100644
--- a/spec/bundler/support/artifice/helpers/endpoint.rb
+++ b/spec/bundler/support/artifice/helpers/endpoint.rb
@@ -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"
diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb
index 4d90e0a426..fea991c071 100644
--- a/spec/bundler/support/artifice/windows.rb
+++ b/spec/bundler/support/artifice/windows.rb
@@ -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"
diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb
index c242e3a528..0d1ad2d528 100644
--- a/spec/bundler/support/rubygems_ext.rb
+++ b/spec/bundler/support/rubygems_ext.rb
@@ -86,7 +86,7 @@ module Spec
puts success_message
puts
else
- system("git status --porcelain")
+ system("git diff")
puts
puts error_message
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index d259fbde1b..e6774ded38 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -105,39 +105,32 @@ 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"
+ require "tempfile"
- captured_stdout = Tempfile.new("out")
- captured_stderr = Tempfile.new("err")
+ captured_stdout = Tempfile.new("out")
+ captured_stderr = Tempfile.new("err")
- orig_stdout = $stdout.dup
- orig_stderr = $stderr.dup
- $stdout.reopen captured_stdout
- $stderr.reopen captured_stderr
+ orig_stdout = $stdout.dup
+ orig_stderr = $stderr.dup
+ $stdout.reopen captured_stdout
+ $stderr.reopen captured_stderr
- yield
+ yield
- $stdout.rewind
- $stderr.rewind
+ $stdout.rewind
+ $stderr.rewind
- return captured_stdout.read, captured_stderr.read
- ensure
- $stdout.reopen orig_stdout
- $stderr.reopen orig_stderr
+ [captured_stdout.read, captured_stderr.read]
+ ensure
+ $stdout.reopen orig_stdout
+ $stderr.reopen orig_stderr
- orig_stdout.close
- orig_stderr.close
- captured_stdout.close!
- captured_stderr.close!
- end
+ orig_stdout.close
+ orig_stderr.close
+ captured_stdout.close!
+ captured_stderr.close!
end
##
diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb
index 324bd9c747..2683840f2e 100644
--- a/test/rubygems/test_gem_commands_update_command.rb
+++ b/test/rubygems/test_gem_commands_update_command.rb
@@ -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
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock
index 0937f71973..aa9587b231 100644
--- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock
@@ -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",
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml
index 6883495282..56a4188f15 100644
--- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml
@@ -7,4 +7,4 @@ edition = "2021"
crate-type = ["cdylib"]
[dependencies]
-rb-sys = "0.9.84"
+rb-sys = "0.9.86"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
index e65b28607d..8c394aec20 100644
--- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
@@ -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",
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
index 26185e0e3c..39b2ae3919 100644
--- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
@@ -7,4 +7,4 @@ edition = "2021"
crate-type = ["cdylib"]
[dependencies]
-rb-sys = "0.9.83"
+rb-sys = "0.9.86"
diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb
index fc5f219490..30a4a477f9 100644
--- a/test/rubygems/test_require.rb
+++ b/test/rubygems/test_require.rb
@@ -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
diff --git a/tool/bundler/dev_gems.rb b/tool/bundler/dev_gems.rb
index 5e5ba94ec2..cb4b556d2f 100644
--- a/tool/bundler/dev_gems.rb
+++ b/tool/bundler/dev_gems.rb
@@ -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
diff --git a/tool/bundler/test_gems.rb b/tool/bundler/test_gems.rb
index aa1cfd09a5..32cb6b34ee 100644
--- a/tool/bundler/test_gems.rb
+++ b/tool/bundler/test_gems.rb
@@ -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"