summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2021-03-10 12:08:20 +0900
committerNARUSE, Yui <nurse@users.noreply.github.com>2021-03-11 17:24:52 +0900
commit0476ce0370c1ee56de690d43c15d5e8d7893dedd (patch)
tree72590a5a0211c53d431cfab4e3b008dbcc3df6e8
parent7efc7afcae6720e1af7ab49986d789b6f9d6fe0a (diff)
Merge RubyGems-3.2.14 and Bundler-2.2.14
-rw-r--r--lib/bundler/compact_index_client/updater.rb2
-rw-r--r--lib/bundler/definition.rb22
-rw-r--r--lib/bundler/dsl.rb9
-rw-r--r--lib/bundler/installer/parallel_installer.rb14
-rw-r--r--lib/bundler/lockfile_parser.rb18
-rw-r--r--lib/bundler/plugin/api/source.rb7
-rw-r--r--lib/bundler/source.rb6
-rw-r--r--lib/bundler/source/metadata.rb4
-rw-r--r--lib/bundler/source/rubygems.rb24
-rw-r--r--lib/bundler/source_list.rb18
-rw-r--r--lib/bundler/spec_set.rb2
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/platform.rb10
-rw-r--r--lib/rubygems/remote_fetcher.rb11
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb21
-rw-r--r--spec/bundler/bundler/source_list_spec.rb21
-rw-r--r--spec/bundler/commands/lock_spec.rb2
-rw-r--r--spec/bundler/install/deploy_spec.rb20
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb506
-rw-r--r--spec/bundler/install/gems/flex_spec.rb32
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb45
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb17
-rw-r--r--spec/bundler/lock/lockfile_spec.rb35
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb44
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock5
-rw-r--r--spec/bundler/spec_helper.rb2
-rw-r--r--spec/bundler/support/builders.rb44
-rw-r--r--spec/bundler/support/helpers.rb2
-rw-r--r--spec/bundler/support/matchers.rb51
-rw-r--r--test/rubygems/test_gem_platform.rb29
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb38
32 files changed, 705 insertions, 360 deletions
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 7959e5c089..9e0180fac7 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -54,7 +54,7 @@ module Bundler
if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
else
- local_temp_path.open("w") {|f| f << content }
+ local_temp_path.open("wb") {|f| f << content }
end
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index a09d661a07..686721cd32 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -106,6 +106,17 @@ module Bundler
@locked_platforms = []
end
+ @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
+ @disable_multisource = @locked_gem_sources.all?(&:disable_multisource?)
+
+ unless @disable_multisource
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. You should run `bundle update` or generate your lockfile from scratch."
+
+ Bundler::SharedHelpers.major_deprecation 2, msg
+
+ @sources.merged_gem_lockfile_sections!
+ end
+
@unlock[:gems] ||= []
@unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -145,6 +156,10 @@ module Bundler
end
end
+ def disable_multisource?
+ @disable_multisource
+ end
+
def resolve_with_cache!
raise "Specs already loaded" if @specs
sources.cached!
@@ -530,6 +545,9 @@ module Bundler
attr_reader :sources
private :sources
+ attr_reader :locked_gem_sources
+ private :locked_gem_sources
+
def nothing_changed?
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
end
@@ -654,10 +672,8 @@ module Bundler
end
def converge_rubygems_sources
- return false if Bundler.feature_flag.disable_multisource?
+ return false if disable_multisource?
- # Get the RubyGems sources from the Gemfile.lock
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
return false if locked_gem_sources.empty?
# Get the RubyGems remotes from the Gemfile
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 23fba99ffa..313d1a9a41 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -460,19 +460,16 @@ repo_name ||= user_name
@sources.add_rubygems_remote(source)
end
- if Bundler.feature_flag.disable_multisource?
+ if Bundler.feature_flag.bundler_3_mode?
msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \
- "should come from that source. To downgrade this error to a warning, run " \
- "`bundle config unset disable_multisource`"
+ "should come from that source"
raise GemfileEvalError, msg
else
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
- "a block to indicate which gems should come from the secondary source. " \
- "To upgrade this warning to an error, run `bundle config set --local " \
- "disable_multisource true`."
+ "a block to indicate which gems should come from the secondary source."
end
end
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
index a6d1de29e6..c3bf5843b7 100644
--- a/lib/bundler/installer/parallel_installer.rb
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -27,13 +27,8 @@ module Bundler
state == :failed
end
- def installation_attempted?
- installed? || failed?
- end
-
- # Only true when spec in neither installed nor already enqueued
def ready_to_enqueue?
- !enqueued? && !installation_attempted?
+ state == :none
end
def has_post_install_message?
@@ -93,6 +88,11 @@ module Bundler
def call
check_for_corrupt_lockfile
+ if @rake
+ do_install(@rake, 0)
+ Gem::Specification.reset
+ end
+
if @size > 1
install_with_worker
else
@@ -217,8 +217,6 @@ module Bundler
# are installed.
def enqueue_specs
@specs.select(&:ready_to_enqueue?).each do |spec|
- next if @rake && !@rake.installed? && spec.name != @rake.name
-
if spec.dependencies_installed? @specs
spec.state = :enqueued
worker_pool.enq spec
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 058d353bbe..f87faff70c 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -131,18 +131,8 @@ module Bundler
@sources << @current_source
end
when GEM
- source_remotes = Array(@opts["remote"])
-
- if source_remotes.size == 1
- @opts["remotes"] = @opts.delete("remote")
- @current_source = TYPES[@type].from_lock(@opts)
- else
- source_remotes.each do |url|
- rubygems_aggregate.add_remote(url)
- end
- @current_source = rubygems_aggregate
- end
-
+ @opts["remotes"] = Array(@opts.delete("remote")).reverse
+ @current_source = TYPES[@type].from_lock(@opts)
@sources << @current_source
when PLUGIN
@current_source = Plugin.source_from_lock(@opts)
@@ -245,9 +235,5 @@ module Bundler
def parse_ruby(line)
@ruby_version = line.strip
end
-
- def rubygems_aggregate
- @rubygems_aggregate ||= Source::Rubygems.new
- end
end
end
diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb
index e1f0826874..d70a16f4bc 100644
--- a/lib/bundler/plugin/api/source.rb
+++ b/lib/bundler/plugin/api/source.rb
@@ -140,6 +140,13 @@ module Bundler
end
end
+ # Set internal representation to fetch the gems/specs locally.
+ #
+ # When this is called, the source should try to fetch the specs and
+ # install from the local system.
+ def local!
+ end
+
# Set internal representation to fetch the gems/specs from remote.
#
# When this is called, the source should try to fetch the specs and
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index be00143f5a..a3f4b09cce 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -33,6 +33,12 @@ module Bundler
spec.source == self
end
+ def local!; end
+
+ def cached!; end
+
+ def remote!; end
+
# it's possible that gems from one source depend on gems from some
# other source, so now we download gemspecs and iterate over those
# dependencies, looking for gems we don't have info on yet.
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 0867879861..50b65ce0ea 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -33,10 +33,6 @@ module Bundler
end
end
- def cached!; end
-
- def remote!; end
-
def options
{}
end
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 5b89b1645d..cede580b0a 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -20,17 +20,29 @@ module Bundler
@dependency_names = []
@allow_remote = false
@allow_cached = false
+ @allow_local = options["allow_local"] || false
@caches = [cache_path, *Bundler.rubygems.gem_cache]
- Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
+ Array(options["remotes"]).reverse_each {|r| add_remote(r) }
+ end
+
+ def local!
+ return if @allow_local
+
+ @specs = nil
+ @allow_local = true
end
def remote!
+ return if @allow_remote
+
@specs = nil
@allow_remote = true
end
def cached!
+ return if @allow_cached
+
@specs = nil
@allow_cached = true
end
@@ -49,8 +61,12 @@ module Bundler
o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
end
+ def disable_multisource?
+ @remotes.size <= 1
+ end
+
def can_lock?(spec)
- return super if Bundler.feature_flag.disable_multisource?
+ return super if disable_multisource?
spec.source.is_a?(Rubygems)
end
@@ -87,7 +103,7 @@ module Bundler
# small_idx.use large_idx.
idx = @allow_remote ? remote_specs.dup : Index.new
idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
- idx.use(installed_specs, :override_dupes)
+ idx.use(installed_specs, :override_dupes) if @allow_local
idx
end
end
@@ -365,7 +381,7 @@ module Bundler
def cached_specs
@cached_specs ||= begin
- idx = installed_specs.dup
+ idx = @allow_local ? installed_specs.dup : Index.new
Dir["#{cache_path}/*.gem"].each do |gemfile|
next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 44b167ca3e..51698af46e 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -9,7 +9,7 @@ module Bundler
:metadata_source
def global_rubygems_source
- @global_rubygems_source ||= rubygems_aggregate_class.new
+ @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true)
end
def initialize
@@ -20,6 +20,16 @@ module Bundler
@global_path_source = nil
@rubygems_sources = []
@metadata_source = Source::Metadata.new
+
+ @disable_multisource = true
+ end
+
+ def disable_multisource?
+ @disable_multisource
+ end
+
+ def merged_gem_lockfile_sections!
+ @disable_multisource = false
end
def add_path_source(options = {})
@@ -47,7 +57,7 @@ module Bundler
end
def global_rubygems_source=(uri)
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
+ @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri, "allow_local" => true)
end
def add_rubygems_remote(uri)
@@ -77,7 +87,7 @@ module Bundler
def lock_sources
lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
- if Bundler.feature_flag.disable_multisource?
+ if disable_multisource?
lock_sources + rubygems_sources.sort_by(&:to_s)
else
lock_sources << combine_rubygems_sources
@@ -94,7 +104,7 @@ module Bundler
end
end
- replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
+ replacement_rubygems = !disable_multisource? &&
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
@global_rubygems_source = replacement_rubygems if replacement_rubygems
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 399c91fea5..dfc3114c41 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -82,6 +82,7 @@ module Bundler
materialized.map! do |s|
next s unless s.is_a?(LazySpecification)
s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
+ s.source.local!
spec = s.__materialize__
unless spec
unless missing_specs
@@ -102,6 +103,7 @@ module Bundler
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
+ s.source.local!
s.source.remote!
spec = s.__materialize__
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 46c5ecb2f3..5e71e22df8 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.2.13".freeze
+ VERSION = "2.2.14".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 609517e1e7..682360264a 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.2.13".freeze
+ VERSION = "3.2.14".freeze
end
# Must be first since it unloads the prelude from 1.9.2
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index e01d0494d6..fd1c0a62ac 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -66,7 +66,7 @@ class Gem::Platform
when String then
arch = arch.split '-'
- if arch.length > 2 and arch.last !~ /\d+(\.\d+)?$/ # reassemble x86-linux-{libc}
+ if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
extra = arch.pop
arch.last << "-#{extra}"
end
@@ -146,8 +146,7 @@ class Gem::Platform
##
# Does +other+ match this platform? Two platforms match if they have the
# same CPU, or either has a CPU of 'universal', they have the same OS, and
- # they have the same version, or either has no version (except for 'linux'
- # where the version is the libc name, with no version standing for 'gnu')
+ # they have the same version, or either has no version.
#
# Additionally, the platform will match if the local CPU is 'arm' and the
# other CPU starts with "arm" (for generic ARM family support).
@@ -163,10 +162,7 @@ class Gem::Platform
@os == other.os and
# version
- (
- (@os != 'linux' and (@version.nil? or other.version.nil?)) or
- @version == other.version
- )
+ (@version.nil? or other.version.nil? or @version == other.version)
end
##
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 7ac334d30d..da7b46e06e 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -51,6 +51,7 @@ class Gem::RemoteFetcher
class UnknownHostError < FetchError
end
+ deprecate_constant(:UnknownHostError)
@fetcher = nil
@@ -262,15 +263,9 @@ class Gem::RemoteFetcher
end
data
- rescue Timeout::Error
- raise UnknownHostError.new('timed out', uri)
- rescue IOError, SocketError, SystemCallError,
+ rescue Timeout::Error, IOError, SocketError, SystemCallError,
*(OpenSSL::SSL::SSLError if Gem::HAVE_OPENSSL) => e
- if e.message =~ /getaddrinfo/
- raise UnknownHostError.new('no such name', uri)
- else
- raise FetchError.new("#{e.class}: #{e}", uri)
- end
+ raise FetchError.new("#{e.class}: #{e}", uri)
end
def fetch_s3(uri, mtime = nil, head = false)
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index d8bb15df7e..cecaddfba4 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -46,4 +46,25 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
end.to raise_error(Bundler::PermissionError)
end
end
+
+ context "when receiving non UTF-8 data and default internal encoding set to ASCII" do
+ let(:response) { double(:response, :body => "\x8B".b) }
+
+ it "works just fine" do
+ old_verbose = $VERBOSE
+ previous_internal_encoding = Encoding.default_internal
+
+ begin
+ $VERBOSE = false
+ Encoding.default_internal = "ASCII"
+ expect(response).to receive(:[]).with("ETag") { nil }
+ expect(fetcher).to receive(:call) { response }
+
+ updater.update(local_path, remote_path)
+ ensure
+ Encoding.default_internal = previous_internal_encoding
+ $VERBOSE = old_verbose
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb
index 3a0691b959..0c40ba8a77 100644
--- a/spec/bundler/bundler/source_list_spec.rb
+++ b/spec/bundler/bundler/source_list_spec.rb
@@ -372,26 +372,7 @@ RSpec.describe Bundler::SourceList do
source_list.add_git_source("uri" => "git://first-git.org/path.git")
end
- it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do
- expect(source_list.lock_sources).to eq [
- Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"),
- ASourcePlugin.new("uri" => "https://second-plugin.org/random"),
- ASourcePlugin.new("uri" => "https://third-bar.org/foo"),
- Bundler::Source::Path.new("path" => "/first/path/to/gem"),
- Bundler::Source::Path.new("path" => "/second/path/to/gem"),
- Bundler::Source::Path.new("path" => "/third/path/to/gem"),
- Bundler::Source::Rubygems.new("remotes" => [
- "https://duplicate-rubygems.org",
- "https://first-rubygems.org",
- "https://second-rubygems.org",
- "https://third-rubygems.org",
- ]),
- ]
- end
-
- it "returns all sources, without combining rubygems sources", :bundler => "3" do
+ it "returns all sources, without combining rubygems sources" do
expect(source_list.lock_sources).to eq [
Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 7724170a63..264af30f6c 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe "bundle lock" do
it "does not fetch remote specs when using the --local option" do
bundle "lock --update --local", :raise_on_error => false
- expect(err).to match(/sources listed in your Gemfile|installed locally/)
+ expect(err).to match(/installed locally/)
end
it "works with --gemfile flag" do
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index adc835eb95..3e3bbe816f 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -126,21 +126,21 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config --local path vendor/bundle"
bundle "install"
gemfile <<-G
- source "http://user_name:password@localgemserver.test/"
- gem "rack"
+ source "http://user_name:password@localgemserver.test/"
+ gem "rack"
G
lockfile <<-G
- GEM
- remote: http://localgemserver.test/
- specs:
- rack (1.0.0)
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rack (1.0.0)
- PLATFORMS
- #{local}
+ PLATFORMS
+ #{local}
- DEPENDENCIES
- rack
+ DEPENDENCIES
+ rack
G
bundle "config set --local deployment true"
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 7916b83977..0f95bfac8f 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -141,156 +141,159 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "when a pinned gem has an indirect dependency" do
+ context "when a pinned gem has an indirect dependency in the pinned source" do
before do
build_repo gem_repo3 do
build_gem "depends_on_rack", "1.0.1" do |s|
s.add_dependency "rack"
end
end
- end
- context "when the indirect dependency is in the pinned source" do
- before do
- # we need a working rack gem in repo3
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
- end
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "depends_on_rack"
- end
- G
+ # we need a working rack gem in repo3
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0"
end
- context "and not in any other sources" do
- before do
- build_repo(gem_repo2) {}
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "depends_on_rack"
end
+ G
+ end
- it "installs from the same source without any warning" do
- bundle :install
- expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
- end
+ context "and not in any other sources" do
+ before do
+ build_repo(gem_repo2) {}
end
- context "and in another source" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ it "installs from the same source without any warning" do
+ bundle :install
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ end
+ end
+
+ context "and in another source" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
+ end
- it "installs from the same source without any warning" do
- bundle :install
+ it "installs from the same source without any warning" do
+ bundle :install
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
- # In https://github.com/bundler/bundler/issues/3585 this failed
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle :install
+ # In https://github.com/bundler/bundler/issues/3585 this failed
+ # when there is already a lock file, and the gems are missing, so try again
+ system_gems []
+ bundle :install
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
- end
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
end
end
+ end
- context "when the indirect dependency is in a different source" do
- before do
- # In these tests, we need a working rack gem in repo2 and not repo3
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0"
+ context "when a pinned gem has an indirect dependency in a different source" do
+ before do
+ # In these tests, we need a working rack gem in repo2 and not repo3
+
+ build_repo gem_repo3 do
+ build_gem "depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "rack"
end
end
- context "and not in any other sources" do
- before do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "depends_on_rack"
- end
- G
- end
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
+ end
+ end
- it "installs from the other source without any warning" do
- expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
+ context "and not in any other sources" do
+ before do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "depends_on_rack"
+ end
+ G
end
- context "and in yet another source" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "depends_on_rack"
- end
- G
- end
+ it "installs from the other source without any warning" do
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ end
+ end
- it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
- bundle :install
- expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
+ context "and in yet another source" do
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "depends_on_rack"
+ end
+ G
+ end
- it "fails", :bundler => "3" do
- bundle :install, :raise_on_error => false
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4)
- end
+ it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
+ bundle :install
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end
- context "and only the dependency is pinned" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ it "fails", :bundler => "3" do
+ bundle :install, :raise_on_error => false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
+ end
+ end
+
+ context "and only the dependency is pinned" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack
- source "#{file_uri_for(gem_repo2)}" # contains broken rack
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack
+ source "#{file_uri_for(gem_repo2)}" # contains broken rack
- gem "depends_on_rack" # installed from gem_repo3
- gem "rack", :source => "#{file_uri_for(gem_repo1)}"
- G
- end
+ gem "depends_on_rack" # installed from gem_repo3
+ gem "rack", :source => "#{file_uri_for(gem_repo1)}"
+ G
+ end
- it "installs the dependency from the pinned source without warning", :bundler => "< 3" do
- bundle :install
+ it "installs the dependency from the pinned source without warning", :bundler => "< 3" do
+ bundle :install
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- # In https://github.com/rubygems/bundler/issues/3585 this failed
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle :install
+ # In https://github.com/rubygems/bundler/issues/3585 this failed
+ # when there is already a lock file, and the gems are missing, so try again
+ system_gems []
+ bundle :install
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ end
- it "fails", :bundler => "3" do
- bundle :install, :raise_on_error => false
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4)
- end
+ it "fails", :bundler => "3" do
+ bundle :install, :raise_on_error => false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
end
end
end
@@ -511,9 +514,149 @@ RSpec.describe "bundle install with gems on multiple sources" do
L
end
- it "upgrades gems when running bundle update, without printing any warnings or errors" do
+ it "does not install newer versions or generate lockfile changes when running bundle install, and warns", :bundler => "< 3" do
+ initial_lockfile = lockfile
+
+ bundle :install
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(the_bundle).to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).not_to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).not_to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.8")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9")
+
+ expect(lockfile).to eq(initial_lockfile)
+ end
+
+ it "fails when running bundle install", :bundler => "3" do
+ initial_lockfile = lockfile
+
+ bundle :install, :raise_on_error => false
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(lockfile).to eq(initial_lockfile)
+ end
+
+ it "splits sections and upgrades gems when running bundle update, and doesn't warn" do
bundle "update --all"
expect(err).to be_empty
+
+ expect(the_bundle).not_to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).not_to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ activesupport (6.1.2.1)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
+ concurrent-ruby (1.1.9)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ tzinfo (2.0.4)
+ concurrent-ruby (~> 1.0)
+ zeitwerk (2.4.2)
+
+ GEM
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "it keeps the currrent lockfile format and upgrades the requested gem when running bundle update with an argument, and warns", :bundler => "< 3" do
+ bundle "update concurrent-ruby"
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(the_bundle).to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).not_to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).not_to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ activesupport (6.0.3.4)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ zeitwerk (~> 2.2, >= 2.2.2)
+ concurrent-ruby (1.1.9)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.9)
+ thread_safe (~> 0.1)
+ zeitwerk (2.4.2)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "fails when running bundle update with an argument", :bundler => "3" do
+ initial_lockfile = lockfile
+
+ bundle "update concurrent-ruby", :raise_on_error => false
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(lockfile).to eq(initial_lockfile)
end
end
end
@@ -551,7 +694,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source ", :bundler => "< 3" do
+ context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source " do
before do
build_repo gem_repo3 do
build_gem "handsoap", "0.2.5.5" do |s|
@@ -578,12 +721,38 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs from the proper sources without any warnings or errors" do
+ it "installs from the default source without any warnings or errors and generates a proper lockfile" do
+ expected_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ nokogiri (1.11.1)
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ GEM
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ handsoap (0.2.5.5)
+ nokogiri (>= 1.2.3)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ handsoap!
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
bundle "install --verbose"
expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3")
expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2")
+ expect(lockfile).to eq(expected_lockfile)
# Even if the gems are already installed
FileUtils.rm bundled_app_lock
@@ -592,6 +761,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3")
expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2")
+ expect(lockfile).to eq(expected_lockfile)
end
end
@@ -619,6 +789,9 @@ RSpec.describe "bundle install with gems on multiple sources" do
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo1)}
+ specs:
+
+ GEM
remote: #{file_uri_for(gem_repo3)}
specs:
rack (0.9.1)
@@ -644,6 +817,84 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
+ context "with a lockfile with aggregated rubygems sources" do
+ let(:aggregate_gem_section_lockfile) do
+ <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ let(:split_gem_section_lockfile) do
+ <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ GEM
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo gem_repo3 do
+ build_gem "rack", "0.9.1"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem 'rack'
+ end
+ G
+
+ lockfile aggregate_gem_section_lockfile
+ end
+
+ it "installs the existing lockfile but prints a warning", :bundler => "< 3" do
+ bundle "config set --local deployment true"
+
+ bundle "install"
+
+ expect(lockfile).to eq(aggregate_gem_section_lockfile)
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+ expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
+ end
+
+ it "refuses to install the existing lockfile and prints an error", :bundler => "3" do
+ bundle "config set --local deployment true"
+
+ bundle "install", :raise_on_error =>false
+
+ expect(lockfile).to eq(aggregate_gem_section_lockfile)
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+ expect(out).to be_empty
+ end
+ end
+
context "with a path gem in the same Gemfile" do
before do
build_lib "foo"
@@ -825,13 +1076,34 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "keeps the old version", :bundler => "< 3" do
- expect(the_bundle).to include_gems("rack 1.0.0")
+ it "installs the higher version in the new repo" do
+ expect(the_bundle).to include_gems("rack 1.2")
+ end
+ end
+
+ it "doesn't update version when a gem uses a source block but a higher version from another source is already installed locally" do
+ build_repo2 do
+ build_gem "example", "0.1.0"
end
- it "installs the higher version in the new repo", :bundler => "3" do
- expect(the_bundle).to include_gems("rack 1.2")
+ build_repo4 do
+ build_gem "example", "1.0.2"
end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "example", :source => "#{file_uri_for(gem_repo2)}"
+ G
+
+ bundle "info example"
+ expect(out).to include("example (0.1.0)")
+
+ system_gems "example-1.0.2", :path => default_bundle_path, :gem_repo => gem_repo4
+
+ bundle "update example --verbose"
+ expect(out).not_to include("Using example 1.0.2")
+ expect(out).to include("Using example 0.1.0")
end
context "when a gem is available from multiple ambiguous sources", :bundler => "3" do
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index 7ab0ded26d..326ec51214 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -245,37 +245,7 @@ RSpec.describe "bundle flex_install" do
end
describe "when adding a new source" do
- it "updates the lockfile", :bundler => "< 3" do
- build_repo2
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- G
-
- lockfile_should_be <<-L
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
- it "updates the lockfile", :bundler => "3" do
+ it "updates the lockfile" do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 035ed9a7f3..94fac0052c 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -3,6 +3,32 @@
RSpec.describe "bundle install with install-time dependencies" do
before do
build_repo2 do
+ build_gem "with_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
+ f.puts "IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ build_gem "another_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
+ f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
# Test complicated gem dependencies for install
build_gem "net_a" do |s|
s.add_dependency "net_b"
@@ -55,6 +81,25 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to eq("YES\nYES")
end
+ it "installs gems with implicit rake dependencies without rake previously installed" do
+ with_path_as("") do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "with_implicit_rake_dep"
+ gem "another_implicit_rake_dep"
+ gem "rake"
+ G
+ end
+
+ run <<-R
+ require 'implicit_rake_dep'
+ require 'another_implicit_rake_dep'
+ puts IMPLICIT_RAKE_DEP
+ puts ANOTHER_IMPLICIT_RAKE_DEP
+ R
+ expect(out).to eq("YES\nYES")
+ end
+
it "installs gems with a dependency with no type" do
skip "incorrect data check error" if Gem.win_platform?
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
index ff73b4a1fa..3e5d38ea4c 100644
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ b/spec/bundler/install/gems/sudo_spec.rb
@@ -49,8 +49,23 @@ RSpec.describe "when using sudo", :sudo => true do
end
it "installs rake and a gem dependent on rake in the same session" do
+ build_repo2 do
+ build_gem "another_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
+ f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+ end
+
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rake"
gem "another_implicit_rake_dep"
G
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index d3591cd62a..639ccb87ea 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -318,40 +318,7 @@ RSpec.describe "the lockfile format" do
G
end
- it "generates a lockfile without credentials for a configured source", :bundler => "< 3" do
- bundle "config set http://localgemserver.test/ user:pass"
-
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
- source "http://localgemserver.test/" do
-
- end
-
- source "http://user:pass@othergemserver.test/" do
- gem "rack-obama", ">= 1.0"
- end
- G
-
- lockfile_should_be <<-G
- GEM
- remote: http://localgemserver.test/
- remote: http://user:pass@othergemserver.test/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack-obama (>= 1.0)!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a lockfile without credentials for a configured source", :bundler => "3" do
+ it "generates a lockfile without credentials for a configured source" do
bundle "config set http://localgemserver.test/ user:pass"
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index 0758d29746..7dbb80af80 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -383,15 +383,53 @@ RSpec.describe "major deprecations" do
"Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
- "a block to indicate which gems should come from the secondary source. " \
- "To upgrade this warning to an error, run `bundle config set --local " \
- "disable_multisource true`."
+ "a block to indicate which gems should come from the secondary source."
)
end
pending "fails with a helpful error", :bundler => "3"
end
+ context "bundle install with a lockfile with a single rubygems section with multiple remotes" do
+ before do
+ build_repo gem_repo3 do
+ build_gem "rack", "0.9.1"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem 'rack'
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "shows a deprecation", :bundler => "< 3" do
+ bundle "install"
+
+ expect(deprecations).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. You should run `bundle update` or generate your lockfile from scratch.")
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
context "when Bundler.setup is run in a ruby script" do
before do
create_file "gems.rb"
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
index 6945be3ed2..05bcb877db 100644
--- a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -6,7 +6,7 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- jruby-jars (9.2.14.0)
+ jruby-jars (9.2.16.0)
jruby-rack (1.1.21)
rake (13.0.1)
rubyzip (1.3.0)
@@ -19,6 +19,7 @@ GEM
PLATFORMS
java
ruby
+ universal-java-11
DEPENDENCIES
demo!
@@ -26,4 +27,4 @@ DEPENDENCIES
warbler (~> 2.0)
BUNDLED WITH
- 2.2.0.rc.2
+ 2.3.0.dev
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 68d8537715..6587ce5d55 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -89,6 +89,8 @@ RSpec.configure do |config|
end
config.before :all do
+ check_test_gems!
+
build_repo1
reset_paths!
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index c76c3f505e..d593ced27e 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -30,7 +30,11 @@ module Spec
end
def build_repo1
+ rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
+
build_repo gem_repo1 do
+ FileUtils.cp rake_path, "#{gem_repo1}/gems/"
+
build_gem "rack", %w[0.9.1 1.0.0] do |s|
s.executables = "rackup"
s.post_install_message = "Rack's post install message"
@@ -150,32 +154,6 @@ module Spec
build_gem "duradura", "7.0"
- build_gem "with_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
- f.puts "IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
- build_gem "another_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
- f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
build_gem "very_simple_binary", &:add_c_extension
build_gem "simple_binary", &:add_c_extension
@@ -255,6 +233,13 @@ module Spec
def build_repo(path, &blk)
return if File.directory?(path)
+
+ FileUtils.mkdir_p("#{path}/gems")
+
+ update_repo(path, &blk)
+ end
+
+ def check_test_gems!
rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
if rake_path.nil?
@@ -263,14 +248,9 @@ module Spec
rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
end
- if rake_path
- FileUtils.mkdir_p("#{path}/gems")
- FileUtils.cp rake_path, "#{path}/gems/"
- else
+ if rake_path.nil?
abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again."
end
-
- update_repo(path, &blk)
end
def update_repo(path)
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index a7cc1ce810..7e2e92a1ec 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -130,7 +130,7 @@ module Spec
def ruby(ruby, options = {})
ruby_cmd = build_ruby_cmd
- escaped_ruby = RUBY_PLATFORM == "java" ? ruby.shellescape.dump : ruby.shellescape
+ escaped_ruby = ruby.shellescape
sys_exec(%(#{ruby_cmd} -w -e #{escaped_ruby}), options)
end
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 5d129ed849..1613662981 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -114,30 +114,49 @@ module Spec
match do
opts = names.last.is_a?(Hash) ? names.pop : {}
source = opts.delete(:source)
- groups = Array(opts[:groups])
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
opts[:raise_on_error] = false
- groups << opts
- @errors = names.map do |name|
- name, version, platform = name.split(/\s+/)
+ @errors = names.map do |full_name|
+ name, version, platform = full_name.split(/\s+/)
require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
- code = []
- code << "require '#{require_path}.rb'"
- code << "puts #{version_const}"
- run code.join("; "), *groups
- actual_version, actual_platform = out.strip.split(/\s+/, 2)
- unless Gem::Version.new(actual_version) == Gem::Version.new(version)
+ source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
+ ruby <<~R, opts
+ require '#{lib_dir}/bundler'
+ Bundler.setup(#{groups})
+
+ require '#{require_path}.rb'
+ actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
+ unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
+ puts actual_version
+ exit 64
+ end
+ unless actual_platform.to_s == '#{platform}'
+ puts actual_platform
+ exit 65
+ end
+ require '#{require_path}/source'
+ exit 0 if #{source.nil?}
+ actual_source = #{source_const}
+ unless actual_source == '#{source}'
+ puts actual_source
+ exit 66
+ end
+ R
+ next if exitstatus == 0
+ if exitstatus == 64
+ actual_version = out.split("\n").last
next "#{name} was expected to be at version #{version} but was #{actual_version}"
end
- unless actual_platform == platform
+ if exitstatus == 65
+ actual_platform = out.split("\n").last
next "#{name} was expected to be of platform #{platform} but was #{actual_platform}"
end
- next unless source
- source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
- run "require '#{require_path}/source'; puts #{source_const}", *groups
- unless out.strip == source
- next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{out}`"
+ if exitstatus == 66
+ actual_source = out.split("\n").last
+ next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{actual_source}`"
end
+ next "Command to check forgem inclusion of gem #{full_name} failed"
end.compact
@errors.empty?
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index ad7285c082..84754402ad 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -134,9 +134,7 @@ class TestGemPlatform < Gem::TestCase
'i386-solaris2.8' => ['x86', 'solaris', '2.8'],
'mswin32' => ['x86', 'mswin32', nil],
'x86_64-linux' => ['x86_64', 'linux', nil],
- 'x86_64-linux-gnu' => ['x86_64', 'linux', nil],
'x86_64-linux-musl' => ['x86_64', 'linux', 'musl'],
- 'x86_64-linux-uclibc' => ['x86_64', 'linux', 'uclibc'],
'x86_64-openbsd3.9' => ['x86_64', 'openbsd', '3.9'],
'x86_64-openbsd4.0' => ['x86_64', 'openbsd', '4.0'],
'x86_64-openbsd' => ['x86_64', 'openbsd', nil],
@@ -145,7 +143,6 @@ class TestGemPlatform < Gem::TestCase
test_cases.each do |arch, expected|
platform = Gem::Platform.new arch
assert_equal expected, platform.to_a, arch.inspect
- assert_equal expected, Gem::Platform.new(platform.to_s).to_a, arch.inspect
end
end
@@ -264,32 +261,6 @@ class TestGemPlatform < Gem::TestCase
assert((with_x86_arch === with_nil_arch), 'x86 =~ nil')
end
- def test_nil_version_is_treated_as_any_version
- x86_darwin_8 = Gem::Platform.new 'i686-darwin8.0'
- x86_darwin_nil = Gem::Platform.new 'i686-darwin'
-
- assert((x86_darwin_8 === x86_darwin_nil), '8.0 =~ nil')
- assert((x86_darwin_nil === x86_darwin_8), 'nil =~ 8.0')
- end
-
- def test_nil_version_is_stricter_for_linux_os
- x86_linux = Gem::Platform.new 'i686-linux'
- x86_linux_gnu = Gem::Platform.new 'i686-linux-gnu'
- x86_linux_musl = Gem::Platform.new 'i686-linux-musl'
- x86_linux_uclibc = Gem::Platform.new 'i686-linux-uclibc'
-
- assert((x86_linux === x86_linux_gnu), 'linux =~ linux-gnu')
- assert((x86_linux_gnu === x86_linux), 'linux-gnu =~ linux')
- assert(!(x86_linux_gnu === x86_linux_musl), 'linux-gnu =~ linux-musl')
- assert(!(x86_linux_musl === x86_linux_gnu), 'linux-musl =~ linux-gnu')
- assert(!(x86_linux_uclibc === x86_linux_musl), 'linux-uclibc =~ linux-musl')
- assert(!(x86_linux_musl === x86_linux_uclibc), 'linux-musl =~ linux-uclibc')
- assert(!(x86_linux === x86_linux_musl), 'linux =~ linux-musl')
- assert(!(x86_linux_musl === x86_linux), 'linux-musl =~ linux')
- assert(!(x86_linux === x86_linux_uclibc), 'linux =~ linux-uclibc')
- assert(!(x86_linux_uclibc === x86_linux), 'linux-uclibc =~ linux')
- end
-
def test_equals3_cpu_arm
arm = Gem::Platform.new 'arm-linux'
armv5 = Gem::Platform.new 'armv5-linux'
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 32600deee2..f08579c0cc 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -496,6 +496,44 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal url, e.uri
end
+ def test_fetch_path_timeout_error
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+
+ def fetcher.fetch_http(uri, mtime = nil, head = nil)
+ raise Timeout::Error, 'timed out'
+ end
+
+ url = 'http://example.com/uri'
+
+ e = assert_raises Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path url
+ end
+
+ assert_match %r{Timeout::Error: timed out \(#{Regexp.escape url}\)\z},
+ e.message
+ assert_equal url, e.uri
+ end
+
+ def test_fetch_path_getaddrinfo_error
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+
+ def fetcher.fetch_http(uri, mtime = nil, head = nil)
+ raise SocketError, 'getaddrinfo: nodename nor servname provided'
+ end
+
+ url = 'http://example.com/uri'
+
+ e = assert_raises Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path url
+ end
+
+ assert_match %r{SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z},
+ e.message
+ assert_equal url, e.uri
+ end
+
def test_fetch_path_openssl_ssl_sslerror
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher