summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler.rb3
-rw-r--r--lib/bundler/cli.rb1
-rw-r--r--lib/bundler/cli/cache.rb1
-rw-r--r--lib/bundler/cli/gem.rb54
-rw-r--r--lib/bundler/compact_index_client/updater.rb10
-rw-r--r--lib/bundler/definition.rb95
-rw-r--r--lib/bundler/dep_proxy.rb23
-rw-r--r--lib/bundler/dsl.rb58
-rw-r--r--lib/bundler/feature_flag.rb1
-rw-r--r--lib/bundler/fetcher.rb1
-rw-r--r--lib/bundler/gem_helper.rb14
-rw-r--r--lib/bundler/gem_version_promoter.rb4
-rw-r--r--lib/bundler/index.rb11
-rw-r--r--lib/bundler/inline.rb1
-rw-r--r--lib/bundler/installer.rb19
-rw-r--r--lib/bundler/installer/standalone.rb15
-rw-r--r--lib/bundler/lazy_specification.rb27
-rw-r--r--lib/bundler/lockfile_parser.rb20
-rw-r--r--lib/bundler/man/bundle-add.12
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.12
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.12
-rw-r--r--lib/bundler/man/bundle-config.18
-rw-r--r--lib/bundler/man/bundle-config.1.ronn6
-rw-r--r--lib/bundler/man/bundle-doctor.12
-rw-r--r--lib/bundler/man/bundle-exec.12
-rw-r--r--lib/bundler/man/bundle-gem.12
-rw-r--r--lib/bundler/man/bundle-info.12
-rw-r--r--lib/bundler/man/bundle-init.12
-rw-r--r--lib/bundler/man/bundle-inject.12
-rw-r--r--lib/bundler/man/bundle-install.12
-rw-r--r--lib/bundler/man/bundle-list.12
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.12
-rw-r--r--lib/bundler/man/bundle-outdated.12
-rw-r--r--lib/bundler/man/bundle-platform.12
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.12
-rw-r--r--lib/bundler/man/bundle-viz.12
-rw-r--r--lib/bundler/man/bundle.12
-rw-r--r--lib/bundler/man/gemfile.52
-rw-r--r--lib/bundler/plugin.rb1
-rw-r--r--lib/bundler/plugin/installer.rb18
-rw-r--r--lib/bundler/plugin/source_list.rb4
-rw-r--r--lib/bundler/resolver.rb195
-rw-r--r--lib/bundler/resolver/spec_group.rb100
-rw-r--r--lib/bundler/rubygems_ext.rb16
-rw-r--r--lib/bundler/rubygems_gem_installer.rb47
-rw-r--r--lib/bundler/settings.rb2
-rw-r--r--lib/bundler/shared_helpers.rb4
-rw-r--r--lib/bundler/source/git.rb36
-rw-r--r--lib/bundler/source/git/git_proxy.rb52
-rw-r--r--lib/bundler/source/path/installer.rb2
-rw-r--r--lib/bundler/source/rubygems.rb3
-rw-r--r--lib/bundler/source_list.rb37
-rw-r--r--lib/bundler/spec_set.rb9
-rw-r--r--lib/bundler/stub_specification.rb8
-rw-r--r--lib/bundler/templates/newgem/CHANGELOG.md.tt5
-rw-r--r--lib/bundler/templates/newgem/Gemfile.tt2
-rw-r--r--lib/bundler/templates/newgem/README.md.tt8
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt2
-rw-r--r--lib/bundler/templates/newgem/rubocop.yml.tt3
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb7
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb1
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb16
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/errors.rb4
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb11
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb18
-rw-r--r--lib/bundler/vendor/thor/lib/thor.rb11
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/arguments.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb17
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb7
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/color.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
-rw-r--r--lib/rubygems.rb4
-rw-r--r--lib/rubygems/command.rb1
-rw-r--r--lib/rubygems/config_file.rb9
-rw-r--r--lib/rubygems/core_ext/tcpsocket_init.rb52
-rw-r--r--lib/rubygems/dependency.rb6
-rw-r--r--lib/rubygems/ext/builder.rb3
-rw-r--r--lib/rubygems/installer_uninstaller_utils.rb7
-rw-r--r--lib/rubygems/platform.rb14
-rw-r--r--lib/rubygems/remote_fetcher.rb3
-rw-r--r--lib/rubygems/requirement.rb2
-rw-r--r--lib/rubygems/resolver/index_specification.rb5
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb7
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb1
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb14
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb2
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb11
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb18
-rw-r--r--lib/rubygems/specification.rb56
-rw-r--r--lib/rubygems/test_case.rb15
-rw-r--r--spec/bundler/bundler/cli_spec.rb4
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb25
-rw-r--r--spec/bundler/bundler/dep_proxy_spec.rb22
-rw-r--r--spec/bundler/bundler/dsl_spec.rb15
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb11
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb4
-rw-r--r--spec/bundler/bundler/plugin_spec.rb1
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb8
-rw-r--r--spec/bundler/bundler/source/git_spec.rb4
-rw-r--r--spec/bundler/bundler/stub_specification_spec.rb27
-rw-r--r--spec/bundler/cache/git_spec.rb2
-rw-r--r--spec/bundler/commands/cache_spec.rb13
-rw-r--r--spec/bundler/commands/exec_spec.rb131
-rw-r--r--spec/bundler/commands/lock_spec.rb69
-rw-r--r--spec/bundler/commands/newgem_spec.rb149
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb11
-rw-r--r--spec/bundler/commands/update_spec.rb13
-rw-r--r--spec/bundler/install/bundler_spec.rb74
-rw-r--r--spec/bundler/install/deploy_spec.rb20
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb15
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb20
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb69
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb67
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb280
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb20
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb26
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb39
-rw-r--r--spec/bundler/install/gemspecs_spec.rb2
-rw-r--r--spec/bundler/install/git_spec.rb21
-rw-r--r--spec/bundler/lock/lockfile_spec.rb2
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb58
-rw-r--r--spec/bundler/quality_spec.rb2
-rw-r--r--spec/bundler/realworld/double_check_spec.rb2
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb217
-rw-r--r--spec/bundler/realworld/parallel_spec.rb2
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb20
-rw-r--r--spec/bundler/resolver/basic_spec.rb2
-rw-r--r--spec/bundler/resolver/platform_spec.rb168
-rw-r--r--spec/bundler/runtime/inline_spec.rb4
-rw-r--r--spec/bundler/runtime/platform_spec.rb110
-rw-r--r--spec/bundler/runtime/setup_spec.rb40
-rw-r--r--spec/bundler/spec_helper.rb3
-rw-r--r--spec/bundler/support/builders.rb2
-rw-r--r--spec/bundler/support/filters.rb3
-rw-r--r--spec/bundler/support/helpers.rb2
-rw-r--r--spec/bundler/support/indexes.rb4
-rw-r--r--spec/bundler/support/matchers.rb33
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb1
-rw-r--r--spec/bundler/support/sometimes.rb57
-rw-r--r--test/rubygems/data/null-required-ruby-version.gemspec.rzbin0 -> 403 bytes
-rw-r--r--test/rubygems/test_gem.rb93
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb18
-rw-r--r--test/rubygems/test_gem_config_file.rb10
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb45
-rw-r--r--test/rubygems/test_gem_ext_builder.rb24
-rw-r--r--test/rubygems/test_gem_installer.rb2
-rw-r--r--test/rubygems/test_gem_platform.rb37
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb6
-rw-r--r--test/rubygems/test_gem_requirement.rb36
-rw-r--r--test/rubygems/test_gem_specification.rb59
-rw-r--r--test/rubygems/test_gem_stream_ui.rb2
-rw-r--r--test/rubygems/test_gem_util.rb8
161 files changed, 2541 insertions, 1013 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index c72ad27c40..d370d8a53a 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -63,7 +63,6 @@ module Bundler
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
autoload :Retry, File.expand_path("bundler/retry", __dir__)
autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__)
- autoload :RubyGemsGemInstaller, File.expand_path("bundler/rubygems_gem_installer", __dir__)
autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__)
autoload :Runtime, File.expand_path("bundler/runtime", __dir__)
autoload :Settings, File.expand_path("bundler/settings", __dir__)
@@ -441,7 +440,7 @@ EOF
end
def local_platform
- return Gem::Platform::RUBY if settings[:force_ruby_platform]
+ return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY]
Gem::Platform.local
end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 249f5b2027..421f42cb52 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -586,6 +586,7 @@ module Bundler
method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library."
method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
+ method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library",
:desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "",
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index c14c8877f0..9cd6133879 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -30,6 +30,7 @@ module Bundler
require_relative "install"
options = self.options.dup
options["local"] = false if Bundler.settings[:cache_all_platforms]
+ options["no-cache"] = true
Bundler::CLI::Install.new(options).run
end
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index 6ef1473b1e..5b3d9c332e 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -39,11 +39,11 @@ module Bundler
constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase }
constant_array = constant_name.split("::")
- git_installed = Bundler.git_present?
+ use_git = Bundler.git_present? && options[:git]
- git_author_name = git_installed ? `git config user.name`.chomp : ""
- github_username = git_installed ? `git config github.user`.chomp : ""
- git_user_email = git_installed ? `git config user.email`.chomp : ""
+ git_author_name = use_git ? `git config user.name`.chomp : ""
+ github_username = use_git ? `git config github.user`.chomp : ""
+ git_user_email = use_git ? `git config user.email`.chomp : ""
config = {
:name => name,
@@ -58,7 +58,9 @@ module Bundler
:ext => options[:ext],
:exe => options[:exe],
:bundler_version => bundler_dependency_version,
+ :git => use_git,
:github_username => github_username.empty? ? "[USERNAME]" : github_username,
+ :required_ruby_version => Gem.ruby_version < Gem::Version.new("2.4.a") ? "2.3.0" : "2.4.0",
}
ensure_safe_gem_name(name, constant_array)
@@ -78,7 +80,7 @@ module Bundler
bin/setup
]
- templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present?
+ templates.merge!("gitignore.tt" => ".gitignore") if use_git
if test_framework = ask_and_set_test_framework
config[:test] = test_framework
@@ -141,12 +143,25 @@ module Bundler
templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
+ if ask_and_set(:changelog, "Do you want to include a changelog?",
+ "A changelog is a file which contains a curated, chronologically ordered list of notable " \
+ "changes for each version of a project. To make it easier for users and contributors to" \
+ " see precisely what notable changes have been made between each release (or version) of" \
+ " the project. Whether consumers or developers, the end users of software are" \
+ " human beings who care about what's in the software. When the software changes, people " \
+ "want to know why and how. see https://keepachangelog.com")
+ config[:changelog] = true
+ Bundler.ui.info "Changelog enabled in config"
+ templates.merge!("CHANGELOG.md.tt" => "CHANGELOG.md")
+ end
+
if ask_and_set(:rubocop, "Do you want to add rubocop as a dependency for gems you generate?",
"RuboCop is a static code analyzer that has out-of-the-box rules for many " \
"of the guidelines in the community style guide. " \
"For more information, see the RuboCop docs (https://docs.rubocop.org/en/stable/) " \
"and the Ruby Style Guides (https://github.com/rubocop-hq/ruby-style-guide).")
config[:rubocop] = true
+ config[:rubocop_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.81.0" : "1.7"
Bundler.ui.info "RuboCop enabled in config"
templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
end
@@ -161,24 +176,31 @@ module Bundler
)
end
+ if File.exist?(target) && !File.directory?(target)
+ Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
+ exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
+ end
+
+ if use_git
+ Bundler.ui.info "Initializing git repo in #{target}"
+ `git init #{target}`
+
+ config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
+ end
+
templates.each do |src, dst|
destination = target.join(dst)
- SharedHelpers.filesystem_access(destination) do
- thor.template("newgem/#{src}", destination, config)
- end
+ thor.template("newgem/#{src}", destination, config)
end
executables.each do |file|
- SharedHelpers.filesystem_access(target.join(file)) do |path|
- executable = (path.stat.mode | 0o111)
- path.chmod(executable)
- end
+ path = target.join(file)
+ executable = (path.stat.mode | 0o111)
+ path.chmod(executable)
end
- if Bundler.git_present? && options[:git]
- Bundler.ui.info "Initializing git repo in #{target}"
+ if use_git
Dir.chdir(target) do
- `git init`
`git add .`
end
end
@@ -188,8 +210,6 @@ module Bundler
Bundler.ui.info "Gem '#{name}' was successfully created. " \
"For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
- rescue Errno::EEXIST => e
- raise GenericSystemCallError.new(e, "There was a conflict while creating the new gem.")
end
private
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 66d1735583..9e0180fac7 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
require_relative "../vendored_fileutils"
-require "stringio"
-require "zlib"
module Bundler
class CompactIndexClient
@@ -45,24 +43,18 @@ module Bundler
else
"bytes=#{local_temp_path.size}-"
end
- else
- # Fastly ignores Range when Accept-Encoding: gzip is set
- headers["Accept-Encoding"] = "gzip"
end
response = @fetcher.call(remote_path, headers)
return nil if response.is_a?(Net::HTTPNotModified)
content = response.body
- if response["Content-Encoding"] == "gzip"
- content = Zlib::GzipReader.new(StringIO.new(content)).read
- end
SharedHelpers.filesystem_access(local_temp_path) do
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 349fa632a0..5f02b15e5f 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require_relative "lockfile_parser"
-require "set"
module Bundler
class Definition
@@ -88,11 +87,7 @@ module Bundler
@lockfile_contents = Bundler.read_file(lockfile)
@locked_gems = LockfileParser.new(@lockfile_contents)
@locked_platforms = @locked_gems.platforms
- if Bundler.settings[:force_ruby_platform]
- @platforms = [Gem::Platform::RUBY]
- else
- @platforms = @locked_platforms.dup
- end
+ @platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
@@ -264,23 +259,18 @@ module Bundler
def resolve
@resolve ||= begin
last_resolve = converge_locked_specs
- resolve =
- if Bundler.frozen_bundle?
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
- last_resolve
- elsif !unlocking? && nothing_changed?
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
- last_resolve
- else
- # 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)
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
- end
-
- # filter out gems that _can_ be installed on multiple platforms, but don't need
- # to be
- resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
+ if Bundler.frozen_bundle?
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
+ last_resolve
+ elsif !unlocking? && nothing_changed?
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
+ last_resolve
+ else
+ # 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, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
+ end
end
end
@@ -611,7 +601,7 @@ module Bundler
deps_for_source = @dependencies.select {|s| s.source == source }
locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
- Set.new(deps_for_source) != Set.new(locked_deps_for_source)
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
end
def specs_for_source_changed?(source)
@@ -673,19 +663,20 @@ module Bundler
def converge_rubygems_sources
return false if Bundler.feature_flag.disable_multisource?
- changes = false
-
# 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
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
@@ -825,11 +816,6 @@ module Bundler
# commonly happens if the version changed in the gemspec
next unless new_spec
- new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
- old_runtime_deps = s.dependencies.select {|d| d.type != :development }
- # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
- next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
-
s.dependencies.replace(new_spec.dependencies)
end
@@ -896,7 +882,7 @@ module Bundler
dependencies.each do |dep|
dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
next unless remote || dep.current_platform?
- target_platforms = dep.gem_platforms(remote ? Resolver.sort_platforms(@platforms) : [generic_local_platform])
+ target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
deps += expand_dependency_with_platforms(dep, target_platforms)
end
deps
@@ -904,7 +890,7 @@ module Bundler
def expand_dependency_with_platforms(dep, platforms)
platforms.map do |p|
- DepProxy.new(dep, p)
+ DepProxy.get_proxy(dep, p)
end
end
@@ -915,29 +901,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 Bundler.feature_flag.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
@@ -984,7 +959,7 @@ module Bundler
next requirements if @locked_gems.dependencies[name] != dependency
next requirements if dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
- requirements[name] = DepProxy.new(dep, locked_spec.platform)
+ requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
requirements
end.values
end
@@ -994,5 +969,17 @@ 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 = sources.default_source
+ dependencies.each do |dep|
+ dep_source = dep.source || default
+ source_requirements[dep.name] = dep_source
+ end
+ source_requirements
+ end
+ end
end
end
diff --git a/lib/bundler/dep_proxy.rb b/lib/bundler/dep_proxy.rb
index bb09fe9ea6..a32dc37b49 100644
--- a/lib/bundler/dep_proxy.rb
+++ b/lib/bundler/dep_proxy.rb
@@ -4,19 +4,18 @@ module Bundler
class DepProxy
attr_reader :__platform, :dep
+ @proxies = {}
+
+ def self.get_proxy(dep, platform)
+ @proxies[[dep, platform]] ||= new(dep, platform).freeze
+ end
+
def initialize(dep, platform)
@dep = dep
@__platform = platform
end
- def hash
- @hash ||= [dep, __platform].hash
- end
-
- def ==(other)
- return false if other.class != self.class
- dep == other.dep && __platform == other.__platform
- end
+ private_class_method :new
alias_method :eql?, :==
@@ -39,6 +38,14 @@ module Bundler
s
end
+ def dup
+ raise NoMethodError.new("DepProxy cannot be duplicated")
+ end
+
+ def clone
+ raise NoMethodError.new("DepProxy cannot be cloned")
+ end
+
private
def method_missing(*args, &blk)
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 1cc7908b8a..23fba99ffa 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,17 +438,33 @@ 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"
+
+ SharedHelpers.major_deprecation(2, msg.strip)
+ end
+
+ def check_rubygems_source_safety
+ @sources.global_rubygems_source = @global_rubygems_sources.shift
+ return if @global_rubygems_sources.empty?
+
+ @global_rubygems_sources.each do |source|
+ @sources.add_rubygems_remote(source)
+ end
if Bundler.feature_flag.disable_multisource?
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
+ "should come from that source. To downgrade this error to a warning, run " \
+ "`bundle config unset disable_multisource`"
raise GemfileEvalError, msg
else
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb
index a92ec8756d..a1b443b042 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -27,7 +27,6 @@ module Bundler
(1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
- settings_flag(:allow_bundler_dependency_conflicts) { bundler_3_mode? }
settings_flag(:allow_offline_install) { bundler_3_mode? }
settings_flag(:auto_clean_without_path) { bundler_3_mode? }
settings_flag(:cache_all) { bundler_3_mode? }
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index 2d9b4c2945..f9c54f7ad2 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -137,7 +137,6 @@ module Bundler
end
specs.each do |name, version, platform, dependencies, metadata|
- next if name == "bundler"
spec = if dependencies
EndpointSpecification.new(name, version, platform, dependencies, metadata)
else
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 0acaa69f25..d3e30124f9 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -116,19 +116,21 @@ module Bundler
def git_push(remote = nil)
remote ||= default_remote
- perform_git_push remote
+ perform_git_push "#{remote} refs/heads/#{current_branch}"
perform_git_push "#{remote} refs/tags/#{version_tag}"
Bundler.ui.confirm "Pushed git commits and release tag."
end
def default_remote
- # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0
- current_branch = sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip
+ remote_for_branch, status = sh_with_status(%W[git config --get branch.#{current_branch}.remote])
+ return "origin" unless status.success?
- remote_for_branch = sh(%W[git config --get branch.#{current_branch}.remote]).strip
- return "origin" if remote_for_branch.empty?
+ remote_for_branch.strip
+ end
- remote_for_branch
+ def current_branch
+ # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0
+ sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip
end
def allowed_push_host
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index 2e87b7d443..3cce3f2139 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -81,8 +81,8 @@ module Bundler
sort_dep_specs(spec_groups, locked_spec)
end.tap do |specs|
if DEBUG
- warn before_result
- warn " after sort_versions: #{debug_format_result(dep, specs).inspect}"
+ puts before_result
+ puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
end
end
end
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index f26f542fde..f945176037 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "set"
-
module Bundler
class Index
include Enumerable
@@ -65,11 +63,14 @@ module Bundler
def unsorted_search(query, base)
results = local_search(query, base)
- seen = results.map(&:full_name).to_set unless @sources.empty?
+ seen = results.map(&:full_name).uniq unless @sources.empty?
@sources.each do |source|
source.unsorted_search(query, base).each do |spec|
- results << spec if seen.add?(spec.full_name)
+ next if seen.include?(spec.full_name)
+
+ seen << spec.full_name
+ results << spec
end
end
@@ -170,7 +171,7 @@ module Bundler
def dependencies_eql?(spec, other_spec)
deps = spec.dependencies.select {|d| d.type != :development }
other_deps = other_spec.dependencies.select {|d| d.type != :development }
- Set.new(deps) == Set.new(other_deps)
+ deps.sort == other_deps.sort
end
def add_source(index)
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/installer.rb b/lib/bundler/installer.rb
index 048b0786a7..09c8b1c157 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -82,7 +82,6 @@ module Bundler
if resolve_if_needed(options)
ensure_specs_are_compatible!
- warn_on_incompatible_bundler_deps
load_plugins
options.delete(:jobs)
else
@@ -90,6 +89,8 @@ module Bundler
end
install(options)
+ Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
+
lock unless Bundler.frozen_bundle?
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
@@ -265,22 +266,6 @@ module Bundler
end
end
- def warn_on_incompatible_bundler_deps
- bundler_version = Gem::Version.create(Bundler::VERSION)
- @definition.specs.each do |spec|
- spec.dependencies.each do |dep|
- next if dep.type == :development
- next unless dep.name == "bundler".freeze
- next if dep.requirement.satisfied_by?(bundler_version)
-
- Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \
- " #{SharedHelpers.pretty_dependency(dep)}" \
- ", which is unsatisfied by the current bundler version #{VERSION}" \
- ", so the dependency is being ignored"
- end
- end
- end
-
def install_in_parallel(size, standalone, force = false)
spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force)
spec_installations.each do |installation|
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index 0720d6d38a..2a3f5cfe35 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -15,6 +15,7 @@ module Bundler
file.puts "ruby_engine = RUBY_ENGINE"
file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
file.puts "path = File.expand_path('..', __FILE__)"
+ file.puts reverse_rubygems_kernel_mixin
paths.each do |path|
file.puts %($:.unshift File.expand_path("\#{path}/#{path}"))
end
@@ -48,5 +49,19 @@ module Bundler
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
raise Gem::InvalidSpecificationException.new(error_message)
end
+
+ def reverse_rubygems_kernel_mixin
+ <<~END
+ kernel = (class << ::Kernel; self; end)
+ [kernel, ::Kernel].each do |k|
+ if k.private_method_defined?(:gem_original_require)
+ private_require = k.private_method_defined?(:require)
+ k.send(:remove_method, :require)
+ k.send(:define_method, :require, k.instance_method(:gem_original_require))
+ k.send(:private, :require) if private_require
+ end
+ end
+ END
+ end
end
end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 1081910816..04ba2a2364 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -4,22 +4,6 @@ require_relative "match_platform"
module Bundler
class LazySpecification
- Identifier = Struct.new(:name, :version, :platform)
- class Identifier
- include Comparable
- def <=>(other)
- return unless other.is_a?(Identifier)
- [name, version, platform_string] <=> [other.name, other.version, other.platform_string]
- end
-
- protected
-
- def platform_string
- platform_string = platform.to_s
- platform_string == Index::RUBY ? Index::NULL : platform_string
- end
- end
-
include MatchPlatform
attr_reader :name, :version, :dependencies, :platform
@@ -108,7 +92,7 @@ module Bundler
end
def identifier
- @__identifier ||= Identifier.new(name, version, platform)
+ @__identifier ||= [name, version, platform_string]
end
def git_version
@@ -116,6 +100,13 @@ module Bundler
" #{source.revision[0..6]}"
end
+ protected
+
+ def platform_string
+ platform_string = platform.to_s
+ platform_string == Index::RUBY ? Index::NULL : platform_string
+ end
+
private
def to_ary
@@ -140,7 +131,7 @@ module Bundler
# explicitly add a more specific platform.
#
def ruby_platform_materializes_to_ruby_platform?
- !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY)
+ !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform]
end
end
end
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-add.1 b/lib/bundler/man/bundle-add.1
index 29b2cadf33..b44295b2d3 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-ADD" "1" "December 2020" "" ""
+.TH "BUNDLE\-ADD" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index 6ba4ed914d..99876d023e 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-BINSTUBS" "1" "December 2020" "" ""
+.TH "BUNDLE\-BINSTUBS" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 8aa45ca213..3b3c6f9734 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CACHE" "1" "December 2020" "" ""
+.TH "BUNDLE\-CACHE" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index 5013cd8cda..4436c3e971 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CHECK" "1" "December 2020" "" ""
+.TH "BUNDLE\-CHECK" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index 231ce273a8..b7e882ecbf 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CLEAN" "1" "December 2020" "" ""
+.TH "BUNDLE\-CLEAN" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index f690b0a8f0..ad36c6bde0 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CONFIG" "1" "December 2020" "" ""
+.TH "BUNDLE\-CONFIG" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
@@ -136,9 +136,6 @@ Any periods in the configuration keys must be replaced with two underscores when
The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\.
.
.IP "\(bu" 4
-\fBallow_bundler_dependency_conflicts\fR (\fBBUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS\fR): Allow resolving to specifications that have dependencies on \fBbundler\fR that are incompatible with the running Bundler version\.
-.
-.IP "\(bu" 4
\fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR
.
.IP "\(bu" 4
@@ -184,6 +181,9 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\.
.
.IP "\(bu" 4
+\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
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 7ca5dbed72..90ec5ab59e 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -133,9 +133,6 @@ the environment variable `BUNDLE_LOCAL__RACK`.
The following is a list of all configuration keys and their purpose. You can
learn more about their operation in [bundle install(1)](bundle-install.1.html).
-* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`):
- Allow resolving to specifications that have dependencies on `bundler` that
- are incompatible with the running Bundler version.
* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`):
When in deployment mode, allow changing the credentials to a gem's source.
Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path`
@@ -178,6 +175,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`):
Allow Bundler to use a local git override without a branch specified in the
Gemfile.
+* `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.
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index dd3471cfa9..2923517608 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-DOCTOR" "1" "December 2020" "" ""
+.TH "BUNDLE\-DOCTOR" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index 374d2b11ed..aa0c509278 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-EXEC" "1" "December 2020" "" ""
+.TH "BUNDLE\-EXEC" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 2ec18ecc65..c1abf90f5c 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-GEM" "1" "December 2020" "" ""
+.TH "BUNDLE\-GEM" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index e7386e3699..c715af4063 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INFO" "1" "December 2020" "" ""
+.TH "BUNDLE\-INFO" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 756dc2c67c..6c8f441bdd 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INIT" "1" "December 2020" "" ""
+.TH "BUNDLE\-INIT" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index 4c66eaf78f..2342b44716 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INJECT" "1" "December 2020" "" ""
+.TH "BUNDLE\-INJECT" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index 34dca1f0bc..c223185b6f 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INSTALL" "1" "December 2020" "" ""
+.TH "BUNDLE\-INSTALL" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index ec507a566b..929b0f79f8 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LIST" "1" "December 2020" "" ""
+.TH "BUNDLE\-LIST" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 6f468db581..bcf588a3cf 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LOCK" "1" "December 2020" "" ""
+.TH "BUNDLE\-LOCK" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index 7131bfad9f..27308ff624 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OPEN" "1" "December 2020" "" ""
+.TH "BUNDLE\-OPEN" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index 8c6ce260c8..40b23568d5 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OUTDATED" "1" "December 2020" "" ""
+.TH "BUNDLE\-OUTDATED" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index cd8eeb29c0..d0ec5c643c 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PLATFORM" "1" "December 2020" "" ""
+.TH "BUNDLE\-PLATFORM" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index 4fc59626bd..9fd42d04a4 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PRISTINE" "1" "December 2020" "" ""
+.TH "BUNDLE\-PRISTINE" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index 764b33527a..366e5f4be2 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-REMOVE" "1" "December 2020" "" ""
+.TH "BUNDLE\-REMOVE" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index 25cbddf5fb..e2de241438 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-SHOW" "1" "December 2020" "" ""
+.TH "BUNDLE\-SHOW" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index a97692911c..a78633bbf8 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-UPDATE" "1" "December 2020" "" ""
+.TH "BUNDLE\-UPDATE" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index c84a0bd8b1..fead09e6ad 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-VIZ" "1" "December 2020" "" ""
+.TH "BUNDLE\-VIZ" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index 58043ff91d..50aa6e17c7 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE" "1" "December 2020" "" ""
+.TH "BUNDLE" "1" "January 2021" "" ""
.
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index d6c26d91ef..460295da4d 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "GEMFILE" "5" "December 2020" "" ""
+.TH "GEMFILE" "5" "January 2021" "" ""
.
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
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..980b0e29b8 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
@@ -79,7 +77,7 @@ module Bundler
source_list = SourceList.new
source_list.add_git_source(git_source_options) if git_source_options
- source_list.add_rubygems_source("remotes" => rubygems_source) if rubygems_source
+ source_list.global_rubygems_source = rubygems_source if rubygems_source
deps = names.map {|name| Dependency.new name, version }
diff --git a/lib/bundler/plugin/source_list.rb b/lib/bundler/plugin/source_list.rb
index b90a331d28..547661cf2f 100644
--- a/lib/bundler/plugin/source_list.rb
+++ b/lib/bundler/plugin/source_list.rb
@@ -17,6 +17,10 @@ module Bundler
path_sources + git_sources + rubygems_sources + [metadata_source]
end
+ def default_source
+ git_sources.first || global_rubygems_source
+ end
+
private
def rubygems_aggregate_class
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 636dc8af46..69899dc6c3 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -5,6 +5,8 @@ module Bundler
require_relative "vendored_molinillo"
require_relative "resolver/spec_group"
+ include GemHelpers
+
# Figures out the best possible configuration of gems that satisfies
# the list of passed dependencies and any child dependencies without
# causing any gem activation errors.
@@ -15,31 +17,38 @@ 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)
- platforms = Set.new(platforms) if platforms
+ 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
+
+ @index_requirements = source_requirements.each_with_object({}) do |source_requirement, index_requirements|
+ name, source = source_requirement
+ index_requirements[name] = name == :global ? source : source.specs
+ end
+
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
@base.each do |ls|
dep = Dependency.new(ls.name, ls.version)
- @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
+ @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
- @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
@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 = ["Ruby\0", "RubyGems\0"]
end
def start(requirements)
@@ -75,7 +84,7 @@ module Bundler
return unless debug?
debug_info = yield
debug_info = debug_info.inspect unless debug_info.is_a?(String)
- puts debug_info.split("\n").map {|s| "BUNDLER: " + " " * depth + s }
+ puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
end
def debug?
@@ -103,16 +112,25 @@ module Bundler
include Molinillo::SpecificationProvider
def dependencies_for(specification)
- specification.dependencies_for_activated_platforms
+ all_dependencies = specification.dependencies_for_activated_platforms
+
+ if @variant_specific_names.include?(specification.name)
+ @variant_specific_names |= all_dependencies.map(&:name) - @generic_names
+ else
+ generic_names, variant_specific_names = specification.partitioned_dependency_names_for_activated_platforms
+ @variant_specific_names |= variant_specific_names - @generic_names
+ @generic_names |= generic_names
+ end
+
+ all_dependencies
end
def search_for(dependency_proxy)
platform = dependency_proxy.__platform
dependency = dependency_proxy.dep
- @search_for[dependency_proxy] ||= begin
- name = dependency.name
- index = index_for(dependency)
- results = index.search(dependency, @base[name])
+ name = dependency.name
+ search_result = @search_for[dependency_proxy] ||= begin
+ results = results_for(dependency, @base[name])
if vertex = @base_dg.vertex_named(name)
locked_requirement = vertex.payload.requirement
@@ -137,55 +155,67 @@ module Bundler
end
nested.reduce([]) do |groups, (version, specs)|
next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
- spec_group = SpecGroup.new(specs)
- spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
- groups << spec_group
+
+ specs_by_platform = Hash.new do |current_specs, current_platform|
+ current_specs[current_platform] = select_best_platform_match(specs, current_platform)
+ end
+
+ spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
+ groups << spec_group_ruby if spec_group_ruby
+
+ next groups if @resolving_only_for_ruby
+
+ spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
+ groups << spec_group if spec_group
+
+ groups
end
else
[]
end
# GVP handles major itself, but it's still a bit risky to trust it with it
# until we get it settled with new behavior. For 2.x it can take over all cases.
- search = if !@use_gvp
+ if !@use_gvp
spec_groups
else
@gem_version_promoter.sort_versions(dependency, spec_groups)
end
- selected_sgs = []
- search.each do |sg|
- next unless sg.for?(platform)
- sg_all_platforms = sg.copy_for(self.class.sort_platforms(@platforms).reverse)
- next unless sg_all_platforms
-
- selected_sgs << sg_all_platforms
-
- next if sg_all_platforms.activated_platforms == [Gem::Platform::RUBY]
- # Add a spec group for "non platform specific spec" as the fallback
- # spec group.
- sg_ruby = sg.copy_for([Gem::Platform::RUBY])
- selected_sgs.insert(-2, sg_ruby) if sg_ruby
+ end
+
+ unless search_result.empty?
+ specific_dependency = @variant_specific_names.include?(name)
+ return search_result unless specific_dependency
+
+ search_result.each do |sg|
+ if @generic_names.include?(name)
+ @variant_specific_names -= [name]
+ sg.activate_all_platforms!
+ else
+ sg.activate_platform!(platform)
+ end
end
- selected_sgs
end
+
+ search_result
end
def index_for(dependency)
- source = @source_requirements[dependency.name]
+ source = @index_requirements[dependency.name]
if source
- source.specs
- elsif @lockfile_uses_separate_rubygems_sources
+ source
+ elsif @no_aggregate_global_source
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
+ dependency.all_sources.each {|s| idx.add_source(s.specs) }
end
else
- @index
+ @index_requirements[:global]
end
end
+ def results_for(dependency, base)
+ index_for(dependency).search(dependency, base)
+ end
+
def name_for(dependency)
dependency.name
end
@@ -206,21 +236,27 @@ module Bundler
requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
end
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies.map(&:dep) == other_dependencies.map(&:dep)
+ end
+
def relevant_sources_for_vertex(vertex)
if vertex.root?
[@source_requirements[vertex.name]]
- elsif @lockfile_uses_separate_rubygems_sources
+ 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
def sort_dependencies(dependencies, activated, conflicts)
dependencies.sort_by do |dependency|
- dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
name = name_for(dependency)
vertex = activated.vertex_named(name)
+ dependency.all_sources = relevant_sources_for_vertex(vertex)
[
@base_dg.vertex_named(name) ? 0 : 1,
vertex.payload ? 0 : 1,
@@ -233,13 +269,6 @@ module Bundler
end
end
- # Sort platforms from most general to most specific
- def self.sort_platforms(platforms)
- platforms.sort_by do |platform|
- platform_sort_key(platform)
- end
- end
-
def self.platform_sort_key(platform)
# Prefer specific platform to not specific platform
return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform
@@ -294,7 +323,7 @@ module Bundler
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
elsif source = @source_requirements[name]
- specs = source.specs[name]
+ specs = source.specs.search(name)
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
message << if versions_with_platforms.any?
@@ -303,7 +332,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
@@ -324,10 +353,16 @@ module Bundler
def version_conflict_message(e)
# only show essential conflicts, if possible
conflicts = e.conflicts.dup
- conflicts.delete_if do |_name, conflict|
- deps = conflict.requirement_trees.map(&:last).flatten(1)
- !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
+
+ if conflicts["bundler"]
+ conflicts.replace("bundler" => conflicts["bundler"])
+ else
+ conflicts.delete_if do |_name, conflict|
+ deps = conflict.requirement_trees.map(&:last).flatten(1)
+ !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
+ end
end
+
e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
solver_name = "Bundler"
@@ -355,15 +390,25 @@ module Bundler
:additional_message_for_conflict => lambda do |o, name, conflict|
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
- other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
- end
- if name == "bundler" && other_bundler_required
- o << "\n"
- o << "This Gemfile requires a different version of Bundler.\n"
- o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
- end
- if conflict.locked_requirement
+ conflict_dependency = conflict.requirement
+ conflict_requirement = conflict_dependency.requirement
+ other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
+
+ if other_bundler_required
+ o << "\n\n"
+
+ candidate_specs = @index_requirements[:default_bundler].search(conflict_dependency)
+ if candidate_specs.any?
+ target_version = candidate_specs.last.version
+ new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
+ o << "Your bundle requires a different version of Bundler than the one you're running.\n"
+ o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
+ else
+ o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
+ end
+ end
+ elsif conflict.locked_requirement
o << "\n"
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
@@ -372,14 +417,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")
@@ -416,23 +455,21 @@ 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.compact!
+ sources = relevant_sources_for_vertex(v)
+ next unless sources.any?
if default_index = sources.index(@source_requirements[:default])
sources.delete_at(default_index)
end
- sources.reject! {|s| s.specs[name].empty? }
+ sources.reject! {|s| s.specs.search(name).empty? }
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/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index 34780f9528..73ffec5838 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -3,28 +3,37 @@
module Bundler
class Resolver
class SpecGroup
- include GemHelpers
-
attr_accessor :name, :version, :source
- attr_accessor :ignores_bundler_dependencies, :activated_platforms
+ attr_accessor :activated_platforms
+
+ def self.create_for(specs, all_platforms, specific_platform)
+ specific_platform_specs = specs[specific_platform]
+ return unless specific_platform_specs.any?
+
+ platforms = all_platforms.select {|p| specs[p].any? }
+
+ new(specific_platform_specs.first, specs, platforms)
+ end
- def initialize(all_specs)
- @all_specs = all_specs
- raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
+ def initialize(exemplary_spec, specs, relevant_platforms)
+ @exemplary_spec = exemplary_spec
@name = exemplary_spec.name
@version = exemplary_spec.version
@source = exemplary_spec.source
- @activated_platforms = []
- @dependencies = nil
- @specs = Hash.new do |specs, platform|
- specs[platform] = select_best_platform_match(all_specs, platform)
+ @all_platforms = relevant_platforms
+ @activated_platforms = relevant_platforms
+ @dependencies = Hash.new do |dependencies, platforms|
+ dependencies[platforms] = dependencies_for(platforms)
end
- @ignores_bundler_dependencies = true
+ @partitioned_dependency_names = Hash.new do |partitioned_dependency_names, platforms|
+ partitioned_dependency_names[platforms] = partitioned_dependency_names_for(platforms)
+ end
+ @specs = specs
end
def to_specs
- @activated_platforms.map do |p|
+ activated_platforms.map do |p|
specs = @specs[p]
next unless specs.any?
@@ -36,18 +45,12 @@ module Bundler
end.flatten.compact.uniq
end
- def copy_for(platforms)
- platforms.select! {|p| for?(p) }
- return unless platforms.any?
-
- copied_sg = self.class.new(@all_specs)
- copied_sg.ignores_bundler_dependencies = @ignores_bundler_dependencies
- copied_sg.activated_platforms = platforms
- copied_sg
+ def activate_platform!(platform)
+ self.activated_platforms = [platform]
end
- def for?(platform)
- @specs[platform].any?
+ def activate_all_platforms!
+ self.activated_platforms = @all_platforms
end
def to_s
@@ -56,11 +59,11 @@ module Bundler
end
def dependencies_for_activated_platforms
- dependencies = @activated_platforms.map {|p| __dependencies[p] }
- metadata_dependencies = @activated_platforms.map do |platform|
- metadata_dependencies(@specs[platform].first, platform)
- end
- dependencies.concat(metadata_dependencies).flatten
+ @dependencies[activated_platforms]
+ end
+
+ def partitioned_dependency_names_for_activated_platforms
+ @partitioned_dependency_names[activated_platforms]
end
def ==(other)
@@ -86,34 +89,43 @@ module Bundler
protected
def sorted_activated_platforms
- @activated_platforms.sort_by(&:to_s)
+ activated_platforms.sort_by(&:to_s)
end
private
- def __dependencies
- @dependencies = Hash.new do |dependencies, platform|
- dependencies[platform] = []
- specs = @specs[platform]
- if spec = specs.first
- spec.dependencies.each do |dep|
- next if dep.type == :development
- next if @ignores_bundler_dependencies && dep.name == "bundler".freeze
- dependencies[platform] << DepProxy.new(dep, platform)
- end
- end
- dependencies[platform]
+ def dependencies_for(platforms)
+ platforms.map do |platform|
+ __dependencies(platform) + metadata_dependencies(platform)
+ end.flatten
+ end
+
+ def partitioned_dependency_names_for(platforms)
+ return @dependencies[platforms].map(&:name), [] if platforms.size == 1
+
+ @dependencies[platforms].partition do |dep_proxy|
+ @dependencies[platforms].count {|dp| dp.dep == dep_proxy.dep } == platforms.size
+ end.map {|deps| deps.map(&:name) }
+ end
+
+ def __dependencies(platform)
+ dependencies = []
+ @specs[platform].first.dependencies.each do |dep|
+ next if dep.type == :development
+ dependencies << DepProxy.get_proxy(dep, platform)
end
+ dependencies
end
- def metadata_dependencies(spec, platform)
- return [] unless spec && spec.is_a?(Gem::Specification)
+ def metadata_dependencies(platform)
+ spec = @specs[platform].first
+ return [] unless spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
+ dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
+ dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
end
dependencies
end
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 0322b06d07..2bd2dcb451 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -158,6 +158,22 @@ module Gem
end
end
+ if Gem::Requirement.new("~> 2.0").hash == Gem::Requirement.new("~> 2.0.0").hash
+ class Requirement
+ module CorrectHashForLambdaOperator
+ def hash
+ if requirements.any? {|r| r.first == "~>" }
+ requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
+ else
+ super
+ end
+ end
+ end
+
+ prepend CorrectHashForLambdaOperator
+ end
+ end
+
class Platform
JAVA = Gem::Platform.new("java") unless defined?(JAVA)
MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index cd5eb152f9..f5f3c53309 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -8,6 +8,53 @@ module Bundler
# Bundler needs to install gems regardless of binstub overwriting
end
+ def install
+ pre_install_checks
+
+ run_pre_install_hooks
+
+ spec.loaded_from = spec_file
+
+ # Completely remove any previous gem files
+ FileUtils.rm_rf gem_dir
+ FileUtils.rm_rf spec.extension_dir
+
+ FileUtils.mkdir_p gem_dir, :mode => 0o755
+
+ extract_files
+
+ build_extensions
+ write_build_info_file
+ run_post_build_hooks
+
+ generate_bin
+ generate_plugins
+
+ write_spec
+ write_cache_file
+
+ say spec.post_install_message unless spec.post_install_message.nil?
+
+ run_post_install_hooks
+
+ spec
+ end
+
+ def generate_plugins
+ return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
+
+ latest = Gem::Specification.stubs_for(spec.name).first
+ return if latest && latest.version > spec.version
+
+ ensure_writable_dir @plugins_dir
+
+ if spec.plugins.empty?
+ remove_plugins_for(spec, @plugins_dir)
+ else
+ regenerate_plugins_for(spec, @plugins_dir)
+ end
+ end
+
def pre_install_checks
super && validate_bundler_checksum(options[:bundler_expected_checksum])
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index 1c669491f6..749e4eb60e 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -7,7 +7,6 @@ module Bundler
autoload :Validator, File.expand_path("settings/validator", __dir__)
BOOL_KEYS = %w[
- allow_bundler_dependency_conflicts
allow_deployment_source_credential_changes
allow_offline_install
auto_clean_without_path
@@ -20,6 +19,7 @@ module Bundler
disable_checksum_validation
disable_exec_load
disable_local_branch_check
+ disable_local_revision_check
disable_multisource
disable_shared_gems
disable_version_check
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index a56a3bff4b..f43e3301ef 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -187,11 +187,11 @@ module Bundler
return @md5_available if defined?(@md5_available)
@md5_available = begin
require "openssl"
- OpenSSL::Digest.digest("MD5", "")
+ ::OpenSSL::Digest.digest("MD5", "")
true
rescue LoadError
true
- rescue OpenSSL::Digest::DigestError
+ rescue ::OpenSSL::Digest::DigestError
false
end
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 0157995cb0..fb13ca0578 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -22,7 +22,7 @@ module Bundler
@uri = options["uri"] || ""
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
- @ref = options["ref"] || options["branch"] || options["tag"] || "master"
+ @ref = options["ref"] || options["branch"] || options["tag"]
@submodules = options["submodules"]
@name = options["name"]
@version = options["version"].to_s.strip.gsub("-", ".pre.")
@@ -60,25 +60,27 @@ module Bundler
alias_method :==, :eql?
def to_s
- at = if local?
- path
- elsif user_ref = options["ref"]
- if ref =~ /\A[a-z0-9]{4,}\z/i
- shortref_for_display(user_ref)
+ begin
+ at = if local?
+ path
+ elsif user_ref = options["ref"]
+ if ref =~ /\A[a-z0-9]{4,}\z/i
+ shortref_for_display(user_ref)
+ else
+ user_ref
+ end
+ elsif ref
+ ref
else
- user_ref
+ git_proxy.branch
end
- else
- ref
- end
- rev = begin
- "@#{shortref_for_display(revision)}"
- rescue GitError
- nil
- end
+ rev = " (at #{at}@#{shortref_for_display(revision)})"
+ rescue GitError
+ ""
+ end
- "#{@safe_uri} (at #{at}#{rev})"
+ "#{@safe_uri}#{rev}"
end
def name
@@ -146,7 +148,7 @@ module Bundler
changed = cached_revision && cached_revision != git_proxy.revision
- if changed && !@unlocked && !git_proxy.contains?(cached_revision)
+ if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
"but the current branch in your local override for #{name} does not contain such commit. " \
"Please make sure your branch is up to date."
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index dd65c674d8..ae21770306 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -17,7 +17,7 @@ module Bundler
class GitNotAllowedError < GitError
def initialize(command)
msg = String.new
- msg << "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, "
+ msg << "Bundler is trying to run `#{command}` at runtime. You probably need to run `bundle install`. However, "
msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md "
msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
super msg
@@ -27,11 +27,11 @@ module Bundler
class GitCommandError < GitError
attr_reader :command
- def initialize(command, path, destination_path, extra_info = nil)
+ def initialize(command, path, extra_info = nil)
@command = command
msg = String.new
- msg << "Git error: command `git #{command}` in directory #{destination_path} has failed."
+ msg << "Git error: command `#{command}` in directory #{path} has failed."
msg << "\n#{extra_info}" if extra_info
msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
super msg
@@ -39,9 +39,9 @@ module Bundler
end
class MissingGitRevisionError < GitCommandError
- def initialize(command, path, destination_path, ref, repo)
+ def initialize(command, destination_path, ref, repo)
msg = "Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?"
- super command, path, destination_path, msg
+ super command, destination_path, msg
end
end
@@ -132,7 +132,7 @@ module Bundler
begin
git "reset", "--hard", @revision, :dir => destination
rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
+ raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
end
if submodules
@@ -145,32 +145,36 @@ module Bundler
private
- def git_null(*command, dir: SharedHelpers.pwd)
+ def git_null(*command, dir: nil)
check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
- capture_and_ignore_stderr("git", "-C", dir.to_s, *command)
+ capture_and_ignore_stderr(*capture3_args_for(command, dir))
end
[URICredentialsFilter.credential_filtered_string(out, uri), status]
end
- def git_retry(*command, dir: SharedHelpers.pwd)
- Bundler::Retry.new("`git -C #{dir} #{URICredentialsFilter.credential_filtered_string(command.shelljoin, uri)}`", GitNotAllowedError).attempts do
+ def git_retry(*command, dir: nil)
+ command_with_no_credentials = check_allowed(command)
+
+ Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do
git(*command, :dir => dir)
end
end
- def git(*command, dir: SharedHelpers.pwd)
+ def git(*command, dir: nil)
command_with_no_credentials = check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
- capture_and_filter_stderr("git", "-C", dir.to_s, *command)
+ capture_and_filter_stderr(*capture3_args_for(command, dir))
end
- raise GitCommandError.new(command_with_no_credentials, path, dir) unless status.success?
+ filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
+
+ raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success?
- URICredentialsFilter.credential_filtered_string(out, uri)
+ filtered_out
end
def has_revision_cached?
@@ -187,10 +191,10 @@ module Bundler
def find_local_revision
allowed_with_path do
- git("rev-parse", "--verify", ref, :dir => path).strip
+ git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
end
rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
+ raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
end
# Adds credentials to the URI as Fetcher#configured_uri_for does
@@ -220,7 +224,7 @@ module Bundler
end
def check_allowed(command)
- command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command.shelljoin, uri)
+ command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
command_with_no_credentials
end
@@ -237,6 +241,20 @@ module Bundler
return_value, _, status = Open3.capture3(*cmd)
[return_value, status]
end
+
+ def capture3_args_for(cmd, dir)
+ return ["git", *cmd] unless dir
+
+ if Bundler.feature_flag.bundler_3_mode? || supports_minus_c?
+ ["git", "-C", dir.to_s, *cmd]
+ else
+ ["git", *cmd, { :chdir => dir.to_s }]
+ end
+ end
+
+ def supports_minus_c?
+ @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
+ end
end
end
end
diff --git a/lib/bundler/source/path/installer.rb b/lib/bundler/source/path/installer.rb
index 6be58e2087..72bfbb4836 100644
--- a/lib/bundler/source/path/installer.rb
+++ b/lib/bundler/source/path/installer.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "../../rubygems_gem_installer"
+
module Bundler
class Source
class Path
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 79ad278da3..5b89b1645d 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -145,6 +145,8 @@ module Bundler
Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
+ require_relative "../rubygems_gem_installer"
+
installed_spec = Bundler::RubyGemsGemInstaller.at(
path,
:install_dir => install_path.to_s,
@@ -351,7 +353,6 @@ module Bundler
def installed_specs
@installed_specs ||= Index.build do |idx|
Bundler.rubygems.all_specs.reverse_each do |spec|
- next if spec.name == "bundler"
spec.source = self
if Bundler.rubygems.spec_missing_extensions?(spec, false)
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 731a791531..44b167ca3e 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -1,21 +1,23 @@
# frozen_string_literal: true
-require "set"
-
module Bundler
class SourceList
attr_reader :path_sources,
:git_sources,
:plugin_sources,
- :global_rubygems_source,
+ :global_path_source,
:metadata_source
+ 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
end
@@ -24,7 +26,9 @@ module Bundler
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
@@ -43,24 +47,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
@@ -96,10 +96,9 @@ module Bundler
replacement_rubygems = !Bundler.feature_flag.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.to_set != replacement_rubygems.remotes.to_set
false
end
@@ -112,10 +111,6 @@ module Bundler
all_sources.each(&:remote!)
end
- def rubygems_primary_remotes
- @rubygems_aggregate.remotes
- end
-
private
def rubygems_aggregate_class
@@ -153,7 +148,7 @@ module Bundler
end
def equal_sources?(lock_sources, replacement_sources)
- lock_sources.to_set == replacement_sources.to_set
+ lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
end
def equal_source?(source, other_source)
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index a0b9552c18..399c91fea5 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require "tsort"
-require "set"
module Bundler
class SpecSet
@@ -13,14 +12,16 @@ module Bundler
end
def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
- handled = Set.new
+ handled = []
deps = dependencies.dup
specs = []
skip += ["bundler"]
loop do
break unless dep = deps.shift
- next if !handled.add?(dep) || skip.include?(dep.name)
+ next if handled.include?(dep) || skip.include?(dep.name)
+
+ handled << dep
specs_for_dep = spec_for_dependency(dep, match_current_platform)
if specs_for_dep.any?
@@ -28,7 +29,7 @@ module Bundler
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
- d = DepProxy.new(d, dep.__platform) unless match_current_platform
+ d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
deps << d
end
elsif check
diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb
index 2456d268da..fa071901e5 100644
--- a/lib/bundler/stub_specification.rb
+++ b/lib/bundler/stub_specification.rb
@@ -26,11 +26,19 @@ module Bundler
# @!group Stub Delegates
+ def manually_installed?
+ # This is for manually installed gems which are gems that were fixed in place after a
+ # failed installation. Once the issue was resolved, the user then manually created
+ # the gem specification using the instructions provided by `gem help install`
+ installed_by_version == Gem::Version.new(0)
+ end
+
# This is defined directly to avoid having to loading the full spec
def missing_extensions?
return false if default_gem?
return false if extensions.empty?
return false if File.exist? gem_build_complete_path
+ return false if manually_installed?
true
end
diff --git a/lib/bundler/templates/newgem/CHANGELOG.md.tt b/lib/bundler/templates/newgem/CHANGELOG.md.tt
new file mode 100644
index 0000000000..c9ea96d453
--- /dev/null
+++ b/lib/bundler/templates/newgem/CHANGELOG.md.tt
@@ -0,0 +1,5 @@
+## [Unreleased]
+
+## [0.1.0] - <%= Time.now.strftime('%F') %>
+
+- Initial release
diff --git a/lib/bundler/templates/newgem/Gemfile.tt b/lib/bundler/templates/newgem/Gemfile.tt
index 1d55fd7a90..b09ccfff15 100644
--- a/lib/bundler/templates/newgem/Gemfile.tt
+++ b/lib/bundler/templates/newgem/Gemfile.tt
@@ -16,5 +16,5 @@ gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>"
<%- end -%>
<%- if config[:rubocop] -%>
-gem "rubocop", "~> 0.80"
+gem "rubocop", "~> <%= config[:rubocop_version] %>"
<%- end -%>
diff --git a/lib/bundler/templates/newgem/README.md.tt b/lib/bundler/templates/newgem/README.md.tt
index 315bc745a3..8fd87abe9a 100644
--- a/lib/bundler/templates/newgem/README.md.tt
+++ b/lib/bundler/templates/newgem/README.md.tt
@@ -29,19 +29,21 @@ TODO: Write usage instructions here
After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test].sub('mini', '').sub('rspec', 'spec') %>` to run the tests.<% end %> You can also run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the gem in this directory, ignoring other installed copies of this gem.<% end %>
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
+<% if config[:git] -%>
## Contributing
-Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).<% end %>
+Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).<% end %>
+<% end -%>
<% if config[:mit] -%>
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
<% end -%>
-<% if config[:coc] -%>
+<% if config[:git] && config[:coc] -%>
## Code of Conduct
-Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).
+Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).
<% end -%>
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 4ed00bc749..5be20c7e4b 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
<%- if config[:mit] -%>
spec.license = "MIT"
<%- end -%>
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = Gem::Requirement.new(">= <%= config[:required_ruby_version] %>")
spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
diff --git a/lib/bundler/templates/newgem/rubocop.yml.tt b/lib/bundler/templates/newgem/rubocop.yml.tt
index 00a72e3006..9ecec78807 100644
--- a/lib/bundler/templates/newgem/rubocop.yml.tt
+++ b/lib/bundler/templates/newgem/rubocop.yml.tt
@@ -1,3 +1,6 @@
+AllCops:
+ TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
+
Style/StringLiterals:
Enabled: true
EnforcedStyle: double_quotes
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
index ec9c770a28..f8c695c1ed 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
@@ -26,6 +26,13 @@ module Bundler::Molinillo
end
end
+ # (see Bundler::Molinillo::SpecificationProvider#dependencies_equal?)
+ def dependencies_equal?(dependencies, other_dependencies)
+ with_no_such_dependency_error_handling do
+ specification_provider.dependencies_equal?(dependencies, other_dependencies)
+ end
+ end
+
# (see Bundler::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
index d1d7045daf..936399ed2f 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require 'set'
require 'tsort'
require_relative 'dependency_graph/log'
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
index 41bc013143..1185a8ab05 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
@@ -59,7 +59,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
- def _recursive_predecessors(vertices = Set.new)
+ def _recursive_predecessors(vertices = new_vertex_set)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
@@ -85,7 +85,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
- def _recursive_successors(vertices = Set.new)
+ def _recursive_successors(vertices = new_vertex_set)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
@@ -128,7 +128,7 @@ module Bundler::Molinillo
# Is there a path from `self` to `other` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def path_to?(other)
_path_to?(other)
end
@@ -138,7 +138,7 @@ module Bundler::Molinillo
# @param [Vertex] other the vertex to check if there's a path to
# @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
# @return [Boolean] whether there is a path to `other` from `self`
- def _path_to?(other, visited = Set.new)
+ def _path_to?(other, visited = new_vertex_set)
return false unless visited.add?(self)
return true if equal?(other)
successors.any? { |v| v._path_to?(other, visited) }
@@ -147,12 +147,18 @@ module Bundler::Molinillo
# Is there a path from `other` to `self` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
+
+ def new_vertex_set
+ require 'set'
+ Set.new
+ end
+ private :new_vertex_set
end
end
end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
index 4d64d21072..e210202b69 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
@@ -34,7 +34,7 @@ module Bundler::Molinillo
# An error caused by attempting to fulfil a dependency that was circular
#
- # @note This exception will be thrown iff a {Vertex} is added to a
+ # @note This exception will be thrown if and only if a {Vertex} is added to a
# {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
# existing {DependencyGraph::Vertex}
class CircularDependencyError < ResolverError
@@ -121,7 +121,7 @@ module Bundler::Molinillo
t = ''.dup
depth = 2
tree.each do |req|
- t << ' ' * depth << req.to_s
+ t << ' ' * depth << printable_requirement.call(req)
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
index fa094c1981..edf2366b7b 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
@@ -45,6 +45,17 @@ module Bundler::Molinillo
true
end
+ # Determines whether two arrays of dependencies are equal, and thus can be
+ # grouped.
+ #
+ # @param [Array<Object>] dependencies
+ # @param [Array<Object>] other_dependencies
+ # @return [Boolean] whether `dependencies` and `other_dependencies` should
+ # be considered equal.
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies == other_dependencies
+ end
+
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
index 26b8bc745c..c689ca7635 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
@@ -329,11 +329,11 @@ module Bundler::Molinillo
# Look for past conflicts that could be unwound to affect the
# requirement tree for the current conflict
+ all_reqs = last_detail_for_current_unwind.all_requirements
+ all_reqs_size = all_reqs.size
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
- intersecting_requirements =
- last_detail_for_current_unwind.all_requirements &
- alternative.requirements_unwound_to_instead
- next if intersecting_requirements.empty?
+ diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
+ next if diff_reqs.size == all_reqs_size
# Find the highest index unwind whilst looping through
current_detail = alternative if alternative > current_detail
alternative
@@ -344,8 +344,12 @@ module Bundler::Molinillo
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
# Update the requirements_unwound_to_instead on any relevant unused unwinds
- relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
- unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
+ relevant_unused_unwinds.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
+ unwind_details.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
current_detail
end
@@ -803,7 +807,7 @@ module Bundler::Molinillo
possibilities.reverse_each do |possibility|
dependencies = dependencies_for(possibility)
- if current_possibility_set && current_possibility_set.dependencies == dependencies
+ if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
current_possibility_set.possibilities.unshift(possibility)
else
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))
diff --git a/lib/bundler/vendor/thor/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb
index f2a03388cc..0794dbb522 100644
--- a/lib/bundler/vendor/thor/lib/thor.rb
+++ b/lib/bundler/vendor/thor/lib/thor.rb
@@ -1,7 +1,7 @@
-require "set"
require_relative "thor/base"
class Bundler::Thor
+ $thor_runner ||= false
class << self
# Allows for custom "Command" package naming.
#
@@ -323,7 +323,7 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def stop_on_unknown_option!(*command_names)
- stop_on_unknown_option.merge(command_names)
+ @stop_on_unknown_option = stop_on_unknown_option | command_names
end
def stop_on_unknown_option?(command) #:nodoc:
@@ -337,7 +337,7 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def disable_required_check!(*command_names)
- disable_required_check.merge(command_names)
+ @disable_required_check = disable_required_check | command_names
end
def disable_required_check?(command) #:nodoc:
@@ -347,12 +347,12 @@ class Bundler::Thor
protected
def stop_on_unknown_option #:nodoc:
- @stop_on_unknown_option ||= Set.new
+ @stop_on_unknown_option ||= []
end
# help command has the required check disabled by default.
def disable_required_check #:nodoc:
- @disable_required_check ||= Set.new([:help])
+ @disable_required_check ||= [:help]
end
# The method responsible for dispatching given the args.
@@ -398,7 +398,6 @@ class Bundler::Thor
# the namespace should be displayed as arguments.
#
def banner(command, namespace = nil, subcommand = false)
- $thor_runner ||= false
command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
"#{basename} #{formatted_usage}"
end.join("\n")
diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index a5368d07f3..de9323b2db 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -219,7 +219,7 @@ class Bundler::Thor
contents = if is_uri
require "open-uri"
- open(path, "Accept" => "application/x-thor-template", &:read)
+ URI.open(path, "Accept" => "application/x-thor-template", &:read)
else
open(path, &:read)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index afdbd53dd0..62c82b3dba 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -251,7 +251,8 @@ class Bundler::Thor
# path<String>:: path of the file to be changed
# flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block
- # config<Hash>:: give :verbose => false to not log the status.
+ # config<Hash>:: give :verbose => false to not log the status, and
+ # :force => true, to force the replacement regardles of runner behavior.
#
# ==== Example
#
@@ -262,9 +263,10 @@ class Bundler::Thor
# end
#
def gsub_file(path, flag, *args, &block)
- return unless behavior == :invoke
config = args.last.is_a?(Hash) ? args.pop : {}
+ return unless behavior == :invoke || config.fetch(:force, false)
+
path = File.expand_path(path, destination_root)
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index 1553afd201..7d57129b83 100644
--- a/lib/bundler/vendor/thor/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
@@ -1,5 +1,5 @@
class Bundler::Thor
- Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
+ Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable) # rubocop:disable Naming/ConstantName
# In order to support versions of Ruby that don't have keyword
# arguments, we need our own spell checker class that doesn't take key
# words. Even though this code wouldn't be hit because of the check
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
index d0f43e2d97..3a5d82cf29 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
@@ -30,7 +30,11 @@ class Bundler::Thor
arguments.each do |argument|
if !argument.default.nil?
- @assigns[argument.human_name] = argument.default
+ begin
+ @assigns[argument.human_name] = argument.default.dup
+ rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4
+ @assigns[argument.human_name] = argument.default
+ end
elsif argument.required?
@non_assigned_required << argument
end
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 6d1342ee3c..3a8927d09c 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -133,15 +133,16 @@ class Bundler::Thor
protected
- def assign_result!(option, result)
- if option.repeatable && option.type == :hash
- (@assigns[option.human_name] ||= {}).merge!(result)
- elsif option.repeatable
- (@assigns[option.human_name] ||= []) << result
- else
- @assigns[option.human_name] = result
+ def assign_result!(option, result)
+ if option.repeatable && option.type == :hash
+ (@assigns[option.human_name] ||= {}).merge!(result)
+ elsif option.repeatable
+ (@assigns[option.human_name] ||= []) << result
+ else
+ @assigns[option.human_name] = result
+ end
end
- end
+
# Check if the current value in peek is a registered switch.
#
# Two booleans are returned. The first is true if the current value
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index be48358cb1..2dddd4a53a 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -94,6 +94,8 @@ class Bundler::Thor
# say("I know you knew that.")
#
def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
+ return if quiet?
+
buffer = prepare_message(message, *color)
buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
@@ -230,8 +232,9 @@ class Bundler::Thor
paras = message.split("\n\n")
paras.map! do |unwrapped|
- counter = 0
- unwrapped.split(" ").inject do |memo, word|
+ words = unwrapped.split(" ")
+ counter = words.first.length
+ words.inject do |memo, word|
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
counter = 0 if word.include? "\n"
if (counter + word.length + 1) < width
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/color.rb b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
index 29f280202d..dc167ed3cc 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/color.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
@@ -97,7 +97,11 @@ class Bundler::Thor
protected
def can_display_colors?
- stdout.tty? && !are_colors_disabled?
+ are_colors_supported? && !are_colors_disabled?
+ end
+
+ def are_colors_supported?
+ stdout.tty? && ENV["TERM"] != "dumb"
end
def are_colors_disabled?
diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index 1b222da995..a3efa9f762 100644
--- a/lib/bundler/vendor/thor/lib/thor/version.rb
+++ b/lib/bundler/vendor/thor/lib/thor/version.rb
@@ -1,3 +1,3 @@
class Bundler::Thor
- VERSION = "1.0.1"
+ VERSION = "1.1.0"
end
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 3f2184b504..3c85284ff2 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -275,7 +275,7 @@ module Gem
unless spec = specs.first
msg = "can't find gem #{dep} with executable #{exec_name}"
- if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message
+ if dep.filters_bundler? && bundler_message = Gem::BundlerVersionFinder.missing_version_message
msg = bundler_message
end
raise Gem::GemNotFoundException, msg
@@ -469,7 +469,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
next if File.exist? subdir
begin
FileUtils.mkdir_p subdir, **options
- rescue Errno::EACCES
+ rescue SystemCallError
end
end
ensure
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/config_file.rb b/lib/rubygems/config_file.rb
index 854d09ef3d..9dc41a2995 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -45,6 +45,7 @@ class Gem::ConfigFile
DEFAULT_UPDATE_SOURCES = true
DEFAULT_CONCURRENT_DOWNLOADS = 8
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
+ DEFAULT_IPV4_FALLBACK_ENABLED = false
##
# For Ruby packagers to set configuration defaults. Set in
@@ -141,6 +142,12 @@ class Gem::ConfigFile
attr_accessor :cert_expiration_length_days
##
+ # == Experimental ==
+ # Fallback to IPv4 when IPv6 is not reachable or slow (default: false)
+
+ attr_accessor :ipv4_fallback_enabled
+
+ ##
# Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
attr_reader :ssl_client_cert
@@ -175,6 +182,7 @@ class Gem::ConfigFile
@update_sources = DEFAULT_UPDATE_SOURCES
@concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
@cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
+ @ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED
operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
@@ -203,6 +211,7 @@ class Gem::ConfigFile
@disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server
@sources = @hash[:sources] if @hash.key? :sources
@cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
+ @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
@ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
@ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert
diff --git a/lib/rubygems/core_ext/tcpsocket_init.rb b/lib/rubygems/core_ext/tcpsocket_init.rb
new file mode 100644
index 0000000000..3d9740c579
--- /dev/null
+++ b/lib/rubygems/core_ext/tcpsocket_init.rb
@@ -0,0 +1,52 @@
+require 'socket'
+
+module CoreExtensions
+ module TCPSocketExt
+ def self.prepended(base)
+ base.prepend Initializer
+ end
+
+ module Initializer
+ CONNECTION_TIMEOUT = 5
+ IPV4_DELAY_SECONDS = 0.1
+
+ def initialize(host, serv, *rest)
+ mutex = Mutex.new
+ addrs = []
+ threads = []
+ cond_var = ConditionVariable.new
+
+ Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
+ Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
+
+ threads << Thread.new(addr) do
+ # give head start to ipv6 addresses
+ sleep IPV4_DELAY_SECONDS if addr.ipv4?
+
+ # raises Errno::ECONNREFUSED when ip:port is unreachable
+ Socket.tcp(addr.ip_address, serv, connect_timeout: CONNECTION_TIMEOUT).close
+ mutex.synchronize do
+ addrs << addr.ip_address
+ cond_var.signal
+ end
+ end
+ end
+
+ mutex.synchronize do
+ timeout_time = CONNECTION_TIMEOUT + Time.now.to_f
+ while addrs.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
+ cond_var.wait(mutex, remaining_time)
+ end
+
+ host = addrs.shift unless addrs.empty?
+ end
+
+ threads.each {|t| t.kill.join if t.alive? }
+
+ super(host, serv, *rest)
+ end
+ end
+ end
+end
+
+TCPSocket.prepend CoreExtensions::TCPSocketExt
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index 68f3e3d991..3721204ab2 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -277,7 +277,7 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
end.map(&:to_spec)
- Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze && !requirement.specific?
+ Gem::BundlerVersionFinder.filter!(matches) if filters_bundler?
if platform_only
matches.reject! do |spec|
@@ -295,6 +295,10 @@ class Gem::Dependency
@requirement.specific?
end
+ def filters_bundler?
+ name == "bundler".freeze && !specific?
+ end
+
def to_specs
matches = matching_specs true
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index e089b3d57a..14d5dde413 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -28,13 +28,14 @@ class Gem::Ext::Builder
unless make_program
make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
end
+ make_program = Shellwords.split(make_program)
destdir = 'DESTDIR=%s' % ENV['DESTDIR']
['clean', '', 'install'].each do |target|
# Pass DESTDIR via command line to override what's in MAKEFLAGS
cmd = [
- make_program,
+ *make_program,
destdir,
target,
].reject(&:empty?)
diff --git a/lib/rubygems/installer_uninstaller_utils.rb b/lib/rubygems/installer_uninstaller_utils.rb
index e81ed4cba3..2c8b7c635e 100644
--- a/lib/rubygems/installer_uninstaller_utils.rb
+++ b/lib/rubygems/installer_uninstaller_utils.rb
@@ -6,11 +6,16 @@
module Gem::InstallerUninstallerUtils
def regenerate_plugins_for(spec, plugins_dir)
+ plugins = spec.plugins
+ return if plugins.empty?
+
+ require 'pathname'
+
spec.plugins.each do |plugin|
plugin_script_path = File.join plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}"
File.open plugin_script_path, 'wb' do |file|
- file.puts "require '#{plugin}'"
+ file.puts "require_relative '#{Pathname.new(plugin).relative_path_from(Pathname.new(plugins_dir))}'"
end
verbose plugin_script_path
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index a500fd24c8..e01d0494d6 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/ # reassemble x86-linux-gnu
+ if arch.length > 2 and arch.last !~ /\d+(\.\d+)?$/ # reassemble x86-linux-{libc}
extra = arch.pop
arch.last << "-#{extra}"
end
@@ -121,10 +121,6 @@ class Gem::Platform
end
end
- def inspect
- "%s @cpu=%p, @os=%p, @version=%p>" % [super[0..-2], *to_a]
- end
-
def to_a
[@cpu, @os, @version]
end
@@ -150,7 +146,8 @@ 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.
+ # 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')
#
# Additionally, the platform will match if the local CPU is 'arm' and the
# other CPU starts with "arm" (for generic ARM family support).
@@ -166,7 +163,10 @@ class Gem::Platform
@os == other.os and
# version
- (@version.nil? or other.version.nil? or @version == other.version)
+ (
+ (@os != 'linux' and (@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 53e840978c..a14c42f00e 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -78,6 +78,7 @@ class Gem::RemoteFetcher
# fetching the gem.
def initialize(proxy=nil, dns=nil, headers={})
+ require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
require 'net/http'
require 'stringio'
require 'uri'
@@ -295,7 +296,7 @@ class Gem::RemoteFetcher
data = fetch_path(uri, mtime)
- if data == nil # indicates the server returned 304 Not Modified
+ if data.nil? # indicates the server returned 304 Not Modified
return Gem.read_binary(path)
end
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 430060e2ff..6721de4055 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -190,7 +190,7 @@ class Gem::Requirement
end
def hash # :nodoc:
- requirements.sort.hash
+ requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
end
def marshal_dump # :nodoc:
diff --git a/lib/rubygems/resolver/index_specification.rb b/lib/rubygems/resolver/index_specification.rb
index 2aa6b419ba..9ea76f40ba 100644
--- a/lib/rubygems/resolver/index_specification.rb
+++ b/lib/rubygems/resolver/index_specification.rb
@@ -35,9 +35,12 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
##
# The required_ruby_version constraint for this specification
+ #
+ # A fallback is included because when generated, some marshalled specs have it
+ # set to +nil+.
def required_ruby_version
- spec.required_ruby_version
+ spec.required_ruby_version || Gem::Requirement.default
end
##
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
index 2ddb0ac426..b765226fb0 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
@@ -26,6 +26,13 @@ module Gem::Resolver::Molinillo
end
end
+ # (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_equal?)
+ def dependencies_equal?(dependencies, other_dependencies)
+ with_no_such_dependency_error_handling do
+ specification_provider.dependencies_equal?(dependencies, other_dependencies)
+ end
+ end
+
# (see Gem::Resolver::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
index 773bb3417f..16430a79f5 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require 'set'
require 'tsort'
require_relative 'dependency_graph/log'
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
index f4cc333dd1..77114951b2 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
@@ -59,7 +59,7 @@ module Gem::Resolver::Molinillo
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
- def _recursive_predecessors(vertices = Set.new)
+ def _recursive_predecessors(vertices = new_vertex_set)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
@@ -85,7 +85,7 @@ module Gem::Resolver::Molinillo
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
- def _recursive_successors(vertices = Set.new)
+ def _recursive_successors(vertices = new_vertex_set)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
@@ -138,7 +138,7 @@ module Gem::Resolver::Molinillo
# @param [Vertex] other the vertex to check if there's a path to
# @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
# @return [Boolean] whether there is a path to `other` from `self`
- def _path_to?(other, visited = Set.new)
+ def _path_to?(other, visited = new_vertex_set)
return false unless visited.add?(self)
return true if equal?(other)
successors.any? { |v| v._path_to?(other, visited) }
@@ -147,12 +147,18 @@ module Gem::Resolver::Molinillo
# Is there a path from `other` to `self` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
+
+ def new_vertex_set
+ require 'set'
+ Set.new
+ end
+ private :new_vertex_set
end
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
index a6e182e84d..ada03a901c 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
@@ -121,7 +121,7 @@ module Gem::Resolver::Molinillo
t = ''.dup
depth = 2
tree.each do |req|
- t << ' ' * depth << req.to_s
+ t << ' ' * depth << printable_requirement.call(req)
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
index a44b9c0d5d..9448dc7bf3 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
@@ -45,6 +45,17 @@ module Gem::Resolver::Molinillo
true
end
+ # Determines whether two arrays of dependencies are equal, and thus can be
+ # grouped.
+ #
+ # @param [Array<Object>] dependencies
+ # @param [Array<Object>] other_dependencies
+ # @return [Boolean] whether `dependencies` and `other_dependencies` should
+ # be considered equal.
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies == other_dependencies
+ end
+
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
index f1c60ec544..8b40e59e42 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
@@ -329,11 +329,11 @@ module Gem::Resolver::Molinillo
# Look for past conflicts that could be unwound to affect the
# requirement tree for the current conflict
+ all_reqs = last_detail_for_current_unwind.all_requirements
+ all_reqs_size = all_reqs.size
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
- intersecting_requirements =
- last_detail_for_current_unwind.all_requirements &
- alternative.requirements_unwound_to_instead
- next if intersecting_requirements.empty?
+ diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
+ next if diff_reqs.size == all_reqs_size
# Find the highest index unwind whilst looping through
current_detail = alternative if alternative > current_detail
alternative
@@ -344,8 +344,12 @@ module Gem::Resolver::Molinillo
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
# Update the requirements_unwound_to_instead on any relevant unused unwinds
- relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
- unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
+ relevant_unused_unwinds.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
+ unwind_details.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
current_detail
end
@@ -803,7 +807,7 @@ module Gem::Resolver::Molinillo
possibilities.reverse_each do |possibility|
dependencies = dependencies_for(possibility)
- if current_possibility_set && current_possibility_set.dependencies == dependencies
+ if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
current_possibility_set.possibilities.unshift(possibility)
else
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index d59f57c49f..7206c3eaf0 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -182,6 +182,7 @@ class Gem::Specification < Gem::BasicSpecification
@@default_value[k].nil?
end
+ @@stubs = nil
@@stubs_by_name = {}
# Sentinel object to represent "not found" stubs
@@ -665,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
@@ -800,10 +804,8 @@ class Gem::Specification < Gem::BasicSpecification
def self.stubs
@@stubs ||= begin
pattern = "*.gemspec"
- stubs = installed_stubs(dirs, pattern) + default_stubs(pattern)
- stubs = stubs.uniq {|stub| stub.full_name }
+ stubs = stubs_for_pattern(pattern, false)
- _resort!(stubs)
@@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
stubs
end
@@ -820,31 +822,40 @@ class Gem::Specification < Gem::BasicSpecification
end
end
- EMPTY = [].freeze # :nodoc:
-
##
# Returns a Gem::StubSpecification for installed gem named +name+
# only returns stubs that match Gem.platforms
def self.stubs_for(name)
- if @@stubs_by_name[name]
- @@stubs_by_name[name]
+ if @@stubs
+ @@stubs_by_name[name] || []
else
- pattern = "#{name}-*.gemspec"
- stubs = installed_stubs(dirs, pattern).select {|s| Gem::Platform.match_spec? s } + default_stubs(pattern)
- stubs = stubs.uniq {|stub| stub.full_name }.group_by(&:name)
- stubs.each_value {|v| _resort!(v) }
-
- @@stubs_by_name.merge! stubs
- @@stubs_by_name[name] ||= EMPTY
+ @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
+ s.name == name
+ end
end
end
+ ##
+ # Finds stub specifications matching a pattern from the standard locations,
+ # optionally filtering out specs not matching the current platform
+ #
+ def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
+ installed_stubs = installed_stubs(Gem::Specification.dirs, pattern)
+ installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
+ stubs = installed_stubs + default_stubs(pattern)
+ stubs = stubs.uniq {|stub| stub.full_name }
+ _resort!(stubs)
+ stubs
+ end
+
def self._resort!(specs) # :nodoc:
specs.sort! do |a, b|
names = a.name <=> b.name
next names if names.nonzero?
- b.version <=> a.version
+ versions = b.version <=> a.version
+ next versions if versions.nonzero?
+ b.platform == Gem::Platform::RUBY ? -1 : 1
end
end
@@ -1080,20 +1091,15 @@ class Gem::Specification < Gem::BasicSpecification
end
def self._latest_specs(specs, prerelease = false) # :nodoc:
- result = Hash.new {|h,k| h[k] = {} }
- native = {}
+ result = {}
specs.reverse_each do |spec|
next if spec.version.prerelease? unless prerelease
- native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY
- result[spec.name][spec.platform] = spec
+ result[spec.name] = spec
end
- result.map(&:last).map(&:values).flatten.reject do |spec|
- minimum = native[spec.name]
- minimum && spec.version < minimum
- end.sort_by{|tup| tup.name }
+ result.map(&:last).flatten.sort_by{|tup| tup.name }
end
##
@@ -1552,7 +1558,6 @@ class Gem::Specification < Gem::BasicSpecification
def build_extensions # :nodoc:
return if default_gem?
return if extensions.empty?
- return if installed_by_version < Gem::Version.new('2.2.0.preview.2')
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, 'extensions'))
@@ -2123,7 +2128,6 @@ class Gem::Specification < Gem::BasicSpecification
def missing_extensions?
return false if default_gem?
return false if extensions.empty?
- return false if installed_by_version < Gem::Version.new('2.2.0.preview.2')
return false if File.exist? gem_build_complete_path
true
@@ -2548,7 +2552,7 @@ class Gem::Specification < Gem::BasicSpecification
begin
dependencies.each do |dep|
next unless dep.runtime?
- dep.to_specs.each do |dep_spec|
+ dep.matching_specs(true).each do |dep_spec|
next if visited.has_key?(dep_spec)
visited[dep_spec] = true
trail.push(dep_spec)
diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb
index 79bd3e2a60..e2763561c6 100644
--- a/lib/rubygems/test_case.rb
+++ b/lib/rubygems/test_case.rb
@@ -301,7 +301,9 @@ class Gem::TestCase < Minitest::Test
def setup
@orig_env = ENV.to_hash
- @tmp = Dir.mktmpdir("tmp", Dir.pwd)
+ @tmp = File.expand_path("tmp")
+
+ FileUtils.mkdir_p @tmp
ENV['GEM_VENDOR'] = nil
ENV['GEMRC'] = nil
@@ -310,7 +312,6 @@ class Gem::TestCase < Minitest::Test
ENV['XDG_DATA_HOME'] = nil
ENV['SOURCE_DATE_EPOCH'] = nil
ENV['BUNDLER_VERSION'] = nil
- ENV["TMPDIR"] = @tmp
@current_dir = Dir.pwd
@fetcher = nil
@@ -321,13 +322,10 @@ class Gem::TestCase < Minitest::Test
# capture output
Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
- tmpdir = File.realpath Dir.tmpdir
- tmpdir.tap(&Gem::UNTAINT)
-
- @tempdir = File.join(tmpdir, "test_rubygems_#{$$}")
+ @tempdir = Dir.mktmpdir("test_rubygems_", @tmp)
@tempdir.tap(&Gem::UNTAINT)
- FileUtils.mkdir_p @tempdir
+ ENV["TMPDIR"] = @tempdir
@orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
@@ -366,7 +364,9 @@ class Gem::TestCase < Minitest::Test
Dir.chdir @tempdir
ENV['HOME'] = @userhome
+ Gem.instance_variable_set :@config_file, nil
Gem.instance_variable_set :@user_home, nil
+ Gem.instance_variable_set :@config_home, nil
Gem.instance_variable_set :@data_home, nil
Gem.instance_variable_set :@gemdeps, nil
Gem.instance_variable_set :@env_requirements_by_name, nil
@@ -449,7 +449,6 @@ class Gem::TestCase < Minitest::Test
Dir.chdir @current_dir
FileUtils.rm_rf @tempdir
- FileUtils.rm_rf @tmp
ENV.replace(@orig_env)
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index ccf957d6df..e49066f7dc 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -138,12 +138,12 @@ RSpec.describe "bundle executable" do
it "doesn't print defaults" do
install_gemfile "", :verbose => true
- expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
it "doesn't print defaults" do
install_gemfile "", :verbose => true
- expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
end
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index acb312edb3..cecaddfba4 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -17,7 +17,6 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
let(:response) { double(:response, :body => "abc123") }
it "treats the response as an update" do
- expect(response).to receive(:[]).with("Content-Encoding") { "" }
expect(response).to receive(:[]).with("ETag") { nil }
expect(fetcher).to receive(:call) { response }
@@ -29,8 +28,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
let(:response) { double(:response, :body => "") }
it "raises HTTPError" do
- expect(response).to receive(:[]).with("Content-Encoding") { "gzip" }
- expect(fetcher).to receive(:call) { response }
+ expect(fetcher).to receive(:call).and_raise(Zlib::GzipFile::Error)
expect do
updater.update(local_path, remote_path)
@@ -48,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/dep_proxy_spec.rb b/spec/bundler/bundler/dep_proxy_spec.rb
index 0f8d6b1076..84243d2ee2 100644
--- a/spec/bundler/bundler/dep_proxy_spec.rb
+++ b/spec/bundler/bundler/dep_proxy_spec.rb
@@ -2,10 +2,10 @@
RSpec.describe Bundler::DepProxy do
let(:dep) { Bundler::Dependency.new("rake", ">= 0") }
- subject { described_class.new(dep, Gem::Platform::RUBY) }
+ subject { described_class.get_proxy(dep, Gem::Platform::RUBY) }
let(:same) { subject }
- let(:other) { subject.dup }
- let(:different) { described_class.new(dep, Gem::Platform::JAVA) }
+ let(:other) { described_class.get_proxy(dep, Gem::Platform::RUBY) }
+ let(:different) { described_class.get_proxy(dep, Gem::Platform::JAVA) }
describe "#eql?" do
it { expect(subject.eql?(same)).to be true }
@@ -15,8 +15,18 @@ RSpec.describe Bundler::DepProxy do
it { expect(subject.eql?("foobar")).to be false }
end
- describe "#hash" do
- it { expect(subject.hash).to eq(same.hash) }
- it { expect(subject.hash).to eq(other.hash) }
+ describe "must use factory methods" do
+ it { expect { described_class.new(dep, Gem::Platform::RUBY) }.to raise_error NoMethodError }
+ it { expect { subject.dup }.to raise_error NoMethodError }
+ it { expect { subject.clone }.to raise_error NoMethodError }
+ end
+
+ describe "frozen" do
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5.0")
+ error = Object.const_get("FrozenError")
+ else
+ error = RuntimeError
+ end
+ it { expect { subject.instance_variable_set(:@__platform, {}) }.to raise_error error }
end
end
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/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb
index 769c461911..d718615ad2 100644
--- a/spec/bundler/bundler/gem_helper_spec.rb
+++ b/spec/bundler/bundler/gem_helper_spec.rb
@@ -9,7 +9,8 @@ RSpec.describe Bundler::GemHelper do
let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") }
before(:each) do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false", "BUNDLE_GEM__CI" => "false"
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false",
+ "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
bundle "gem #{app_name}"
prepare_gemspec(app_gemspec_path)
end
@@ -267,6 +268,14 @@ RSpec.describe Bundler::GemHelper do
Rake.application["release"].invoke
end
+
+ it "also works with releasing from a branch not yet pushed" do
+ sys_exec("git checkout -b module_function", :dir => app_path)
+
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
+ end
end
context "on releasing with a custom tag prefix" do
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 01e0232fba..43a3630bbb 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Bundler::GemVersionPromoter do
def build_spec_groups(name, versions)
versions.map do |v|
- Bundler::Resolver::SpecGroup.new(build_spec(name, v))
+ Bundler::Resolver::SpecGroup.create_for({ Gem::Platform::RUBY => build_spec(name, v) }, [Gem::Platform::RUBY], Gem::Platform::RUBY)
end
end
@@ -170,7 +170,7 @@ RSpec.describe Bundler::GemVersionPromoter do
context "debug output" do
it "should not kerblooie on its own debug output" do
gvp = unlocking(:level => :patch)
- dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby")
+ dep = Bundler::DepProxy.get_proxy(dep("foo", "1.2.0").first, "ruby")
result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0]))
expect(result.class).to eq Array
end
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index c1c88ce480..cc28382043 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -110,6 +110,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/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb
index 35702d7763..97f06973cb 100644
--- a/spec/bundler/bundler/source/git/git_proxy_spec.rb
+++ b/spec/bundler/bundler/source/git/git_proxy_spec.rb
@@ -130,18 +130,20 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "when given a SHA as a revision" do
let(:revision) { "abcd" * 10 }
let(:command) { ["reset", "--hard", revision] }
+ let(:command_for_display) { "git #{command.shelljoin}" }
it "fails gracefully when resetting to the revision fails" do
expect(subject).to receive(:git_retry).with("clone", any_args) { destination.mkpath }
expect(subject).to receive(:git_retry).with("fetch", any_args, :dir => destination)
- expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command, cache, destination))
+ expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command_for_display, destination))
expect(subject).not_to receive(:git)
expect { subject.copy_to(destination, submodules) }.
to raise_error(
Bundler::Source::Git::MissingGitRevisionError,
- "Git error: command `git #{command}` in directory #{destination} has failed.\n" \
- "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?" \
+ "Git error: command `#{command_for_display}` in directory #{destination} has failed.\n" \
+ "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?\n" \
+ "If this error persists you could try removing the cache directory '#{destination}'"
)
end
end
diff --git a/spec/bundler/bundler/source/git_spec.rb b/spec/bundler/bundler/source/git_spec.rb
index f7475a35aa..6668b6e69a 100644
--- a/spec/bundler/bundler/source/git_spec.rb
+++ b/spec/bundler/bundler/source/git_spec.rb
@@ -14,14 +14,14 @@ RSpec.describe Bundler::Source::Git do
describe "#to_s" do
it "returns a description" do
- expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git"
end
context "when the URI contains credentials" do
let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" }
it "filters credentials" do
- expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git"
end
end
end
diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb
index 0a54f9d7b5..fb612813c2 100644
--- a/spec/bundler/bundler/stub_specification_spec.rb
+++ b/spec/bundler/bundler/stub_specification_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Bundler::StubSpecification do
s.name = "gemname"
s.version = "1.0.0"
s.loaded_from = __FILE__
+ s.extensions = "ext/gemname"
end
described_class.from_stub(gemspec)
@@ -17,4 +18,30 @@ RSpec.describe Bundler::StubSpecification do
expect(stub).to be(with_bundler_stub_spec)
end
end
+
+ describe "#manually_installed?" do
+ it "returns true if installed_by_version is nil or 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.manually_installed?).to be true
+ end
+
+ it "returns false if installed_by_version is greater than 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ expect(stub.manually_installed?).to be false
+ end
+ end
+
+ describe "#missing_extensions?" do
+ it "returns false if manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.missing_extensions?).to be false
+ end
+
+ it "returns true if not manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ expect(stub.missing_extensions?).to be true
+ end
+ end
end
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 97d73907db..25f12a9e87 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -200,7 +200,7 @@ RSpec.describe "bundle cache with git" do
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
- bundle :cache, "all-platforms" => true, :install => false, :path => "./vendor/cache"
+ bundle :cache, "all-platforms" => true, :install => false
simulate_new_machine
with_path_as "" do
diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb
index f4a57039ad..3b8bce4b01 100644
--- a/spec/bundler/commands/cache_spec.rb
+++ b/spec/bundler/commands/cache_spec.rb
@@ -1,6 +1,19 @@
# frozen_string_literal: true
RSpec.describe "bundle cache" do
+ it "doesn't update the cache multiple times, even if it already exists" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+ end
+
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 6485eb6a5a..0d104ad304 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -668,29 +668,40 @@ RSpec.describe "bundle exec" do
subject { bundle "exec #{path} arg1 arg2", :raise_on_error => false }
- shared_examples_for "it runs" do
- it "like a normally executed executable" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
- subject
- expect(exitstatus).to eq(exit_code)
- expect(err).to eq(expected_err)
- expect(out).to eq(expected)
- end
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
end
- it_behaves_like "it runs"
-
context "the executable exits explicitly" do
let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" }
context "with exit 0" do
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "with exit 99" do
let(:exit_code) { 99 }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
end
@@ -707,7 +718,15 @@ RSpec.describe "bundle exec" do
# this is specified by C99
128 + 15
end
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "the executable is empty" do
@@ -716,7 +735,15 @@ RSpec.describe "bundle exec" do
let(:exit_code) { 0 }
let(:expected_err) { "#{path} is empty" }
let(:expected) { "" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "the executable raises" do
@@ -743,12 +770,27 @@ RSpec.describe "bundle exec" do
let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\n#{system_gem_path("bin/bundle")}: Err (Err)" }
let(:expected) { super() }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the file uses the current ruby shebang" do
let(:shebang) { "#!#{Gem.ruby}" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when Bundler.setup fails", :bundler => "< 3" do
@@ -762,11 +804,19 @@ 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
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when Bundler.setup fails", :bundler => "3" do
@@ -785,14 +835,28 @@ The source contains the following versions of 'rack': 1.0.0\e[0m
\e[33mRun `bundle install` to install missing gems.\e[0m
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the executable exits non-zero via at_exit" do
let(:executable) { super() + "\n\nat_exit { $! ? raise($!) : exit(1) }" }
let(:exit_code) { 1 }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when disable_exec_load is set" do
@@ -803,7 +867,14 @@ The source contains the following versions of 'rack': 1.0.0\e[0m
bundle "config set disable_exec_load true"
end
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "regarding $0 and __FILE__" do
@@ -819,12 +890,26 @@ $0: #{path.to_s.inspect}
__FILE__: #{path.to_s.inspect}
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
context "when the path is relative" do
let(:path) { super().relative_path_from(bundled_app) }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the path is relative with a leading ./" do
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index afc3b03a53..7724170a63 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -220,6 +220,30 @@ RSpec.describe "bundle lock" do
expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq)
end
+ it "supports adding new platforms with force_ruby_platform = true" do
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-x86-linux)
+
+ PLATFORMS
+ ruby
+ x86-linux
+
+ DEPENDENCIES
+ platform_specific
+ L
+
+ bundle "config set force_ruby_platform true"
+ bundle "lock --add-platform java x86-mingw32"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ lockfile = Bundler::LockfileParser.new(read_lockfile)
+ expect(lockfile.platforms).to contain_exactly(rb, linux, java, mingw)
+ end
+
it "supports adding the `ruby` platform" do
bundle "lock --add-platform ruby"
@@ -467,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/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 8aca745bef..c1d5e1814d 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe "bundle gem" do
def bundle_exec_rubocop
prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec"))
- rubocop_version = RUBY_VERSION > "2.4" ? "0.90.0" : "0.80.1"
+ rubocop_version = RUBY_VERSION > "2.4" ? "1.7.0" : "0.81.0"
gems = ["minitest", "rake", "rake-compiler", "rspec", "rubocop -v #{rubocop_version}", "test-unit"]
gems.unshift "parallel -v 1.19.2" if RUBY_VERSION < "2.5"
- gems += ["rubocop-ast -v 0.4.0"] if rubocop_version == "0.90.0"
+ gems += ["rubocop-ast -v 1.4.0"] if rubocop_version == "1.7.0"
path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(:base => bundled_app(gem_name)) : system_gem_path
realworld_system_gems gems, :path => path
bundle "exec rubocop --debug --config .rubocop.yml", :dir => bundled_app(gem_name)
@@ -28,44 +28,9 @@ RSpec.describe "bundle gem" do
let(:require_path) { "mygem" }
before do
- git_config_content = <<-EOF
- [user]
- name = "Bundler User"
- email = user@example.com
- [github]
- user = bundleuser
- EOF
- @git_config_location = ENV["GIT_CONFIG"]
- path = "#{tmp}/test_git_config.txt"
- File.open(path, "w") {|f| f.write(git_config_content) }
- ENV["GIT_CONFIG"] = path
- end
-
- after do
- FileUtils.rm(ENV["GIT_CONFIG"]) if File.exist?(ENV["GIT_CONFIG"])
- ENV["GIT_CONFIG"] = @git_config_location
- end
-
- shared_examples_for "git config is present" do
- context "git config user.{name,email} present" do
- it "sets gemspec author to git user.name if available" do
- expect(generated_gemspec.authors.first).to eq("Bundler User")
- end
-
- it "sets gemspec email to git user.email if available" do
- expect(generated_gemspec.email.first).to eq("user@example.com")
- end
- end
- end
-
- shared_examples_for "git config is absent" do
- it "sets gemspec author to default message if git user.name is not set or empty" do
- expect(generated_gemspec.authors.first).to eq("TODO: Write your name")
- end
-
- it "sets gemspec email to default message if git user.email is not set or empty" do
- expect(generated_gemspec.email.first).to eq("TODO: Write your email address")
- end
+ sys_exec("git config --global user.name 'Bundler User'")
+ sys_exec("git config --global user.email user@example.com")
+ sys_exec("git config --global github.user bundleuser")
end
describe "git repo initialization" do
@@ -125,19 +90,24 @@ RSpec.describe "bundle gem" do
end
shared_examples_for "--coc flag" do
- before do
- bundle "gem #{gem_name} --coc"
- end
it "generates a gem skeleton with MIT license" do
+ bundle "gem #{gem_name} --coc"
gem_skeleton_assertions
expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to exist
end
- describe "README additions" do
- it "generates the README with a section for the Code of Conduct" do
- expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
- expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
- end
+ it "generates the README with a section for the Code of Conduct" do
+ bundle "gem #{gem_name} --coc"
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
+ end
+
+ it "generates the README with a section for the Code of Conduct, respecting the configured git default branch" do
+ sys_exec("git config --global init.defaultBranch main")
+ bundle "gem #{gem_name} --coc"
+
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/main/CODE_OF_CONDUCT.md")
end
end
@@ -150,11 +120,29 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to_not exist
end
- describe "README additions" do
- it "generates the README without a section for the Code of Conduct" do
- expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct")
- expect(bundled_app("#{gem_name}/README.md").read).not_to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
- end
+ it "generates the README without a section for the Code of Conduct" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
+ end
+ end
+
+ shared_examples_for "--changelog flag" do
+ before do
+ bundle "gem #{gem_name} --changelog"
+ end
+ it "generates a gem skeleton with a CHANGELOG", :readline do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to exist
+ end
+ end
+
+ shared_examples_for "--no-changelog flag" do
+ before do
+ bundle "gem #{gem_name} --no-changelog"
+ end
+ it "generates a gem skeleton without a CHANGELOG", :readline do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to_not exist
end
end
@@ -282,7 +270,7 @@ RSpec.describe "bundle gem" do
context "git config github.user is absent" do
before do
- sys_exec("git config --unset github.user")
+ sys_exec("git config --global --unset github.user")
bundle "gem #{gem_name}"
end
@@ -393,17 +381,29 @@ RSpec.describe "bundle gem" do
bundle "gem #{gem_name}"
end
- it_should_behave_like "git config is present"
+ it "sets gemspec author to git user.name if available" do
+ expect(generated_gemspec.authors.first).to eq("Bundler User")
+ end
+
+ it "sets gemspec email to git user.email if available" do
+ expect(generated_gemspec.email.first).to eq("user@example.com")
+ end
end
context "git config user.{name,email} is not set" do
before do
- sys_exec("git config --unset user.name", :dir => bundled_app)
- sys_exec("git config --unset user.email", :dir => bundled_app)
+ sys_exec("git config --global --unset user.name")
+ sys_exec("git config --global --unset user.email")
bundle "gem #{gem_name}"
end
- it_should_behave_like "git config is absent"
+ it "sets gemspec author to default message if git user.name is not set or empty" do
+ expect(generated_gemspec.authors.first).to eq("TODO: Write your name")
+ end
+
+ it "sets gemspec email to default message if git user.email is not set or empty" do
+ expect(generated_gemspec.email.first).to eq("TODO: Write your email address")
+ end
end
it "sets gemspec metadata['allowed_push_host']" do
@@ -416,9 +416,7 @@ RSpec.describe "bundle gem" do
it "sets a minimum ruby version" do
bundle "gem #{gem_name}"
- bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec
-
- expect(bundler_gemspec.required_ruby_version).to eq(generated_gemspec.required_ruby_version)
+ expect(generated_gemspec.required_ruby_version).to eq(Gem::Requirement.new(Gem.ruby_version < Gem::Version.new("2.4.a") ? ">= 2.3.0" : ">= 2.4.0"))
end
it "requires the version file" do
@@ -904,6 +902,22 @@ RSpec.describe "bundle gem" do
it_behaves_like "--rubocop flag"
it_behaves_like "--no-rubocop flag"
end
+
+ context "with changelog option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__CHANGELOG" => "true"
+ end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
+
+ context "with changelog option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__CHANGELOG" => "false"
+ end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
end
context "gem naming with underscore", :readline do
@@ -1089,13 +1103,24 @@ Usage: "bundle gem NAME [OPTIONS]"
expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist
end
+
+ it "asks about CHANGELOG" do
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__RUBOCOP" => "false",
+ "BUNDLE_GEM__COC" => "false"
+
+ bundle "gem foobar" do |input, _, _|
+ input.puts "yes"
+ end
+
+ expect(bundled_app("foobar/CHANGELOG.md")).to exist
+ end
end
context "on conflicts with a previously created file", :readline do
it "should fail gracefully" do
FileUtils.touch(bundled_app("conflict-foobar"))
bundle "gem conflict-foobar", :raise_on_error => false
- expect(err).to include("Errno::ENOTDIR")
+ expect(err).to eq("Couldn't create a new gem named `conflict-foobar` because there's an existing file named `conflict-foobar`.")
expect(exitstatus).to eql(32)
end
end
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
index 710152e59f..104221efbe 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/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index b8de6507f6..521c175711 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -651,6 +651,8 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
build_gem "rails", "3.0.1" do |s|
s.add_dependency "bundler", Bundler::VERSION.succ
end
+
+ build_gem "bundler", Bundler::VERSION.succ
end
gemfile <<-G
@@ -659,18 +661,11 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
G
end
- it "should explain that bundler conflicted", :bundler => "< 3" do
+ it "should explain that bundler conflicted and how to resolve the conflict" do
bundle "update", :all => true, :raise_on_error => false
expect(last_command.stdboth).not_to match(/in snapshot/i)
expect(err).to match(/current Bundler version/i).
- and match(/perhaps you need to update bundler/i)
- end
-
- it "should warn that the newer version of Bundler would conflict", :bundler => "3" do
- bundle "update", :all => true
- expect(err).to include("rails (3.0.1) has dependency bundler").
- and include("so the dependency is being ignored")
- expect(the_bundle).to include_gem "rails 3.0.1"
+ and match(/Install the necessary version with `gem install bundler:#{Bundler::VERSION.succ}`/i)
end
end
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index af1ff7225a..963ce82db8 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -21,17 +21,57 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "are not added if not already present" do
+ it "are forced to the current bundler version even if not already present" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- expect(the_bundle).not_to include_gems "bundler #{Bundler::VERSION}"
+ expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "causes a conflict if explicitly requesting a different version" do
- bundle "config set force_ruby_platform true"
+ it "causes a conflict if explicitly requesting a different version of bundler" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails", "3.0"
+ gem "bundler", "0.9.1"
+ G
+ nice_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "bundler":
+ In Gemfile:
+ bundler (= 0.9.1)
+
+ Current Bundler version:
+ bundler (#{Bundler::VERSION})
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a non matching requirement on bundler" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails", "3.0"
+ gem "bundler", "~> 0.8"
+ G
+
+ nice_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "bundler":
+ In Gemfile:
+ bundler (~> 0.8)
+
+ Current Bundler version:
+ bundler (#{Bundler::VERSION})
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do
install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0"
@@ -45,10 +85,8 @@ RSpec.describe "bundle install" do
Current Bundler version:
bundler (#{Bundler::VERSION})
- This Gemfile requires a different version of Bundler.
- Perhaps you need to update Bundler by running `gem install bundler`?
- Could not find gem 'bundler (= 0.9.2)' in any
+ Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.
E
expect(err).to include(nice_error)
end
@@ -197,27 +235,5 @@ RSpec.describe "bundle install" do
bundle "check"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
-
- context "with allow_bundler_dependency_conflicts set" do
- before { bundle "config set allow_bundler_dependency_conflicts true" }
-
- it "are forced to the current bundler version with warnings when no compatible version is found" do
- build_repo4 do
- build_gem "requires_nonexistant_bundler" do |s|
- s.add_runtime_dependency "bundler", "99.99.99.99"
- end
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "requires_nonexistant_bundler"
- G
-
- expect(err).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \
- "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored"
-
- expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0"
- end
- end
end
end
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index 5f4fc71499..f3898c0a65 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -85,6 +85,18 @@ RSpec.describe "install in deployment or frozen mode" do
bundle :install
end
+ it "works when path gems are specified twice" do
+ build_lib "foo", :path => lib_path("nested/foo")
+ gemfile <<-G
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ G
+
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle :install
+ end
+
it "works when there are credentials in the source URL" do
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
source "http://user:pass@localgemserver.test/"
@@ -341,7 +353,7 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)")
+ expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com")
expect(err).not_to include("You have changed in the Gemfile")
end
@@ -361,7 +373,7 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master@#{revision_for(lib_path("rack-1.0"))[0..6]}")
+ expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")}")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
@@ -385,7 +397,7 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master@#{revision_for(lib_path("rack"))[0..6]})`")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")}`")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have deleted from the Gemfile")
end
@@ -401,7 +413,7 @@ RSpec.describe "install in deployment or frozen mode" do
gem "rack-obama"
G
- expect(the_bundle).not_to include_gems "rack 1.0.0"
+ run "require 'rack'", :raise_on_error => false
expect(err).to include strip_whitespace(<<-E).strip
The dependencies in your gemfile changed
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index b41a083d92..a70b950e1b 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/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index 2e0c0bcf6d..ba8f253b0e 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -598,6 +598,24 @@ RSpec.describe "bundle install with git sources" do
bundle :install, :raise_on_error => false
expect(err).to match(/The Gemfile lock is pointing to revision \w+/)
end
+
+ it "does not explode on invalid revision on install" do
+ build_git "rack", "0.8"
+
+ build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ s.write "lib/rack.rb", "puts :LOCAL"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ G
+
+ bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set disable_local_revision_check true)
+ bundle :install
+ expect(out).to match(/Bundle complete!/)
+ end
end
describe "specified inline" do
@@ -629,8 +647,6 @@ RSpec.describe "bundle install with git sources" do
end
it "installs dependencies from git even if a newer gem is available elsewhere" do
- skip "override is not winning" if Gem.win_platform?
-
system_gems "rack-1.0.0"
build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index fc40c5e9b9..3463c5ec06 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -136,8 +136,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "installs dependencies from the path even if a newer gem is available elsewhere" do
- skip "override is not winning" if Gem.win_platform?
-
system_gems "rack-1.0.0"
build_lib "rack", "1.0", :path => lib_path("nested/bar") do |s|
@@ -581,6 +579,71 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
end
+
+ it "keeps using the same version even when another dependency is added" do
+ build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "rack", "0.9.1"
+ end
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "rack 0.9.1"
+
+ lockfile_should_be <<-G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ rack (= 0.9.1)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "rack"
+ s.add_dependency "rake", "13.0.1"
+ end
+
+ bundle "install"
+
+ lockfile_should_be <<-G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ rack
+ rake (= 13.0.1)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+ rake (13.0.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ expect(the_bundle).to include_gems "rack 0.9.1"
+ end
end
describe "switching sources" do
@@ -636,8 +699,6 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when there are both a gemspec and remote gems" do
it "doesn't query rubygems for local gemspec name" do
- skip "platform issues" if Gem.win_platform?
-
build_lib "private_lib", "2.2", :path => lib_path("private_lib")
gemfile = <<-G
source "http://localgemserver.test"
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index 1a3794dffe..c49594183e 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
@@ -299,6 +286,48 @@ RSpec.describe "bundle install across platforms" do
bundle :install
expect(vendored_gems("gems/rack-1.0.0")).to exist
end
+
+ it "keeps existing platforms when installing with force_ruby_platform" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0-java)
+
+ PLATFORMS
+ java
+
+ DEPENDENCIES
+ platform_specific
+ G
+
+ bundle "config set --local force_ruby_platform true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gem "platform_specific 1.0 RUBY"
+
+ lockfile_should_be <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-java)
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
RSpec.describe "bundle install with platform conditionals" do
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 75b7b67e98..b388b17881 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,26 +187,19 @@ 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(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")
+ 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")
- # 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(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")
- 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
@@ -222,7 +214,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 +223,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 +239,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 +271,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.")
@@ -304,6 +295,33 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
+ context "when a top-level gem can only be found in an scoped source" do
+ before do
+ build_repo2
+
+ build_repo gem_repo3 do
+ build_gem "private_gem_1", "1.0.0"
+ build_gem "private_gem_2", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "private_gem_1"
+
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "private_gem_2"
+ end
+ G
+ end
+
+ it "fails" do
+ bundle :install, :raise_on_error => false
+ expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.")
+ expect(err).to include("The source does not contain any versions of 'private_gem_1'")
+ end
+ end
+
context "when a top-level gem has an indirect dependency" do
context "when disable_multisource is set" do
before do
@@ -381,6 +399,200 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
end
+
+ context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do
+ before do
+ build_repo gem_repo2 do
+ build_gem "activesupport", "6.0.3.4" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2"
+ s.add_dependency "i18n", ">= 0.7", "< 2"
+ s.add_dependency "minitest", "~> 5.1"
+ s.add_dependency "tzinfo", "~> 1.1"
+ s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2"
+ end
+
+ build_gem "activesupport", "6.1.2.1" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2"
+ s.add_dependency "i18n", ">= 1.6", "< 2"
+ s.add_dependency "minitest", ">= 5.1"
+ s.add_dependency "tzinfo", "~> 2.0"
+ s.add_dependency "zeitwerk", "~> 2.3"
+ end
+
+ build_gem "concurrent-ruby", "1.1.8"
+ build_gem "concurrent-ruby", "1.1.9"
+ build_gem "connection_pool", "2.2.3"
+
+ build_gem "i18n", "1.8.9" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0"
+ end
+
+ build_gem "minitest", "5.14.3"
+ build_gem "rack", "2.2.3"
+ build_gem "redis", "4.2.5"
+
+ build_gem "sidekiq", "6.1.3" do |s|
+ s.add_dependency "connection_pool", ">= 2.2.2"
+ s.add_dependency "rack", "~> 2.0"
+ s.add_dependency "redis", ">= 4.2.0"
+ end
+
+ build_gem "thread_safe", "0.3.6"
+
+ build_gem "tzinfo", "1.2.9" do |s|
+ s.add_dependency "thread_safe", "~> 0.1"
+ end
+
+ build_gem "tzinfo", "2.0.4" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0"
+ end
+
+ build_gem "zeitwerk", "2.4.2"
+ end
+
+ build_repo gem_repo3 do
+ build_gem "sidekiq-pro", "5.2.1" do |s|
+ s.add_dependency "connection_pool", ">= 2.2.3"
+ s.add_dependency "sidekiq", ">= 6.1.0"
+ end
+ end
+
+ gemfile <<-G
+ # frozen_string_literal: true
+
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "activesupport"
+
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "sidekiq-pro"
+ end
+ G
+
+ lockfile <<~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.8)
+ 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 "upgrades gems when running bundle update, without printing any warnings or errors" do
+ bundle "update --all"
+ expect(err).to be_empty
+ end
+ end
+ end
+
+ context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved", :bundler => "< 3" do
+ before do
+ build_lib "activesupport", "7.0.0.alpha", :path => lib_path("rails/activesupport")
+ build_lib "rails", "7.0.0.alpha", :path => lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 7.0.0.alpha"
+ end
+
+ build_repo gem_repo2 do
+ build_gem "activesupport", "6.1.2"
+
+ build_gem "webpacker", "5.2.1" do |s|
+ s.add_dependency "activesupport", ">= 5.2"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gemspec :path => "#{lib_path("rails")}"
+
+ gem "webpacker", "~> 5.0"
+ G
+ end
+
+ it "installs all gems without warning" do
+ bundle :install
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", :source => "path@#{lib_path("rails/activesupport")}")
+ expect(the_bundle).to include_gems("rails 7.0.0.alpha", :source => "path@#{lib_path("rails")}")
+ 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
+ before do
+ build_repo gem_repo3 do
+ build_gem "handsoap", "0.2.5.5" do |s|
+ s.add_dependency "nokogiri", ">= 1.2.3"
+ end
+ end
+
+ update_repo gem_repo2 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "racca", "~> 1.4"
+ end
+
+ build_gem "racca", "1.5.2"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ source "#{file_uri_for(gem_repo3)}" do
+ gem "handsoap"
+ end
+
+ gem "nokogiri"
+ G
+ end
+
+ it "installs from the proper sources without any warnings or errors" do
+ 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")
+
+ # Even if the gems are already installed
+ FileUtils.rm bundled_app_lock
+ 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")
+ end
end
context "with a gem that is only found in the wrong source" do
@@ -389,14 +601,13 @@ 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'")
end
end
@@ -457,14 +668,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,7 +825,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "keeps the old version", :bundler => "2" do
+ it "keeps the old version", :bundler => "< 3" do
expect(the_bundle).to include_gems("rack 1.0.0")
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index b58726064f..9e30fc4fd4 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -211,37 +211,17 @@ RSpec.describe "bundle install with specific platforms" do
build_repo2 do
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" }
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" }
build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" }
build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" }
build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4")
-
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3")
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" }
build_gem("google-protobuf", "3.0.0.alpha.4.0")
build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
- build_gem("google-protobuf", "3.0.0.alpha.3")
- build_gem("google-protobuf", "3.0.0.alpha.2.0")
- build_gem("google-protobuf", "3.0.0.alpha.1.1")
- build_gem("google-protobuf", "3.0.0.alpha.1.0")
end
end
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 4384a731cd..035ed9a7f3 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs plugins depended on by other plugins" do
- install_gemfile <<-G
+ install_gemfile <<-G, :env => { "DEBUG" => "1" }
source "#{file_uri_for(gem_repo2)}"
gem "net_a"
G
@@ -97,7 +97,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs multiple levels of dependencies" do
- install_gemfile <<-G
+ install_gemfile <<-G, :env => { "DEBUG" => "1" }
source "#{file_uri_for(gem_repo2)}"
gem "net_c"
gem "net_e"
@@ -114,7 +114,7 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1" }
+ bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
expect(out).to include("BUNDLER: Starting resolution")
end
@@ -128,7 +128,7 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER" => "1" }
+ bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
expect(out).to include("BUNDLER: Starting resolution")
end
@@ -142,10 +142,13 @@ RSpec.describe "bundle install with install-time dependencies" do
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1" }
+ bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
- activated_groups = "net_b (1.0) (ruby)"
- activated_groups += ", net_b (1.0) (#{local_platforms.join(", ")})" if local_platforms.any? && local_platforms != ["ruby"]
+ activated_groups = if local_platforms.any?
+ "net_b (1.0) (ruby), net_b (1.0) (#{local_platforms.join(", ")})"
+ else
+ "net_b (1.0) (ruby)"
+ end
expect(out).to include(" net_b").
and include("BUNDLER: Starting resolution").
@@ -157,10 +160,6 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "when a required ruby version" do
context "allows only an older version" do
- before do
- skip "gem not found" if Gem.win_platform?
- end
-
it "installs the older version" do
build_repo2 do
build_gem "rack", "1.2" do |s|
@@ -239,7 +238,6 @@ RSpec.describe "bundle install with install-time dependencies" do
let(:ruby_requirement) { %("#{RUBY_VERSION}") }
let(:error_message_requirement) { "~> #{RUBY_VERSION}.0" }
- let(:error_message_platform) { " #{Bundler.local_platform}" }
shared_examples_for "ruby version conflicts" do
it "raises an error during resolution" do
@@ -256,9 +254,9 @@ RSpec.describe "bundle install with install-time dependencies" do
nice_error = strip_whitespace(<<-E).strip
Bundler found conflicting requirements for the Ruby\0 version:
In Gemfile:
- Ruby\0 (#{error_message_requirement})#{error_message_platform}
+ Ruby\0 (#{error_message_requirement})
- require_ruby#{error_message_platform} was resolved to 1.0, which depends on
+ require_ruby was resolved to 1.0, which depends on
Ruby\0 (> 9000)
Ruby\0 (> 9000), which is required by gem 'require_ruby', is not available in the local ruby installation
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index 1037a98092..08d5276a54 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -7,6 +7,12 @@ RSpec.shared_examples "bundle install --standalone" do
expect(the_bundle).to include_gems(*args)
end
+ it "still makes system gems unavailable to normal bundler" do
+ system_gems "rack-1.0.0"
+
+ expect(the_bundle).to_not include_gems("rack")
+ end
+
it "generates a bundle/bundler/setup.rb" do
expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
@@ -26,6 +32,39 @@ RSpec.shared_examples "bundle install --standalone" do
expect(out).to eq(expected_gems.values.join("\n"))
end
+ it "makes the gems available without bundler via Kernel.require" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nKernel.require \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
+ end
+ ruby testrb
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "makes system gems unavailable without bundler" do
+ system_gems "rack-1.0.0"
+
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ begin
+ require "rack"
+ rescue LoadError
+ puts "LoadError"
+ end
+ RUBY
+ ruby testrb
+
+ expect(out).to eq("LoadError")
+ end
+
it "works on a different system" do
begin
FileUtils.mv(bundled_app, "#{bundled_app}2")
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 0db1f1985b..dc1934804d 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -28,8 +28,6 @@ RSpec.describe "bundle install" do
end
it "should use gemspecs in the system cache when available" do
- skip "weird incompatible marshal file format error" if Gem.win_platform?
-
gemfile <<-G
source "http://localtestserver.gem"
gem 'rack'
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index 31c9568f85..71771d3dc2 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -2,10 +2,10 @@
RSpec.describe "bundle install" do
context "git sources" do
- it "displays the revision hash of the gem repository", :bundler => "< 3" do
+ it "displays the revision hash of the gem repository" do
build_git "foo", "1.0", :path => lib_path("foo")
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true
gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
G
@@ -13,7 +13,18 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
end
- it "displays the ref of the gem repository when using branch~num as a ref", :bundler => "< 3" do
+ it "displays the correct default branch" do
+ build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main"
+
+ install_gemfile <<-G, :verbose => true
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ end
+
+ it "displays the ref of the gem repository when using branch~num as a ref" do
skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform?
build_git "foo", "1.0", :path => lib_path("foo")
@@ -22,7 +33,7 @@ RSpec.describe "bundle install" do
rev2 = revision_for(lib_path("foo"))[0..6]
update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true
gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2"
G
@@ -31,7 +42,7 @@ RSpec.describe "bundle install" do
update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true
- bundle :update, :all => true
+ bundle :update, :all => true, :verbose => true
expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev2})")
expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}"
end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index af3a10f9e9..976db33b0e 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -1134,7 +1134,7 @@ RSpec.describe "the lockfile format" do
G
expect(bundled_app_lock).not_to exist
- expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)"
+ expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com"
end
it "works correctly with multiple version dependencies" do
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index d061ca7064..0758d29746 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,7 +378,7 @@ 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 " \
@@ -389,7 +389,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 "when Bundler.setup is run in a ruby script" do
@@ -422,14 +422,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 +439,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 +461,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 +483,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 +514,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 +526,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 +538,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 +550,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 +562,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 +574,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 +587,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 +603,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/quality_spec.rb b/spec/bundler/quality_spec.rb
index 405c786842..2b1e28fa30 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -220,7 +220,7 @@ RSpec.describe "The library itself" do
gem_list = loaded_gemspec.files
- expect(git_list.to_set).to eq(gem_list.to_set)
+ expect(git_list.sort).to eq(gem_list.sort)
end
it "does not contain any warnings" do
diff --git a/spec/bundler/realworld/double_check_spec.rb b/spec/bundler/realworld/double_check_spec.rb
index 0a8f5e4d9e..07697f080e 100644
--- a/spec/bundler/realworld/double_check_spec.rb
+++ b/spec/bundler/realworld/double_check_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "double checking sources", :realworld => true, :sometimes => true do
+RSpec.describe "double checking sources", :realworld => true do
it "finds already-installed gems" do
create_file("rails.gemspec", <<-RUBY)
Gem::Specification.new do |s|
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index 0f19cc7842..1925f76c06 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
+RSpec.describe "real world edgecases", :realworld => true do
def rubygems_version(name, requirement)
ruby <<-RUBY
require "#{spec_dir}/support/artifice/vcr"
@@ -64,6 +64,8 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do
# from https://github.com/rubygems/bundler/issues/5031
+ system_gems "bundler-2.99.0"
+
gemfile <<-G
source "https://rubygems.org"
gem 'rails', '~> 4.2.7.1'
@@ -189,7 +191,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
rails (~> 4.2.7.1)
L
- bundle "lock --update paperclip"
+ bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" }
expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
end
@@ -448,12 +450,219 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
end
G
+ if Bundler.feature_flag.bundler_3_mode?
+ # Conflicts on bundler version, so fails earlier
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false
+ expect(out).to display_total_steps_of(435)
+ else
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
+ expect(out).to display_total_steps_of(1025)
+ end
+ end
+
+ it "doesn't hang on tricky gemfile" do
+ skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2"
+
+ gemfile <<~G
+ source 'https://rubygems.org'
+
+ group :development do
+ gem "puppet-module-posix-default-r2.7", '~> 0.3'
+ gem "puppet-module-posix-dev-r2.7", '~> 0.3'
+ gem "beaker-rspec"
+ gem "beaker-puppet"
+ gem "beaker-docker"
+ gem "beaker-puppet_install_helper"
+ gem "beaker-module_install_helper"
+ end
+ G
+
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
+
+ if Bundler.feature_flag.bundler_3_mode?
+ expect(out).to display_total_steps_of(890)
+ else
+ expect(out).to display_total_steps_of(891)
+ end
+ end
+
+ it "doesn't hang on nix gemfile" do
+ skip "Only for ruby 3.0.0" if RUBY_VERSION != "3.0.0"
+
+ gemfile <<~G
+ source "https://rubygems.org" do
+ gem "addressable"
+ gem "atk"
+ gem "awesome_print"
+ gem "bacon"
+ gem "byebug"
+ gem "cairo"
+ gem "cairo-gobject"
+ gem "camping"
+ gem "charlock_holmes"
+ gem "cld3"
+ gem "cocoapods"
+ gem "cocoapods-acknowledgements"
+ gem "cocoapods-art"
+ gem "cocoapods-bin"
+ gem "cocoapods-browser"
+ gem "cocoapods-bugsnag"
+ gem "cocoapods-check"
+ gem "cocoapods-clean"
+ gem "cocoapods-clean_build_phases_scripts"
+ gem "cocoapods-core"
+ gem "cocoapods-coverage"
+ gem "cocoapods-deintegrate"
+ gem "cocoapods-dependencies"
+ gem "cocoapods-deploy"
+ gem "cocoapods-downloader"
+ gem "cocoapods-expert-difficulty"
+ gem "cocoapods-fix-react-native"
+ gem "cocoapods-generate"
+ gem "cocoapods-git_url_rewriter"
+ gem "cocoapods-keys"
+ gem "cocoapods-no-dev-schemes"
+ gem "cocoapods-open"
+ gem "cocoapods-packager"
+ gem "cocoapods-playgrounds"
+ gem "cocoapods-plugins"
+ gem "cocoapods-prune-localizations"
+ gem "cocoapods-rome"
+ gem "cocoapods-search"
+ gem "cocoapods-sorted-search"
+ gem "cocoapods-static-swift-framework"
+ gem "cocoapods-stats"
+ gem "cocoapods-tdfire-binary"
+ gem "cocoapods-testing"
+ gem "cocoapods-trunk"
+ gem "cocoapods-try"
+ gem "cocoapods-try-release-fix"
+ gem "cocoapods-update-if-you-dare"
+ gem "cocoapods-whitelist"
+ gem "cocoapods-wholemodule"
+ gem "coderay"
+ gem "concurrent-ruby"
+ gem "curb"
+ gem "curses"
+ gem "daemons"
+ gem "dep-selector-libgecode"
+ gem "digest-sha3"
+ gem "domain_name"
+ gem "do_sqlite3"
+ gem "ethon"
+ gem "eventmachine"
+ gem "excon"
+ gem "faraday"
+ gem "ffi"
+ gem "ffi-rzmq-core"
+ gem "fog-dnsimple"
+ gem "gdk_pixbuf2"
+ gem "gio2"
+ gem "gitlab-markup"
+ gem "glib2"
+ gem "gpgme"
+ gem "gtk2"
+ gem "hashie"
+ gem "highline"
+ gem "hike"
+ gem "hitimes"
+ gem "hpricot"
+ gem "httpclient"
+ gem "http-cookie"
+ gem "iconv"
+ gem "idn-ruby"
+ gem "jbuilder"
+ gem "jekyll"
+ gem "jmespath"
+ gem "jwt"
+ gem "libv8"
+ gem "libxml-ruby"
+ gem "magic"
+ gem "markaby"
+ gem "method_source"
+ gem "mini_magick"
+ gem "msgpack"
+ gem "mysql2"
+ gem "ncursesw"
+ gem "netrc"
+ gem "net-scp"
+ gem "net-ssh"
+ gem "nokogiri"
+ gem "opus-ruby"
+ gem "ovirt-engine-sdk"
+ gem "pango"
+ gem "patron"
+ gem "pcaprub"
+ gem "pg"
+ gem "pry"
+ gem "pry-byebug"
+ gem "pry-doc"
+ gem "public_suffix"
+ gem "puma"
+ gem "rails"
+ gem "rainbow"
+ gem "rbnacl"
+ gem "rb-readline"
+ gem "re2"
+ gem "redis"
+ gem "redis-rack"
+ gem "rest-client"
+ gem "rmagick"
+ gem "rpam2"
+ gem "rspec"
+ gem "rubocop"
+ gem "rubocop-performance"
+ gem "ruby-libvirt"
+ gem "ruby-lxc"
+ gem "ruby-progressbar"
+ gem "ruby-terminfo"
+ gem "ruby-vips"
+ gem "rubyzip"
+ gem "rugged"
+ gem "sassc"
+ gem "scrypt"
+ gem "semian"
+ gem "sequel"
+ gem "sequel_pg"
+ gem "simplecov"
+ gem "sinatra"
+ gem "slop"
+ gem "snappy"
+ gem "sqlite3"
+ gem "taglib-ruby"
+ gem "thrift"
+ gem "tilt"
+ gem "tiny_tds"
+ gem "treetop"
+ gem "typhoeus"
+ gem "tzinfo"
+ gem "unf_ext"
+ gem "uuid4r"
+ gem "whois"
+ gem "zookeeper"
+ end
+ G
+
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
if Bundler.feature_flag.bundler_3_mode?
- expect(out).to include("BUNDLER: Finished resolution (2492 steps)")
+ expect(out).to display_total_steps_of(1874)
else
- expect(out).to include("BUNDLER: Finished resolution (2722 steps)")
+ expect(out).to display_total_steps_of(1922)
+ end
+ end
+
+ private
+
+ RSpec::Matchers.define :display_total_steps_of do |expected_steps|
+ match do |out|
+ out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)")
+ end
+
+ failure_message do |out|
+ actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first
+
+ "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}"
end
end
end
diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb
index 2a5154ffbf..97c0e0cab4 100644
--- a/spec/bundler/realworld/parallel_spec.rb
+++ b/spec/bundler/realworld/parallel_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "parallel", :realworld => true, :sometimes => true do
+RSpec.describe "parallel", :realworld => true do
it "installs" do
gemfile <<-G
source "https://rubygems.org"
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
new file mode 100644
index 0000000000..518da2800b
--- /dev/null
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "bundle install with complex dependencies", :realworld => true do
+ it "resolves quickly" do
+ start_time = Time.now
+
+ install_gemfile <<-G
+ source 'https://rubygems.org'
+
+ gem "actionmailer"
+ gem "mongoid", ">= 0.10.2"
+ G
+
+ duration = Time.now - start_time
+
+ expect(duration.to_f).to be < 120 # seconds
+ end
+end
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb
index 57897f89b4..ee62dc3577 100644
--- a/spec/bundler/resolver/basic_spec.rb
+++ b/spec/bundler/resolver/basic_spec.rb
@@ -176,7 +176,7 @@ Bundler could not find compatible versions for gem "a":
deps = []
@deps.each do |d|
- deps << Bundler::DepProxy.new(d, "ruby")
+ deps << Bundler::DepProxy.get_proxy(d, "ruby")
end
should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]]
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index 415c5458df..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"
@@ -120,6 +137,157 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[foo-1.1.0]
end
+ it "doesn't include gems not needed for none of the platforms" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "includes gems needed for at least one platform" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "extra2", ">= 0"
+ end
+
+ gem "extra2", "1.0.0" do
+ dep "extra3", ">= 0"
+ end
+
+ gem "extra3", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "properly adds platforms when platform requirements come from different dependencies" do
+ @index = build_index do
+ gem "ffi", "1.9.14"
+ gem "ffi", "1.9.14", "universal-mingw32"
+
+ gem "gssapi", "0.1"
+ gem "gssapi", "0.2"
+ gem "gssapi", "0.3"
+ gem "gssapi", "1.2.0" do
+ dep "ffi", ">= 1.0.1"
+ end
+
+ gem "mixlib-shellout", "2.2.6"
+ gem "mixlib-shellout", "2.2.6", "universal-mingw32" do
+ dep "win32-process", "~> 0.8.2"
+ end
+
+ # we need all these versions to get the sorting the same as it would be
+ # pulling from rubygems.org
+ %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v|
+ gem "win32-process", v do
+ dep "ffi", ">= 1.0.0"
+ end
+ end
+ end
+
+ dep "mixlib-shellout"
+ dep "gssapi"
+
+ platforms "universal-mingw32", "ruby"
+
+ should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3]
+ end
+
describe "with mingw32" do
before :each do
@index = build_index do
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index b46da20096..bd136ddcd7 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -46,8 +46,6 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "requires the gems" do
- skip "gems not found" if Gem.win_platform?
-
script <<-RUBY
gemfile do
path "#{lib_path}" do
@@ -94,8 +92,6 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "lets me use my own ui object" do
- skip "prints just one CONFIRMED" if Gem.win_platform?
-
script <<-RUBY, :artifice => "endpoint"
require '#{lib_dir}/bundler'
class MyBundlerUI < Bundler::UI::Silent
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index 215ba8628f..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
@@ -84,9 +167,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
end
- it "allows specifying only-ruby-platform" do
- simulate_platform "java"
-
+ it "allows specifying only-ruby-platform on jruby", :jruby do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
@@ -100,6 +181,29 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
end
+ it "allows specifying only-ruby-platform" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
+
+ bundle "config set force_ruby_platform true"
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ end
+
+ it "doesn't pull platform specific gems on truffleruby", :truffleruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ end
+
it "allows specifying only-ruby-platform on windows with dependency platforms" do
simulate_windows do
install_gemfile <<-G
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index e2bed00a7f..a0036df39e 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -1252,7 +1252,7 @@ end
exempts << "fiddle" if Gem.win_platform? && Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
exempts << "uri" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7")
exempts << "pathname" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0")
- exempts << "set" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0")
+ exempts << "set" unless Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.2.6")
exempts << "tsort" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0")
exempts
end
@@ -1334,36 +1334,8 @@ end
expect(out).to eq("The Gemfile's dependencies are satisfied")
end
- # bundler respects paths specified directly in RUBYLIB or RUBYOPT, and
- # that happens when running ruby from the ruby-core setup. To
- # workaround, we manually remove those for these tests when they would
- # override the default gem.
- def load_path_exclusions_hack_for(name)
- if ruby_core?
- if ENV.key?("PWD")
- # .ext/common is relative from build directory
- ext_folder = Pathname(ENV["PWD"]) + ".ext/common"
- else
- ext_folder = source_root.join(".ext/common")
- end
- require_name = name.tr("-", "/")
- if File.exist?(ext_folder.join("#{require_name}.rb"))
- { :exclude_from_load_path => ext_folder.to_s }
- else
- lib_folder = source_lib_dir
- if File.exist?(lib_folder.join("#{require_name}.rb"))
- { :exclude_from_load_path => lib_folder.to_s }
- else
- {}
- end
- end
- else
- {}
- end
- end
-
Gem::Specification.select(&:default_gem?).map(&:name).each do |g|
- it "activates newer versions of #{g}" do
+ it "activates newer versions of #{g}", :ruby_repo do
skip if exemptions.include?(g)
build_repo4 do
@@ -1375,11 +1347,10 @@ end
gem "#{g}", "999999"
G
- opts = { :env => { "RUBYOPT" => activation_warning_hack_rubyopt } }
- expect(the_bundle).to include_gem("#{g} 999999", opts.merge(load_path_exclusions_hack_for(g)))
+ expect(the_bundle).to include_gem("#{g} 999999", :env => { "RUBYOPT" => activation_warning_hack_rubyopt })
end
- it "activates older versions of #{g}" do
+ it "activates older versions of #{g}", :ruby_repo do
skip if exemptions.include?(g)
build_repo4 do
@@ -1391,8 +1362,7 @@ end
gem "#{g}", "0.0.0.a"
G
- opts = { :env => { "RUBYOPT" => activation_warning_hack_rubyopt } }
- expect(the_bundle).to include_gem("#{g} 0.0.0.a", opts.merge(load_path_exclusions_hack_for(g)))
+ expect(the_bundle).to include_gem("#{g} 0.0.0.a", :env => { "RUBYOPT" => activation_warning_hack_rubyopt })
end
end
end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 7723c85ce6..a72a1f5255 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -23,7 +23,6 @@ require_relative "support/indexes"
require_relative "support/matchers"
require_relative "support/permissions"
require_relative "support/platforms"
-require_relative "support/sometimes"
require_relative "support/sudo"
$debug = false
@@ -105,7 +104,7 @@ RSpec.configure do |config|
all_output = all_commands_output
if example.exception && !all_output.empty?
- message = example.exception.message + all_output
+ message = all_output + "\n" + example.exception.message
(class << example.exception; self; end).send(:define_method, :message) do
message
end
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index 02a2c0f659..c76c3f505e 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -547,9 +547,11 @@ module Spec
class GitBuilder < LibBuilder
def _build(options)
+ default_branch = options[:default_branch] || "master"
path = options[:path] || _default_path
source = options[:source] || "git@#{path}"
super(options.merge(:path => path, :source => source))
+ @context.git("config --global init.defaultBranch #{default_branch}", path)
@context.git("init", path)
@context.git("add *", path)
@context.git("config user.email lol@wut.com", path)
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index b1978e44e6..0c1f27e470 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -32,7 +32,8 @@ RSpec.configure do |config|
config.filter_run_excluding :no_color_tty => Gem.win_platform? || !ENV["GITHUB_ACTION"].nil?
config.filter_run_excluding :permissions => Gem.win_platform?
config.filter_run_excluding :readline => Gem.win_platform?
- config.filter_run_excluding :jruby => RUBY_PLATFORM != "java"
+ config.filter_run_excluding :jruby => RUBY_ENGINE != "jruby"
+ config.filter_run_excluding :truffleruby => RUBY_ENGINE != "truffleruby"
config.filter_run_when_matching :focus unless ENV["CI"]
end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index c4018eb818..a7cc1ce810 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -275,14 +275,12 @@ module Spec
def install_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :install, opts
end
def lock_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :lock, opts
end
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index 7440523fc9..1f3c4ddaa6 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -22,7 +22,7 @@ module Spec
@deps.each do |d|
@platforms.each do |p|
source_requirements[d.name] = d.source = default_source
- deps << Bundler::DepProxy.new(d, p)
+ deps << Bundler::DepProxy.get_proxy(d, p)
end
end
source_requirements ||= {}
@@ -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/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 6c9ab0d410..5d129ed849 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -115,7 +115,6 @@ module Spec
opts = names.last.is_a?(Hash) ? names.pop : {}
source = opts.delete(:source)
groups = Array(opts[:groups])
- exclude_from_load_path = opts.delete(:exclude_from_load_path)
opts[:raise_on_error] = false
groups << opts
@errors = names.map do |name|
@@ -123,11 +122,6 @@ module Spec
require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
code = []
- if exclude_from_load_path
- code << "exclude_from_load_path = File.expand_path('#{exclude_from_load_path}')"
- code << "$LOAD_PATH.delete_if { |path| File.expand_path(path) == exclude_from_load_path }"
- end
- code << "$LOADED_FEATURES.delete_if { |feature| File.basename(feature, '.*') == '#{require_path}' }"
code << "require '#{require_path}.rb'"
code << "puts #{version_const}"
run code.join("; "), *groups
@@ -151,23 +145,34 @@ module Spec
match_when_negated do
opts = names.last.is_a?(Hash) ? names.pop : {}
- groups = Array(opts[:groups]) || []
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
opts[:raise_on_error] = false
@errors = names.map do |name|
name, version = name.split(/\s+/, 2)
- run <<-R, *(groups + [opts])
+ ruby <<-R, opts
+ begin
+ require '#{lib_dir}/bundler'
+ Bundler.setup(#{groups})
+ rescue Bundler::GemNotFound, Bundler::GitError
+ exit 0
+ end
+
begin
require '#{name}'
- puts #{Spec::Builders.constantize(name)}
+ name_constant = '#{Spec::Builders.constantize(name)}'
+ if #{version.nil?} || name_constant == '#{version}'
+ exit 64
+ else
+ exit 0
+ end
rescue LoadError, NameError
- puts "WIN"
+ exit 0
end
R
- next if out == "WIN"
+ next if exitstatus == 0
+ next "command to check version of #{name} installed failed" unless exitstatus == 64
next "expected #{name} to not be installed, but it was" if version.nil?
- if Gem::Version.new(out) == Gem::Version.new(version)
- next "expected #{name} (#{version}) not to be installed, but it was"
- end
+ next "expected #{name} (#{version}) not to be installed, but it was"
end.compact
@errors.empty?
diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb
index ac02021cff..c2e5a5f484 100644
--- a/spec/bundler/support/rubygems_version_manager.rb
+++ b/spec/bundler/support/rubygems_version_manager.rb
@@ -78,6 +78,7 @@ class RubygemsVersionManager
end
def rubygems_unrequire_needed?
+ require "rubygems"
!$LOADED_FEATURES.include?(local_copy_path.join("lib/rubygems.rb").to_s)
end
diff --git a/spec/bundler/support/sometimes.rb b/spec/bundler/support/sometimes.rb
deleted file mode 100644
index 65a95ed59c..0000000000
--- a/spec/bundler/support/sometimes.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Sometimes
- def run_with_retries(example_to_run, retries)
- example = RSpec.current_example
- example.metadata[:retries] ||= retries
-
- retries.times do |t|
- example.metadata[:retried] = t + 1
- example.instance_variable_set(:@exception, nil)
- example_to_run.run
- break unless example.exception
- end
-
- if e = example.exception
- new_exception = e.exception(e.message + "[Retried #{retries} times]")
- new_exception.set_backtrace e.backtrace
- example.instance_variable_set(:@exception, new_exception)
- end
- end
-end
-
-RSpec.configure do |config|
- config.include Sometimes
- config.alias_example_to :sometimes, :sometimes => true
- config.add_setting :sometimes_retry_count, :default => 5
-
- config.around(:each, :sometimes => true) do |example|
- retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count
- run_with_retries(example, retries)
- end
-
- config.after(:suite) do
- message = proc do |color, text|
- colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color)
- notification = RSpec::Core::Notifications::MessageNotification.new(colored)
- formatter = RSpec.configuration.formatters.first
- formatter.message(notification) if formatter.respond_to?(:message)
- end
-
- retried_examples = RSpec.world.example_groups.map do |g|
- g.descendants.map do |d|
- d.filtered_examples.select do |e|
- e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1
- end
- end
- end.flatten
-
- message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}")
-
- retried_examples.each do |e|
- message.call(:cyan, " #{e.full_description}")
- path = RSpec::Core::Metadata.relative_path(e.location)
- message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path)
- end
- end
-end
diff --git a/test/rubygems/data/null-required-ruby-version.gemspec.rz b/test/rubygems/data/null-required-ruby-version.gemspec.rz
new file mode 100644
index 0000000000..f4ec1a9620
--- /dev/null
+++ b/test/rubygems/data/null-required-ruby-version.gemspec.rz
Binary files differ
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index 344b03be9b..8b028d3495 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -297,6 +297,58 @@ class TestGem < Gem::TestCase
assert_equal %w[a-1 b-2 c-1], loaded_spec_names
end
+ def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies
+ a1 = util_spec 'a', '1' do |s|
+ s.executables = ['exec']
+ s.add_dependency 'b'
+ end
+
+ b1 = util_spec 'b', '1' do |s|
+ s.add_dependency 'c', '1'
+ end
+
+ b2 = util_spec 'b', '2' do |s|
+ s.add_dependency 'c', '2'
+ end
+
+ c2 = util_spec 'c', '2'
+
+ install_specs c2, b1, b2, a1
+
+ # c1 is missing, but not needed for activation, so we should not get any errors here
+
+ Gem.activate_bin_path("a", "exec", ">= 0")
+
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ end
+
+ def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies
+ a1 = util_spec 'a', '1' do |s|
+ s.executables = ['exec']
+ s.add_dependency 'b'
+ end
+
+ b1 = util_spec 'b', '1' do |s|
+ s.add_dependency 'c', '1'
+ end
+
+ b2 = util_spec 'b', '2' do |s|
+ s.add_dependency 'c', '2'
+ end
+
+ c1 = util_spec 'c', '1'
+
+ install_specs c1, b1, b2, a1
+
+ # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency
+
+ e = assert_raises Gem::UnsatisfiableDependencyError do
+ load Gem.activate_bin_path("a", "exec", ">= 0")
+ end
+
+ assert_equal "Unable to resolve dependency: 'b (>= 0)' requires 'c (= 2)'", e.message
+ end
+
def test_activate_bin_path_in_debug_mode
a1 = util_spec 'a', '1' do |s|
s.executables = ['exec']
@@ -416,6 +468,32 @@ class TestGem < Gem::TestCase
assert_equal %w[bundler-1.17.3], loaded_spec_names
end
+ def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given
+ File.open("Gemfile.lock", "w") do |f|
+ f.write <<-L.gsub(/ {8}/, "")
+ GEM
+ remote: https://rubygems.org/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ 2.1.4
+ L
+ end
+
+ File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
+
+ e = assert_raises Gem::GemNotFoundException do
+ load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8")
+ end
+
+ assert_equal "can't find gem bundler (= 2.2.8) with executable bundle", e.message
+ end
+
def test_self_bin_path_no_exec_name
e = assert_raises ArgumentError do
Gem.bin_path 'a'
@@ -692,6 +770,11 @@ class TestGem < Gem::TestCase
ensure
FileUtils.chmod 0600, parent
end
+
+ def test_self_ensure_gem_directories_non_existent_paths
+ Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise
+ Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario
+ end
end
def test_self_extension_dir_shared
@@ -1875,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
diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb
index 57939b8088..c4af421f5d 100644
--- a/test/rubygems/test_gem_commands_outdated_command.rb
+++ b/test/rubygems/test_gem_commands_outdated_command.rb
@@ -28,4 +28,22 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
assert_equal "foo (0.2 < 2.0)\n", @ui.output
assert_equal "", @ui.error
end
+
+ def test_execute_with_up_to_date_platform_specific_gem
+ spec_fetcher do |fetcher|
+ fetcher.download 'foo', '2.0'
+
+ fetcher.gem 'foo', '1.0'
+ fetcher.gem 'foo', '2.0' do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
+ end
end
diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb
index ddc35a9594..7db31013aa 100644
--- a/test/rubygems/test_gem_config_file.rb
+++ b/test/rubygems/test_gem_config_file.rb
@@ -41,6 +41,7 @@ class TestGemConfigFile < Gem::TestCase
assert_equal true, @cfg.verbose
assert_equal [@gem_repo], Gem.sources
assert_equal 365, @cfg.cert_expiration_length_days
+ assert_equal false, @cfg.ipv4_fallback_enabled
File.open @temp_conf, 'w' do |fp|
fp.puts ":backtrace: true"
@@ -56,6 +57,7 @@ class TestGemConfigFile < Gem::TestCase
fp.puts ":ssl_verify_mode: 0"
fp.puts ":ssl_ca_cert: /etc/ssl/certs"
fp.puts ":cert_expiration_length_days: 28"
+ fp.puts ":ipv4_fallback_enabled: true"
end
util_config_file
@@ -70,6 +72,14 @@ class TestGemConfigFile < Gem::TestCase
assert_equal 0, @cfg.ssl_verify_mode
assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert
assert_equal 28, @cfg.cert_expiration_length_days
+ assert_equal true, @cfg.ipv4_fallback_enabled
+ end
+
+ def test_initialize_ipv4_fallback_enabled_env
+ ENV['IPV4_FALLBACK_ENABLED'] = 'true'
+ util_config_file %W[--config-file #{@temp_conf}]
+
+ assert_equal true, @cfg.ipv4_fallback_enabled
end
def test_initialize_handle_arguments_config_file
diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb
index 85dba54675..c62a3f355a 100644
--- a/test/rubygems/test_gem_dependency_installer.rb
+++ b/test/rubygems/test_gem_dependency_installer.rb
@@ -44,7 +44,7 @@ class TestGemDependencyInstaller < Gem::TestCase
s.add_development_dependency 'c'
end
- util_reset_gems
+ util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1)
end
def test_install
@@ -287,8 +287,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -307,8 +305,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -329,8 +325,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -946,6 +940,31 @@ class TestGemDependencyInstaller < Gem::TestCase
assert_equal %w[d-2], inst.installed_gems.map {|s| s.full_name }
end
+ def test_install_legacy_spec_with_nil_required_ruby_version
+ path = File.expand_path "../data/null-required-ruby-version.gemspec.rz", __FILE__
+ spec = Marshal.load Gem.read_binary(path)
+ def spec.validate(*args); end
+
+ util_build_gem spec
+
+ cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ FileUtils.mkdir_p File.dirname cache_file
+ FileUtils.mv spec.cache_file, cache_file
+
+ util_setup_spec_fetcher spec
+
+ data = Gem.read_binary(cache_file)
+
+ @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data
+
+ dep = Gem::Dependency.new 'activesupport'
+
+ inst = Gem::DependencyInstaller.new
+ inst.install dep
+
+ assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name)
+ end
+
def test_install_legacy_spec_with_nil_required_rubygems_version
path = File.expand_path "../data/null-required-rubygems-version.gemspec.rz", __FILE__
spec = Marshal.load Gem.read_binary(path)
@@ -1131,16 +1150,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@d1, @d1_gem = util_gem 'd', '1'
@d2, @d2_gem = util_gem 'd', '2'
- util_reset_gems
- end
-
- def util_reset_gems
- @a1 ||= nil
- @b1 ||= nil
- @a1_pre ||= nil
- @d1 ||= nil
- @d2 ||= nil
-
- util_setup_spec_fetcher(*[@a1, @a1_pre, @b1, @d1, @d2].compact)
+ util_setup_spec_fetcher(@d1, @d2)
end
end
diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb
index 0fe650b8a5..6bebfa7a03 100644
--- a/test/rubygems/test_gem_ext_builder.rb
+++ b/test/rubygems/test_gem_ext_builder.rb
@@ -14,6 +14,7 @@ class TestGemExtBuilder < Gem::TestCase
FileUtils.mkdir_p @dest_path
@orig_DESTDIR = ENV['DESTDIR']
+ @orig_make = ENV['make']
@spec = util_spec 'a'
@@ -22,6 +23,7 @@ class TestGemExtBuilder < Gem::TestCase
def teardown
ENV['DESTDIR'] = @orig_DESTDIR
+ ENV['make'] = @orig_make
super
end
@@ -81,6 +83,28 @@ install:
assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results
end
+ def test_custom_make_with_options
+ ENV['make'] = 'make V=1'
+ results = []
+ File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ io.puts <<-MAKEFILE
+all:
+\t@#{Gem.ruby} -e "puts 'all: OK'"
+
+clean:
+\t@#{Gem.ruby} -e "puts 'clean: OK'"
+
+install:
+\t@#{Gem.ruby} -e "puts 'install: OK'"
+ MAKEFILE
+ end
+ Gem::Ext::Builder.make @dest_path, results, @ext
+ results = results.join("\n").b
+ assert_match %r{clean: OK}, results
+ assert_match %r{all: OK}, results
+ assert_match %r{install: OK}, results
+ end
+
def test_build_extensions
@spec.extensions << 'ext/extconf.rb'
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index 4ce7e92442..5652d86331 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -821,6 +821,8 @@ gem 'other', version
assert !File.exist?(system_path), 'plugin written incorrect written to system plugins_dir'
assert File.exist?(build_root_path), 'plugin not written to build_root'
+
+ refute_includes File.read(build_root_path), build_root
end
def test_keeps_plugins_up_to_date
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index 83a6f24de4..ad7285c082 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -134,7 +134,9 @@ 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],
@@ -143,6 +145,7 @@ 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
@@ -261,6 +264,32 @@ 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'
@@ -356,6 +385,14 @@ class TestGemPlatform < Gem::TestCase
assert_local_match 'sparc-solaris2.8-mq5.3'
end
+ def test_inspect
+ result = Gem::Platform.new("universal-java11").inspect
+
+ assert_equal 1, result.scan(/@cpu=/).size
+ assert_equal 1, result.scan(/@os=/).size
+ assert_equal 1, result.scan(/@version=/).size
+ end
+
def assert_local_match(name)
assert_match Gem::Platform.local, name
end
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 1c88e8d3e8..32600deee2 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -962,6 +962,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
end
+ def test_tcpsocketext_require
+ with_configured_fetcher(":ipv4_fallback_enabled: true") do |fetcher|
+ refute require('rubygems/core_ext/tcpsocket_init')
+ end
+ end
+
def with_configured_fetcher(config_str = nil, &block)
if config_str
temp_conf = File.join @tempdir, '.gemrc'
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index 670defe330..13897eaefb 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -83,7 +83,7 @@ class TestGemRequirement < Gem::TestCase
Gem::Requirement.parse(Gem::Version.new('2'))
end
- if RUBY_VERSION >= '2.5'
+ if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/)
def test_parse_deduplication
assert_same '~>', Gem::Requirement.parse('~> 1').first
end
@@ -401,6 +401,27 @@ class TestGemRequirement < Gem::TestCase
assert_equal r1.hash, r2.hash
end
+ def test_hash_returns_equal_hashes_for_equivalent_requirements
+ refute_requirement_hash_equal "= 1.2", "= 1.3"
+ refute_requirement_hash_equal "= 1.3", "= 1.2"
+
+ refute_requirement_hash_equal "~> 1.3", "~> 1.3.0"
+ refute_requirement_hash_equal "~> 1.3.0", "~> 1.3"
+
+ assert_requirement_hash_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]
+
+ assert_requirement_hash_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]
+ assert_requirement_hash_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]
+
+ assert_requirement_hash_equal "= 1.0", "= 1.0.0"
+ assert_requirement_hash_equal "= 1.1", "= 1.1.0"
+ assert_requirement_hash_equal "= 1", "= 1.0.0"
+
+ assert_requirement_hash_equal "1.0", "1.0.0"
+ assert_requirement_hash_equal "1.1", "1.1.0"
+ assert_requirement_hash_equal "1", "1.0.0"
+ end
+
# Assert that two requirements are equal. Handles Gem::Requirements,
# strings, arrays, numbers, and versions.
@@ -415,6 +436,13 @@ class TestGemRequirement < Gem::TestCase
"#{requirement} is satisfied by #{version}"
end
+ # Assert that two requirement hashes are equal. Handles Gem::Requirements,
+ # strings, arrays, numbers, and versions.
+
+ def assert_requirement_hash_equal(expected, actual)
+ assert_equal req(expected).hash, req(actual).hash
+ end
+
# Refute the assumption that two requirements are equal.
def refute_requirement_equal(unexpected, actual)
@@ -427,4 +455,10 @@ class TestGemRequirement < Gem::TestCase
refute req(requirement).satisfied_by?(v(version)),
"#{requirement} is not satisfied by #{version}"
end
+
+ # Refute the assumption that two requirements hashes are equal.
+
+ def refute_requirement_hash_equal(unexpected, actual)
+ refute_equal req(unexpected).hash, req(actual).hash
+ end
end
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 374d58d38f..1389b495f2 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -1161,6 +1161,14 @@ dependencies: []
Gem::Specification.class_variable_set(:@@stubs, nil)
end
+ def test_self_stubs_for_no_lazy_loading_after_all_specs_setup
+ Gem::Specification.all = [util_spec('a', '1')]
+
+ save_gemspec('b-1', '1', File.join(Gem.dir, 'specifications')){|s| s.name = 'b' }
+
+ assert_equal [], Gem::Specification.stubs_for('b').map {|s| s.full_name }
+ end
+
def test_self_stubs_for_mult_platforms
# gems for two different platforms are installed with --user-install
# the correct one should be returned in the array
@@ -1200,6 +1208,16 @@ dependencies: []
Gem.platforms = orig_platform
end
+ def test_self_stubs_returns_only_specified_named_specs
+ dir_standard_specs = File.join Gem.dir, 'specifications'
+
+ save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' }
+ save_gemspec('a-2', '2', dir_standard_specs){|s| s.name = 'a' }
+ save_gemspec('a-a', '3', dir_standard_specs){|s| s.name = 'a-a' }
+
+ assert_equal ['a-1', 'a-2'], Gem::Specification.stubs_for('a').map(&:full_name).sort
+ end
+
def test_handles_private_null_type
path = File.expand_path "../data/null-type.gemspec.rz", __FILE__
@@ -1612,20 +1630,6 @@ dependencies: []
refute_path_exists @a1.extension_dir
end
- def test_build_extensions_old
- skip "extensions don't quite work on jruby" if Gem.java_platform?
- ext_spec
-
- refute_empty @ext.extensions, 'sanity check'
-
- @ext.installed_by_version = v(0)
-
- @ext.build_extensions
-
- gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
- refute_path_exists gem_make_out
- end
-
def test_build_extensions_preview
skip "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
@@ -3522,19 +3526,6 @@ Did you mean 'Ruby'?
specfile.delete
end
- ##
- # KEEP p-1-x86-darwin-8
- # KEEP p-1
- # KEEP c-1.2
- # KEEP a_evil-9
- # a-1
- # a-1-x86-my_platform-1
- # KEEP a-2
- # a-2-x86-other_platform-1
- # KEEP a-2-x86-my_platform-1
- # a-3.a
- # KEEP a-3-x86-other_platform-1
-
def test_latest_specs
spec_fetcher do |fetcher|
fetcher.spec 'a', 1 do |s|
@@ -3557,8 +3548,6 @@ Did you mean 'Ruby'?
end
expected = %W[
- a-2
- a-2-x86-my_platform-1
a-3-x86-other_platform-1
]
@@ -3734,18 +3723,6 @@ end
refute spec.missing_extensions?
end
- def test_missing_extensions_eh_legacy
- ext_spec
-
- @ext.installed_by_version = v '2.2.0.preview.2'
-
- assert @ext.missing_extensions?
-
- @ext.installed_by_version = v '2.2.0.preview.1'
-
- refute @ext.missing_extensions?
- end
-
def test_missing_extensions_eh_none
refute @a1.missing_extensions?
end
diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb
index e154a723c9..a62e9ea0cf 100644
--- a/test/rubygems/test_gem_stream_ui.rb
+++ b/test/rubygems/test_gem_stream_ui.rb
@@ -5,7 +5,7 @@ require 'timeout'
class TestGemStreamUI < Gem::TestCase
# increase timeout with MJIT for --jit-wait testing
- mjit_enabled = defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ mjit_enabled = defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
SHORT_TIMEOUT = (RUBY_ENGINE == "ruby" && !mjit_enabled) ? 0.1 : 1.0
module IsTty
diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb
index acf7ac8962..7197f664e2 100644
--- a/test/rubygems/test_gem_util.rb
+++ b/test/rubygems/test_gem_util.rb
@@ -46,8 +46,8 @@ class TestGemUtil < Gem::TestCase
assert_equal File.join(@tempdir, 'd'), paths[0]
assert_equal @tempdir, paths[1]
- assert_equal File.realpath(Dir.tmpdir), paths[2]
- assert_equal File.realpath("..", Dir.tmpdir), paths[3]
+ assert_equal File.realpath("..", @tempdir), paths[2]
+ assert_equal File.realpath("../..", @tempdir), paths[3]
ensure
# restore default permissions, allow the directory to be removed
FileUtils.chmod(0775, 'd/e') unless win_platform? || java_platform?
@@ -72,10 +72,10 @@ class TestGemUtil < Gem::TestCase
]
files_with_absolute_base = Gem::Util.glob_files_in_dir('*.rb', File.join(@tempdir, 'g'))
- assert_equal expected_paths.to_set, files_with_absolute_base.to_set
+ assert_equal expected_paths.sort, files_with_absolute_base.sort
files_with_relative_base = Gem::Util.glob_files_in_dir('*.rb', 'g')
- assert_equal expected_paths.to_set, files_with_relative_base.to_set
+ assert_equal expected_paths.sort, files_with_relative_base.sort
end
def test_correct_for_windows_path