summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler/definition.rb74
-rw-r--r--lib/bundler/dsl.rb63
-rw-r--r--lib/bundler/feature_flag.rb1
-rw-r--r--lib/bundler/inline.rb1
-rw-r--r--lib/bundler/lockfile_parser.rb20
-rw-r--r--lib/bundler/man/bundle-config.114
-rw-r--r--lib/bundler/man/bundle-config.1.ronn23
-rw-r--r--lib/bundler/plugin.rb1
-rw-r--r--lib/bundler/plugin/installer.rb17
-rw-r--r--lib/bundler/resolver.rb66
-rw-r--r--lib/bundler/settings.rb1
-rw-r--r--lib/bundler/source/rubygems.rb11
-rw-r--r--lib/bundler/source_list.rb53
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/command.rb1
-rw-r--r--lib/rubygems/specification.rb3
-rw-r--r--spec/bundler/bundler/dsl_spec.rb15
-rw-r--r--spec/bundler/bundler/plugin_spec.rb1
-rw-r--r--spec/bundler/bundler/source_list_spec.rb21
-rw-r--r--spec/bundler/commands/exec_spec.rb3
-rw-r--r--spec/bundler/commands/lock_spec.rb45
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb11
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb15
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb25
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb271
-rw-r--r--spec/bundler/install/gems/flex_spec.rb32
-rw-r--r--spec/bundler/lock/lockfile_spec.rb35
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb104
-rw-r--r--spec/bundler/resolver/platform_spec.rb17
-rw-r--r--spec/bundler/runtime/platform_spec.rb83
-rw-r--r--spec/bundler/support/indexes.rb2
-rw-r--r--test/rubygems/test_gem.rb10
33 files changed, 618 insertions, 425 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 3c25149d33..9178f0126f 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -106,6 +106,19 @@ module Bundler
@locked_platforms = []
end
+ @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
+ @disable_multisource = !Bundler.frozen_bundle? || @locked_gem_sources.none? {|s| s.remotes.size > 1 }
+
+ unless @disable_multisource
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
+ "You should regenerate your lockfile in a non frozen environment."
+
+ Bundler::SharedHelpers.major_deprecation 2, msg
+
+ @sources.allow_multisource!
+ @locked_gem_sources.each(&:allow_multisource!)
+ end
+
@unlock[:gems] ||= []
@unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -145,6 +158,14 @@ module Bundler
end
end
+ def disable_multisource?
+ @disable_multisource
+ end
+
+ def allow_multisource!
+ @disable_multisource = false
+ end
+
def resolve_with_cache!
raise "Specs already loaded" if @specs
sources.cached!
@@ -264,7 +285,7 @@ module Bundler
# Run a resolve against the locally available gems
Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
- Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end
end
end
@@ -530,6 +551,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,21 +678,20 @@ module Bundler
end
def converge_rubygems_sources
- return false if Bundler.feature_flag.disable_multisource?
+ return false if disable_multisource?
- changes = false
+ return false if locked_gem_sources.empty?
- # Get the RubyGems sources from the Gemfile.lock
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
# Get the RubyGems remotes from the Gemfile
actual_remotes = sources.rubygems_remotes
+ return false if actual_remotes.empty?
+
+ changes = false
# If there is a RubyGems source in both
- if !locked_gem_sources.empty? && !actual_remotes.empty?
- locked_gem_sources.each do |locked_gem|
- # Merge the remotes from the Gemfile into the Gemfile.lock
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
- end
+ locked_gem_sources.each do |locked_gem|
+ # Merge the remotes from the Gemfile into the Gemfile.lock
+ changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end
changes
@@ -893,30 +916,18 @@ module Bundler
# Record the specs available in each gem's source, so that those
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
- default = sources.default_source
- source_requirements = { :default => default }
- default = nil unless Bundler.feature_flag.disable_multisource?
- dependencies.each do |dep|
- next unless source = dep.source || default
- source_requirements[dep.name] = source
- end
+ source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements)
metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source
end
+ source_requirements[:global] = index unless disable_multisource?
source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
source_requirements
end
def pinned_spec_names(skip = nil)
- pinned_names = []
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
- @dependencies.each do |dep|
- next unless dep_source = dep.source || default
- next if dep_source == skip
- pinned_names << dep.name
- end
- pinned_names
+ dependency_source_requirements.reject {|_, source| source == skip }.keys
end
def requested_groups
@@ -973,5 +984,18 @@ module Bundler
Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
end
+
+ def dependency_source_requirements
+ @dependency_source_requirements ||= begin
+ source_requirements = {}
+ default = disable_multisource? && sources.default_source
+ dependencies.each do |dep|
+ dep_source = dep.source || default
+ next unless dep_source
+ source_requirements[dep.name] = dep_source
+ end
+ source_requirements
+ end
+ end
end
end
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 1cc7908b8a..ef5aaf669b 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -24,6 +24,9 @@ module Bundler
def initialize
@source = nil
@sources = SourceList.new
+
+ @global_rubygems_sources = []
+
@git_sources = {}
@dependencies = []
@groups = []
@@ -45,6 +48,7 @@ module Bundler
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
+ check_primary_source_safety
rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -164,8 +168,7 @@ module Bundler
elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
- check_primary_source_safety(@sources)
- @sources.global_rubygems_source = source
+ @global_rubygems_sources << source
end
end
@@ -183,24 +186,14 @@ module Bundler
end
def path(path, options = {}, &blk)
- unless block_given?
- msg = "You can no longer specify a path source by itself. Instead, \n" \
- "either use the :path option on a gem, or specify the gems that \n" \
- "bundler should find in the path source by passing a block to \n" \
- "the path method, like: \n\n" \
- " path 'dir/containing/rails' do\n" \
- " gem 'rails'\n" \
- " end\n\n"
-
- raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
- SharedHelpers.major_deprecation(2, msg.strip)
- end
-
source_options = normalize_hash(options).merge(
"path" => Pathname.new(path),
"root_path" => gemfile_root,
"gemspec" => gemspecs.find {|g| g.name == options["name"] }
)
+
+ source_options["global"] = true unless block_given?
+
source = @sources.add_path_source(source_options)
with_source(source, &blk)
end
@@ -279,6 +272,11 @@ module Bundler
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
end
+ def check_primary_source_safety
+ check_path_source_safety
+ check_rubygems_source_safety
+ end
+
private
def add_git_sources
@@ -440,25 +438,40 @@ repo_name ||= user_name
end
end
- def check_primary_source_safety(source_list)
- return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
+ def check_path_source_safety
+ return if @sources.global_path_source.nil?
+
+ msg = "You can no longer specify a path source by itself. Instead, \n" \
+ "either use the :path option on a gem, or specify the gems that \n" \
+ "bundler should find in the path source by passing a block to \n" \
+ "the path method, like: \n\n" \
+ " path 'dir/containing/rails' do\n" \
+ " gem 'rails'\n" \
+ " end\n\n"
- if Bundler.feature_flag.disable_multisource?
+ SharedHelpers.major_deprecation(2, msg.strip)
+ end
+
+ def check_rubygems_source_safety
+ if @global_rubygems_sources.size <= 1
+ @sources.global_rubygems_source = @global_rubygems_sources.first
+ return
+ end
+
+ @global_rubygems_sources.each do |source|
+ @sources.add_rubygems_remote(source)
+ end
+
+ 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"
- unless Bundler.feature_flag.bundler_2_mode?
- msg += ". To downgrade this error to a warning, run " \
- "`bundle config unset disable_multisource`"
- end
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/feature_flag.rb b/lib/bundler/feature_flag.rb
index a1b443b042..9b7172fa35 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -32,7 +32,6 @@ module Bundler
settings_flag(:cache_all) { bundler_3_mode? }
settings_flag(:default_install_uses_path) { bundler_3_mode? }
settings_flag(:deployment_means_frozen) { bundler_3_mode? }
- settings_flag(:disable_multisource) { bundler_3_mode? }
settings_flag(:forget_cli_options) { bundler_3_mode? }
settings_flag(:global_gem_cache) { bundler_3_mode? }
settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index 59211193d4..02da06cee9 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -50,6 +50,7 @@ def gemfile(install = false, options = {}, &gemfile)
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new
builder.instance_eval(&gemfile)
+ builder.check_primary_source_safety
Bundler.settings.temporary(:frozen => false) do
definition = builder.to_definition(nil, true)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index f836737621..058d353bbe 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -64,8 +64,6 @@ module Bundler
@state = nil
@specs = {}
- @rubygems_aggregate = Source::Rubygems.new
-
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@@ -89,7 +87,6 @@ module Bundler
send("parse_#{@state}", line)
end
end
- @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
@specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version
rescue ArgumentError => e
@@ -134,16 +131,19 @@ module Bundler
@sources << @current_source
end
when GEM
- if Bundler.feature_flag.disable_multisource?
+ source_remotes = Array(@opts["remote"])
+
+ if source_remotes.size == 1
@opts["remotes"] = @opts.delete("remote")
@current_source = TYPES[@type].from_lock(@opts)
- @sources << @current_source
else
- Array(@opts["remote"]).each do |url|
- @rubygems_aggregate.add_remote(url)
+ source_remotes.each do |url|
+ rubygems_aggregate.add_remote(url)
end
- @current_source = @rubygems_aggregate
+ @current_source = rubygems_aggregate
end
+
+ @sources << @current_source
when PLUGIN
@current_source = Plugin.source_from_lock(@opts)
@sources << @current_source
@@ -245,5 +245,9 @@ 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/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 7a4a16c43e..da628a7dcc 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -56,9 +56,6 @@ Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the con
.P
Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
.
-.P
-Executing \fBbundle config set \-\-local disable_multisource true\fR upgrades the warning about the Gemfile containing multiple primary sources to an error\. Executing \fBbundle config unset disable_multisource\fR downgrades this error to a warning\.
-.
.SH "REMEMBERING OPTIONS"
Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\.
.
@@ -184,9 +181,6 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
.
.IP "\(bu" 4
-\fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\.
-.
-.IP "\(bu" 4
\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\.
.
.IP "\(bu" 4
@@ -211,10 +205,10 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR): When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\.
.
.IP "\(bu" 4
-\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR) Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
+\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
.
.IP "\(bu" 4
-\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to 1\.
+\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to 1 on Windows, and to the the number of processors on other platforms\.
.
.IP "\(bu" 4
\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\.
@@ -241,7 +235,7 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBprefer_patch\fR (BUNDLE_PREFER_PATCH): Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\.
.
.IP "\(bu" 4
-\fBprint_only_version_number\fR (\fBBUNDLE_PRINT_ONLY_VERSION_NUMBER\fR) Print only version number from \fBbundler \-\-version\fR\.
+\fBprint_only_version_number\fR (\fBBUNDLE_PRINT_ONLY_VERSION_NUMBER\fR): Print only version number from \fBbundler \-\-version\fR\.
.
.IP "\(bu" 4
\fBredirect\fR (\fBBUNDLE_REDIRECT\fR): The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
@@ -283,7 +277,7 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBunlock_source_unlocks_spec\fR (\fBBUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC\fR): Whether running \fBbundle update \-\-source NAME\fR unlocks a gem with the given name\. Defaults to \fBtrue\fR\.
.
.IP "\(bu" 4
-\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR) Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
+\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
.
.IP "\(bu" 4
\fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index b3c4e59a78..81d0603e8b 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -47,10 +47,6 @@ configuration only from the local application.
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration.
-Executing `bundle config set --local disable_multisource true` upgrades the warning about
-the Gemfile containing multiple primary sources to an error. Executing `bundle
-config unset disable_multisource` downgrades this error to a warning.
-
## REMEMBERING OPTIONS
Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or
@@ -178,10 +174,6 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
Allow Bundler to use a local git override without checking if the revision
present in the lockfile is present in the repository.
-* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
- When set, Gemfiles containing multiple sources will produce errors
- instead of warnings.
- Use `bundle config unset disable_multisource` to unset.
* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
Stop Bundler from accessing gems installed to RubyGems' normal location.
* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):
@@ -206,13 +198,14 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`):
Whether Bundler should cache all gems globally, rather than locally to the
installing Ruby installation.
-* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`): When set, no post install
- messages will be printed. To silence a single gem, use dot notation like
- `ignore_messages.httparty true`.
-* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`)
+* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`):
+ When set, no post install messages will be printed. To silence a single gem,
+ use dot notation like `ignore_messages.httparty true`.
+* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`):
Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`.
* `jobs` (`BUNDLE_JOBS`):
- The number of gems Bundler can install in parallel. Defaults to 1.
+ The number of gems Bundler can install in parallel. Defaults to 1 on Windows,
+ and to the the number of processors on other platforms.
* `no_install` (`BUNDLE_NO_INSTALL`):
Whether `bundle package` should skip installing gems.
* `no_prune` (`BUNDLE_NO_PRUNE`):
@@ -233,7 +226,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
Enable Bundler's experimental plugin system.
* `prefer_patch` (BUNDLE_PREFER_PATCH):
Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`.
-* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`)
+* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`):
Print only version number from `bundler --version`.
* `redirect` (`BUNDLE_REDIRECT`):
The number of redirects allowed for network requests. Defaults to `5`.
@@ -269,7 +262,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `unlock_source_unlocks_spec` (`BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC`):
Whether running `bundle update --source NAME` unlocks a gem with the given
name. Defaults to `true`.
-* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`)
+* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`):
Require passing `--all` to `bundle update` when everything should be updated,
and disallow passing no options to `bundle update`.
* `user_agent` (`BUNDLE_USER_AGENT`):
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index da3f468da5..dddb468582 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -105,6 +105,7 @@ module Bundler
else
builder.eval_gemfile(gemfile)
end
+ builder.check_primary_source_safety
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 26cec4f18c..73198aec04 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -16,15 +16,13 @@ module Bundler
version = options[:version] || [">= 0"]
- Bundler.settings.temporary(:disable_multisource => false) do
- if options[:git]
- install_git(names, version, options)
- elsif options[:local_git]
- install_local_git(names, version, options)
- else
- sources = options[:source] || Bundler.rubygems.sources
- install_rubygems(names, version, sources)
- end
+ if options[:git]
+ install_git(names, version, options)
+ elsif options[:local_git]
+ install_local_git(names, version, options)
+ else
+ sources = options[:source] || Bundler.rubygems.sources
+ install_rubygems(names, version, sources)
end
end
@@ -84,6 +82,7 @@ module Bundler
deps = names.map {|name| Dependency.new name, version }
definition = Definition.new(nil, deps, source_list, true)
+ definition.allow_multisource!
install_definition(definition)
end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 0f17ba3afb..0c11c83b72 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -17,15 +17,14 @@ module Bundler
# ==== Returns
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
# collection of gemspecs is returned. Otherwise, nil is returned.
- def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
+ def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
base = SpecSet.new(base) unless base.is_a?(SpecSet)
- resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
+ resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
result = resolver.start(requirements)
SpecSet.new(result)
end
- def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
- @index = index
+ def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@source_requirements = source_requirements
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@@ -36,14 +35,14 @@ module Bundler
@base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
end
additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
- @platforms = platforms
+ @platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } }
@resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
@gem_version_promoter = gem_version_promoter
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
- @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
+ @no_aggregate_global_source = @source_requirements[:global].nil?
@variant_specific_names = []
- @generic_names = []
+ @generic_names = ["Ruby\0", "RubyGems\0"]
end
def start(requirements)
@@ -125,8 +124,7 @@ module Bundler
dependency = dependency_proxy.dep
name = dependency.name
search_result = @search_for[dependency_proxy] ||= begin
- index = index_for(dependency)
- results = index.search(dependency, @base[name])
+ results = results_for(dependency, @base[name])
if vertex = @base_dg.vertex_named(name)
locked_requirement = vertex.payload.requirement
@@ -195,23 +193,26 @@ module Bundler
search_result
end
- def index_for(dependency)
+ def index_for(dependency, base)
source = @source_requirements[dependency.name]
if source
source.specs
- elsif @lockfile_uses_separate_rubygems_sources
- Index.build do |idx|
- if dependency.all_sources
- dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
- else
- idx.add_source @source_requirements[:default].specs
- end
+ elsif @no_aggregate_global_source
+ dependency.all_sources.find(-> { Index.new }) do |s|
+ idx = s.specs
+ results = idx.search(dependency, base)
+ next if results.empty? || results == base
+ return idx
end
else
- @index
+ @source_requirements[:global]
end
end
+ def results_for(dependency, base)
+ index_for(dependency, base).search(dependency, base)
+ end
+
def name_for(dependency)
dependency.name
end
@@ -238,11 +239,13 @@ module Bundler
def relevant_sources_for_vertex(vertex)
if vertex.root?
- [@source_requirements[vertex.name]]
- elsif @lockfile_uses_separate_rubygems_sources
+ [@source_requirements[vertex.name]].compact
+ elsif @no_aggregate_global_source
vertex.recursive_predecessors.map do |v|
@source_requirements[v.name]
- end << @source_requirements[:default]
+ end.compact << @source_requirements[:default]
+ else
+ []
end
end
@@ -283,7 +286,7 @@ module Bundler
if (base = @base[dependency.name]) && !base.empty?
dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
else
- all = index_for(dependency).search(dependency.name).size
+ all = index_for(dependency, base).search(dependency.name).size
if all <= 1
all - 1_000_000
@@ -326,7 +329,7 @@ module Bundler
"The source does not contain any versions of '#{name}'"
end
else
- message = "Could not find gem '#{requirement}' in any of the gem sources " \
+ message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \
"listed in your Gemfile#{cache_message}."
end
raise GemNotFound, message
@@ -411,14 +414,8 @@ module Bundler
relevant_sources = if conflict.requirement.source
[conflict.requirement.source]
- elsif conflict.requirement.all_sources
- conflict.requirement.all_sources
- elsif @lockfile_uses_separate_rubygems_sources
- # every conflict should have an explicit group of sources when we
- # enforce strict pinning
- raise "no source set for #{conflict}"
else
- []
+ conflict.requirement.all_sources
end.compact.map(&:to_s).uniq.sort
metadata_requirement = name.end_with?("\0")
@@ -455,7 +452,8 @@ module Bundler
def validate_resolved_specs!(resolved_specs)
resolved_specs.each do |v|
name = v.name
- next unless sources = relevant_sources_for_vertex(v)
+ sources = relevant_sources_for_vertex(v)
+ next unless sources.any?
sources.compact!
if default_index = sources.index(@source_requirements[:default])
sources.delete_at(default_index)
@@ -464,14 +462,12 @@ module Bundler
sources.uniq!
next if sources.size <= 1
- multisource_disabled = Bundler.feature_flag.disable_multisource?
-
msg = ["The gem '#{name}' was found in multiple relevant sources."]
msg.concat sources.map {|s| " * #{s}" }.sort
- msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
+ msg << "You #{@no_aggregate_global_source ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
msg = msg.join("\n")
- raise SecurityError, msg if multisource_disabled
+ raise SecurityError, msg if @no_aggregate_global_source
Bundler.ui.warn "Warning: #{msg}"
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index 749e4eb60e..ceb2fde32c 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -20,7 +20,6 @@ module Bundler
disable_exec_load
disable_local_branch_check
disable_local_revision_check
- disable_multisource
disable_shared_gems
disable_version_check
force_ruby_platform
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 5b89b1645d..1b4bccadb8 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -21,6 +21,7 @@ module Bundler
@allow_remote = false
@allow_cached = false
@caches = [cache_path, *Bundler.rubygems.gem_cache]
+ @disable_multisource = true
Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
end
@@ -49,8 +50,16 @@ module Bundler
o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
end
+ def disable_multisource?
+ @disable_multisource
+ end
+
+ def allow_multisource!
+ @disable_multisource = false
+ end
+
def can_lock?(spec)
- return super if Bundler.feature_flag.disable_multisource?
+ return super if disable_multisource?
spec.source.is_a?(Rubygems)
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 436891256d..4ba6415448 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -5,24 +5,41 @@ module Bundler
attr_reader :path_sources,
:git_sources,
:plugin_sources,
- :global_rubygems_source,
- :metadata_source
+ :global_path_source,
+ :metadata_source,
+ :disable_multisource
+
+ def global_rubygems_source
+ @global_rubygems_source ||= rubygems_aggregate_class.new
+ end
def initialize
@path_sources = []
@git_sources = []
@plugin_sources = []
@global_rubygems_source = nil
- @rubygems_aggregate = rubygems_aggregate_class.new
+ @global_path_source = nil
@rubygems_sources = []
@metadata_source = Source::Metadata.new
+ @disable_multisource = true
+ end
+
+ def disable_multisource?
+ @disable_multisource
+ end
+
+ def allow_multisource!
+ rubygems_sources.map(&:allow_multisource!)
+ @disable_multisource = false
end
def add_path_source(options = {})
if options["gemspec"]
add_source_to_list Source::Gemspec.new(options), path_sources
else
- add_source_to_list Source::Path.new(options), path_sources
+ path_source = add_source_to_list Source::Path.new(options), path_sources
+ @global_path_source ||= path_source if options["global"]
+ path_source
end
end
@@ -41,24 +58,20 @@ module Bundler
end
def global_rubygems_source=(uri)
- if Bundler.feature_flag.disable_multisource?
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
- end
- add_rubygems_remote(uri)
+ @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
end
def add_rubygems_remote(uri)
- return if Bundler.feature_flag.disable_multisource?
- @rubygems_aggregate.add_remote(uri)
- @rubygems_aggregate
+ global_rubygems_source.add_remote(uri)
+ global_rubygems_source
end
def default_source
- global_rubygems_source || @rubygems_aggregate
+ global_path_source || global_rubygems_source
end
def rubygems_sources
- @rubygems_sources + [default_source]
+ @rubygems_sources + [global_rubygems_source]
end
def rubygems_remotes
@@ -75,7 +88,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
@@ -92,9 +105,9 @@ module Bundler
end
end
- replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
+ replacement_rubygems = !disable_multisource? &&
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
- @rubygems_aggregate = replacement_rubygems if replacement_rubygems
+ @global_rubygems_source = replacement_rubygems if replacement_rubygems
return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
return true if replacement_rubygems && rubygems_remotes.sort_by(&:to_s) != replacement_rubygems.remotes.sort_by(&:to_s)
@@ -110,10 +123,6 @@ module Bundler
all_sources.each(&:remote!)
end
- def rubygems_primary_remotes
- @rubygems_aggregate.remotes
- end
-
private
def rubygems_aggregate_class
@@ -136,7 +145,9 @@ module Bundler
end
def combine_rubygems_sources
- Source::Rubygems.new("remotes" => rubygems_remotes)
+ aggregate_source = Source::Rubygems.new("remotes" => rubygems_remotes)
+ aggregate_source.allow_multisource! unless disable_multisource?
+ aggregate_source
end
def warn_on_git_protocol(source)
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index f9569c8f78..0ddfa668cd 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.2.9".freeze
+ VERSION = "2.2.10".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 41b1353e1f..22fe0366b2 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.2.9".freeze
+ VERSION = "3.2.10".freeze
end
# Must be first since it unloads the prelude from 1.9.2
diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb
index bf55ce3205..9f935e6285 100644
--- a/lib/rubygems/command.rb
+++ b/lib/rubygems/command.rb
@@ -634,6 +634,7 @@ RubyGems is a package manager for Ruby.
gem install rake
gem list --local
gem build package.gemspec
+ gem push package-0.0.1.gem
gem help install
Further help:
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 73062afe53..6b569032ba 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -666,6 +666,9 @@ class Gem::Specification < Gem::BasicSpecification
#
# # Only prereleases or final releases after 2.6.0.preview2
# spec.required_ruby_version = '> 2.6.0.preview2'
+ #
+ # # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
+ # spec.required_ruby_version = '>= 2.3', '< 4'
def required_ruby_version=(req)
@required_ruby_version = Gem::Requirement.create req
diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb
index ff87b57886..a47dd6e399 100644
--- a/spec/bundler/bundler/dsl_spec.rb
+++ b/spec/bundler/bundler/dsl_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Bundler::Dsl do
expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption)
end
- context "default hosts", :bundler => "2" do
+ context "default hosts", :bundler => "< 3" do
it "converts :github to URI using https" do
subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git"
@@ -195,19 +195,6 @@ RSpec.describe Bundler::Dsl do
# gem 'spree_api'
# gem 'spree_backend'
# end
- describe "#github", :bundler => "< 3" do
- it "from github" do
- spree_gems = %w[spree_core spree_api spree_backend]
- subject.github "spree" do
- spree_gems.each {|spree_gem| subject.send :gem, spree_gem }
- end
-
- subject.dependencies.each do |d|
- expect(d.source.uri).to eq("https://github.com/spree/spree.git")
- end
- end
- end
-
describe "#github" do
it "from github" do
spree_gems = %w[spree_core spree_api spree_backend]
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index 8c95723bcc..d18896895e 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -112,6 +112,7 @@ RSpec.describe Bundler::Plugin do
before do
allow(Plugin::DSL).to receive(:new) { builder }
allow(builder).to receive(:eval_gemfile).with(gemfile)
+ allow(builder).to receive(:check_primary_source_safety)
allow(builder).to receive(:to_definition) { definition }
allow(builder).to receive(:inferred_plugins) { [] }
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/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 5d43586116..bb4091ef98 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -762,7 +762,8 @@ RSpec.describe "bundle exec" do
let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" }
let(:expected_err) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile.\e[0m
+\e[31mCould not find gem 'rack (= 2)' in locally installed gems.
+The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m
\e[33mRun `bundle install` to install missing gems.\e[0m
EOS
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 44bde4a9b8..7724170a63 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -491,6 +491,51 @@ RSpec.describe "bundle lock" do
end
end
+ it "does not conflict on ruby requirements when adding new platforms" do
+ next_minor = Gem.ruby_version.segments[0..1].map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".")
+
+ build_repo4 do
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "universal-darwin"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x64-mingw32"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+
+ gem "raygun-apm"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ raygun-apm (1.0.78-universal-darwin)
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ raygun-apm
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform x86_64-linux", :artifice => :compact_index, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end
+
context "when an update is available" do
let(:repo) { gem_repo2 }
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
index 2c965f0ddd..3f81808980 100644
--- a/spec/bundler/commands/post_bundle_message_spec.rb
+++ b/spec/bundler/commands/post_bundle_message_spec.rb
@@ -113,16 +113,7 @@ RSpec.describe "post bundle message" do
bundle "config set force_ruby_platform true"
end
- it "should report a helpful error message", :bundler => "< 3" do
- install_gemfile <<-G, :raise_on_error => false
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "not-a-gem", :group => :development
- G
- expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.")
- end
-
- it "should report a helpful error message", :bundler => "3" do
+ it "should report a helpful error message" do
install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index 7a95a8abde..4001df26da 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -422,14 +422,13 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- %w[ruby jruby].each do |platform|
- simulate_platform(platform) do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gemspec
- G
- end
- end
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gemspec
+ G
+
+ simulate_platform("ruby") { bundle "install" }
+ simulate_platform("jruby") { bundle "install" }
end
context "on ruby" do
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index 8ab59abeeb..9b4bbba016 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -88,14 +88,15 @@ RSpec.describe "bundle install across platforms" do
simulate_new_machine
simulate_platform "ruby"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "nokogiri"
- G
+ bundle "install"
expect(the_bundle).to include_gems "nokogiri 1.4.2"
expect(the_bundle).not_to include_gems "weakling"
+
+ simulate_platform "java"
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
end
it "does not keep unneeded platforms for gems that are used" do
@@ -241,20 +242,6 @@ RSpec.describe "bundle install across platforms" do
end
end
- it "works the other way with gems that have different dependencies" do
- simulate_platform "ruby"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "nokogiri"
- G
-
- simulate_platform "java"
- bundle "install"
-
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
- end
-
it "works with gems with platform-specific dependency having different requirements order" do
simulate_platform x64_mac
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 655f91dd69..e40ae84c59 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "2" do
+ it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do
bundle :install
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
@@ -54,7 +54,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "warns about ambiguous gems, but installs anyway", :bundler => "2" do
+ it "warns about ambiguous gems, but installs anyway", :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_repo1)}")
@@ -96,7 +96,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "installs the gems without any warning" do
bundle :install
- expect(out).not_to include("Warning")
+ expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0")
expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1")
end
@@ -128,7 +128,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- gemfile <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo3)}"
gem "rack-obama" # should come from repo3!
gem "rack", :source => "#{file_uri_for(gem_repo1)}"
@@ -136,8 +136,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs the gems without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
+ expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
end
end
@@ -173,8 +172,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "installs from the same source without any warning" do
bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ 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
@@ -188,27 +187,38 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "when disable_multisource is set" do
- before do
- bundle "config set disable_multisource true"
- 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(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- 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/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
- # 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
+ end
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- 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")
+ context "and in another source with a higher version" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.1" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
+ end
end
end
+
+ 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")
+ end
end
end
@@ -222,7 +232,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "and not in any other sources" do
before do
- gemfile <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
source "#{file_uri_for(gem_repo3)}" do
gem "depends_on_rack"
@@ -231,8 +241,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs from the other source without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
+ expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
end
end
@@ -248,7 +257,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs from the other source and warns about ambiguous gems", :bundler => "2" do
+ 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)}")
@@ -280,7 +289,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs the dependency from the pinned source without warning", :bundler => "2" do
+ 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.")
@@ -305,80 +314,74 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
context "when a top-level gem has an indirect dependency" do
- context "when disable_multisource is set" do
- before do
- bundle "config set disable_multisource true"
- end
-
- before do
- build_repo gem_repo2 do
- build_gem "depends_on_rack", "1.0.1" do |s|
- s.add_dependency "rack"
- end
- end
-
- build_repo gem_repo3 do
- build_gem "unrelated_gem", "1.0.0"
+ before do
+ build_repo gem_repo2 do
+ build_gem "depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "rack"
end
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ build_repo gem_repo3 do
+ build_gem "unrelated_gem", "1.0.0"
+ end
- gem "depends_on_rack"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "unrelated_gem"
- end
- G
- end
+ gem "depends_on_rack"
- context "and the dependency is only in the top-level source" do
- before do
- update_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "unrelated_gem"
end
+ G
+ end
- it "installs all gems without 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", "unrelated_gem 1.0.0")
+ context "and the dependency is only in the top-level source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
end
end
- context "and the dependency is only in a pinned source" do
- before do
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ it "installs all gems without 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", "unrelated_gem 1.0.0")
+ end
+ end
+
+ context "and the dependency is only in a pinned source" do
+ before do
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
+ end
- it "does not find the dependency" do
- bundle :install, :raise_on_error => false
- expect(err).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources")
- end
+ it "does not find the dependency" do
+ bundle :install, :raise_on_error => false
+ expect(err).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources")
end
+ end
- context "and the dependency is in both the top-level and a pinned source" do
- before do
- update_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
+ context "and the dependency is in both the top-level and a pinned source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
+ end
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
+ end
- it "installs the dependency from the top-level source without 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", "unrelated_gem 1.0.0")
- end
+ it "installs the dependency from the top-level source without 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", "unrelated_gem 1.0.0")
end
end
end
@@ -389,15 +392,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "not_in_repo1", "1.0.0"
end
- gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo3)}"
gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}"
G
end
it "does not install the gem" do
- bundle :install, :raise_on_error => false
- expect(err).to include("Could not find gem 'not_in_repo1'")
+ expect(err).to include("Could not find gem 'not_in_repo1")
end
end
@@ -433,6 +435,92 @@ 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 a lockfile with separate rubygems source sections if not in frozen mode" do
+ bundle "install"
+
+ expect(lockfile).to eq(split_gem_section_lockfile)
+
+ expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
+ end
+
+ it "installs the existing lockfile but prints a warning if in frozen mode", :bundler => "< 3" do
+ bundle "config set --local deployment true"
+
+ bundle "install"
+
+ expect(lockfile).to eq(aggregate_gem_section_lockfile)
+
+ expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
+ end
+
+ it "refuses to install the existing lockfile and prints an error if in frozen mode", :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"
@@ -457,14 +545,13 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do
system_gems "rack-0.9.1"
- gemfile <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack" # shoud come from repo1!
G
end
it "installs the gems without any warning" do
- bundle :install
expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack 1.0.0")
end
@@ -615,16 +702,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "keeps the old version", :bundler => "2" do
- expect(the_bundle).to include_gems("rack 1.0.0")
- end
-
- it "installs the higher version in the new repo", :bundler => "3" do
+ it "installs the higher version in the new repo" do
expect(the_bundle).to include_gems("rack 1.2")
end
end
- context "when a gem is available from multiple ambiguous sources", :bundler => "3" do
+ context "when a gem is available from multiple ambiguous sources" do
it "raises, suggesting a source block" do
build_repo4 do
build_gem "depends_on_rack" do |s|
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/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 d061ca7064..cb85b6c9cb 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_env", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do
expect(deprecations).to include \
"`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \
@@ -33,7 +33,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_env", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \
@@ -50,7 +50,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_system", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_system", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \
"If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \
@@ -67,7 +67,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_exec", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_exec", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \
"If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \
@@ -84,7 +84,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .load", :bundler => "2" do
+ it "is deprecated in favor of .load", :bundler => "< 3" do
expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)"
end
@@ -109,7 +109,7 @@ RSpec.describe "major deprecations" do
bundle "check --path vendor/bundle", :raise_on_error => false
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `--path` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \
@@ -118,7 +118,7 @@ RSpec.describe "major deprecations" do
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
context "bundle check --path=" do
@@ -131,7 +131,7 @@ RSpec.describe "major deprecations" do
bundle "check --path=vendor/bundle", :raise_on_error => false
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `--path` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \
@@ -140,7 +140,7 @@ RSpec.describe "major deprecations" do
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
context "bundle cache --all" do
@@ -153,7 +153,7 @@ RSpec.describe "major deprecations" do
bundle "cache --all", :raise_on_error => false
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `--all` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \
@@ -162,7 +162,7 @@ RSpec.describe "major deprecations" do
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
describe "bundle config" do
@@ -292,7 +292,7 @@ RSpec.describe "major deprecations" do
G
end
- it "should output a deprecation warning", :bundler => "2" do
+ it "should output a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`")
end
@@ -356,7 +356,7 @@ RSpec.describe "major deprecations" do
bundle "install #{flag_name} #{value}"
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `#{flag_name}` flag is deprecated because it relies on " \
"being remembered across bundler invocations, which bundler " \
@@ -365,7 +365,7 @@ RSpec.describe "major deprecations" do
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
end
end
@@ -378,18 +378,58 @@ RSpec.describe "major deprecations" do
G
end
- it "shows a deprecation", :bundler => "2" do
+ it "shows a deprecation", :bundler => "< 3" do
expect(deprecations).to include(
"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 "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
+ context "bundle install with a lockfile with a single rubygems section with multiple remotes in frozen mode" 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
+
+ bundle "config set --local deployment true"
+ 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 regenerate your lockfile in a non frozen environment.")
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
end
context "when Bundler.setup is run in a ruby script" do
@@ -422,14 +462,14 @@ RSpec.describe "major deprecations" do
RUBY
end
- it "should print a capistrano deprecation warning", :bundler => "2" do
+ it "should print a capistrano deprecation warning", :bundler => "< 3" do
expect(deprecations).to include("Bundler no longer integrates " \
"with Capistrano, but Capistrano provides " \
"its own integration with Bundler via the " \
"capistrano-bundler gem. Use it instead.")
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
describe Bundler::Dsl do
@@ -439,7 +479,7 @@ RSpec.describe "major deprecations" do
end
context "with github gems" do
- it "does not warn about removal", :bundler => "2" do
+ it "does not warn about removal", :bundler => "< 3" do
expect(Bundler.ui).not_to receive(:warn)
subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git"
@@ -461,7 +501,7 @@ The :github git source is deprecated, and will be removed in the future. Change
end
context "with bitbucket gems" do
- it "does not warn about removal", :bundler => "2" do
+ it "does not warn about removal", :bundler => "< 3" do
expect(Bundler.ui).not_to receive(:warn)
subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
end
@@ -483,7 +523,7 @@ The :bitbucket git source is deprecated, and will be removed in the future. Add
end
context "with gist gems" do
- it "does not warn about removal", :bundler => "2" do
+ it "does not warn about removal", :bundler => "< 3" do
expect(Bundler.ui).not_to receive(:warn)
subject.gem("not-really-a-gem", :gist => "1234")
end
@@ -514,7 +554,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle :show
end
- it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
+ it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do
expect(deprecations).to include("use `bundle list` instead of `bundle show`")
end
@@ -526,7 +566,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --outdated"
end
- it "prints a deprecation warning informing about its removal", :bundler => "2" do
+ it "prints a deprecation warning informing about its removal", :bundler => "< 3" do
expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement")
end
@@ -538,7 +578,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --verbose"
end
- it "prints a deprecation warning informing about its removal", :bundler => "2" do
+ it "prints a deprecation warning informing about its removal", :bundler => "< 3" do
expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement")
end
@@ -550,7 +590,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show rack"
end
- it "prints a deprecation warning recommending `bundle info`", :bundler => "2" do
+ it "prints a deprecation warning recommending `bundle info`", :bundler => "< 3" do
expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`")
end
@@ -562,7 +602,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show --paths"
end
- it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
+ it "prints a deprecation warning recommending `bundle list`", :bundler => "< 3" do
expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`")
end
@@ -574,7 +614,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "show rack --paths"
end
- it "prints deprecation warning recommending `bundle info`", :bundler => "2" do
+ it "prints deprecation warning recommending `bundle info`", :bundler => "< 3" do
expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`")
end
@@ -587,7 +627,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "console", :raise_on_error => false
end
- it "prints a deprecation warning", :bundler => "2" do
+ it "prints a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include \
"bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
end
@@ -603,7 +643,7 @@ The :gist git source is deprecated, and will be removed in the future. Add this
bundle "viz"
end
- it "prints a deprecation warning", :bundler => "2" do
+ it "prints a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
end
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index 7169ba4b95..bc4081f8b5 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -28,6 +28,23 @@ RSpec.describe "Resolving platform craziness" do
end
end
+ it "resolves multiplatform gems with redundant platforms correctly" do
+ @index = build_index do
+ gem "zookeeper", "1.4.11"
+ gem "zookeeper", "1.4.11", "java" do
+ dep "slyphon-log4j", "= 1.2.15"
+ dep "slyphon-zookeeper_jar", "= 3.3.5"
+ end
+ gem "slyphon-log4j", "1.2.15"
+ gem "slyphon-zookeeper_jar", "3.3.5", "java"
+ end
+
+ dep "zookeeper"
+ platforms "java", "ruby", "universal-java-11"
+
+ should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java]
+ end
+
it "takes the latest ruby gem, even if an older platform specific version is available" do
@index = build_index do
gem "foo", "1.0.0"
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index f28b5ea16b..154d967e12 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -57,6 +57,89 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "nokogiri 1.4.2"
end
+ it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "mini_portile2", "~> 2.5.0"
+ s.add_dependency "racc", "~> 1.4"
+ end
+
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ s.add_dependency "racc", "~> 1.4"
+ end
+
+ build_gem "mini_portile2", "2.5.0"
+ build_gem "racc", "1.5.2"
+ end
+
+ good_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ mini_portile2 (2.5.0)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
+ nokogiri (1.11.1-#{Bundler.local_platform})
+ racc (~> 1.4)
+ racc (1.5.2)
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ nokogiri (~> 1.11)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "nokogiri", "~> 1.11"
+ G
+
+ lockfile good_lockfile
+
+ bundle "update nokogiri"
+
+ expect(lockfile).to eq(good_lockfile)
+ end
+
+ it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "nokogiri"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ nokogiri (1.4.2)
+ nokogiri (1.4.2-java)
+ weakling (>= 0.0.3)
+ weakling (0.0.3)
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ 2.1.4
+ G
+
+ bundle "install"
+
+ expect(out).to include("Fetching nokogiri 1.4.2 (java)")
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA"
+ end
+
it "will add the resolve for the current platform" do
lockfile <<-G
GEM
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index 45b68541f5..1f3c4ddaa6 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -30,7 +30,7 @@ module Spec
args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter
args[2] ||= [] # additional_base_requirements
args[3] ||= @platforms # platforms
- Bundler::Resolver.resolve(deps, @index, source_requirements, *args)
+ Bundler::Resolver.resolve(deps, source_requirements, *args)
end
def should_resolve_as(specs)
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index 1c6d790b25..8b028d3495 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -1958,15 +1958,9 @@ class TestGem < Gem::TestCase
io.write 'gem "a"'
end
- platform = Bundler::GemHelpers.generic_local_platform
- if platform == Gem::Platform::RUBY
- platform = ''
- else
- platform = " #{platform}"
- end
-
expected = <<-EXPECTED
-Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile.
+Could not find gem 'a' in locally installed gems.
+The source does not contain any versions of 'a'
You may need to `gem install -g` to install missing gems
EXPECTED