summaryrefslogtreecommitdiff
path: root/lib/bundler
diff options
context:
space:
mode:
authorDavid Rodríguez <deivid.rodriguez@riseup.net>2021-02-01 16:17:16 +0100
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2021-03-08 13:47:35 +0900
commit53468cc11147b0d285fc376fc546b677dad600ca (patch)
treeeb9c97f544d089be2d324126b025b11f41a22c90 /lib/bundler
parent2ab6b7a7516e1b2c48a66ce513afabb62d101461 (diff)
Sync latest development version of bundler & rubygems
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4143
Diffstat (limited to 'lib/bundler')
-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
79 files changed, 649 insertions, 438 deletions
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