1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Merge RubyGems-3.2.22 and Bundler-2.2.22

This commit is contained in:
Hiroshi SHIBATA 2021-07-07 08:57:34 +09:00 committed by nagachika
parent 865221f0ba
commit ec171fa1f9
73 changed files with 606 additions and 592 deletions

View file

@ -100,8 +100,11 @@ module Bundler
files_not_readable_or_writable = [] files_not_readable_or_writable = []
files_not_rw_and_owned_by_different_user = [] files_not_rw_and_owned_by_different_user = []
files_not_owned_by_current_user_but_still_rw = [] files_not_owned_by_current_user_but_still_rw = []
broken_symlinks = []
Find.find(Bundler.bundle_path.to_s).each do |f| Find.find(Bundler.bundle_path.to_s).each do |f|
if !File.writable?(f) || !File.readable?(f) if !File.exist?(f)
broken_symlinks << f
elsif !File.writable?(f) || !File.readable?(f)
if File.stat(f).uid != Process.uid if File.stat(f).uid != Process.uid
files_not_rw_and_owned_by_different_user << f files_not_rw_and_owned_by_different_user << f
else else
@ -113,6 +116,13 @@ module Bundler
end end
ok = true ok = true
if broken_symlinks.any?
Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
ok = false
end
if files_not_owned_by_current_user_but_still_rw.any? if files_not_owned_by_current_user_but_still_rw.any?
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \ Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
"user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}" "user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}"

View file

@ -104,7 +104,7 @@ module Bundler
private private
def warn_if_root def warn_if_root
return if Bundler.settings[:silence_root_warning] || Bundler::WINDOWS || !Process.uid.zero? return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \ Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \
"if it is needed, and installing your bundle as root will break this " \ "if it is needed, and installing your bundle as root will break this " \
"application for all non-root users on this machine.", :wrap => true "application for all non-root users on this machine.", :wrap => true

View file

@ -21,9 +21,13 @@ module Bundler
Bundler::Fetcher.disable_endpoint = options["full-index"] Bundler::Fetcher.disable_endpoint = options["full-index"]
update = options[:update] update = options[:update]
conservative = options[:conservative]
if update.is_a?(Array) # unlocking specific gems if update.is_a?(Array) # unlocking specific gems
Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update) Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update)
update = { :gems => update, :lock_shared_dependencies => options[:conservative] } update = { :gems => update, :conservative => conservative }
elsif update
update = { :conservative => conservative } if conservative
end end
definition = Bundler.definition(update) definition = Bundler.definition(update)

View file

@ -27,9 +27,14 @@ module Bundler
raise InvalidOption, "Cannot specify --all along with specific options." raise InvalidOption, "Cannot specify --all along with specific options."
end end
conservative = options[:conservative]
if full_update if full_update
# We're doing a full update if conservative
Bundler.definition(true) Bundler.definition(:conservative => conservative)
else
Bundler.definition(true)
end
else else
unless Bundler.default_lockfile.exist? unless Bundler.default_lockfile.exist?
raise GemfileLockNotFound, "This Bundle hasn't been installed yet. " \ raise GemfileLockNotFound, "This Bundle hasn't been installed yet. " \
@ -43,7 +48,7 @@ module Bundler
end end
Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby], Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
:lock_shared_dependencies => options[:conservative], :conservative => conservative,
:bundler => options[:bundler]) :bundler => options[:bundler])
end end

View file

@ -65,19 +65,19 @@ module Bundler
end end
def mswin? def mswin?
Bundler::WINDOWS Gem.win_platform?
end end
def mswin64? def mswin64?
Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64" Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
end end
def mingw? def mingw?
Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64" Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
end end
def x64_mingw? def x64_mingw?
Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64" Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
end end
(KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version| (KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version|

View file

@ -56,10 +56,8 @@ module Bundler
@unlocking_bundler = false @unlocking_bundler = false
@unlocking = unlock @unlocking = unlock
else else
unlock = unlock.dup
@unlocking_bundler = unlock.delete(:bundler) @unlocking_bundler = unlock.delete(:bundler)
unlock.delete_if {|_k, v| Array(v).empty? } @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
@unlocking = !unlock.empty?
end end
@dependencies = dependencies @dependencies = dependencies
@ -106,8 +104,8 @@ module Bundler
@locked_platforms = [] @locked_platforms = []
end end
@locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@multisource_allowed = @locked_gem_sources.any?(&:multiple_remotes?) && (sources.aggregate_global_source? || Bundler.frozen_bundle?) @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
if @multisource_allowed if @multisource_allowed
unless sources.aggregate_global_source? unless sources.aggregate_global_source?
@ -116,10 +114,9 @@ module Bundler
Bundler::SharedHelpers.major_deprecation 2, msg Bundler::SharedHelpers.major_deprecation 2, msg
end end
@sources.merged_gem_lockfile_sections! @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
end end
@unlock[:gems] ||= []
@unlock[:sources] ||= [] @unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@ruby_version.diff(locked_ruby_version_object) @ruby_version.diff(locked_ruby_version_object)
@ -132,8 +129,10 @@ module Bundler
@path_changes = converge_paths @path_changes = converge_paths
@source_changes = converge_sources @source_changes = converge_sources
unless @unlock[:lock_shared_dependencies] if @unlock[:conservative]
eager_unlock = expand_dependencies(@unlock[:gems], true) @unlock[:gems] ||= @dependencies.map(&:name)
else
eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
@unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name) @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
end end
@ -257,7 +256,7 @@ module Bundler
def specs_for(groups) def specs_for(groups)
deps = dependencies_for(groups) deps = dependencies_for(groups)
specs.for(expand_dependencies(deps)) SpecSet.new(specs.for(expand_dependencies(deps)))
end end
def dependencies_for(groups) def dependencies_for(groups)
@ -498,9 +497,6 @@ module Bundler
attr_reader :sources attr_reader :sources
private :sources private :sources
attr_reader :locked_gem_sources
private :locked_gem_sources
def nothing_changed? def nothing_changed?
!@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
end end
@ -628,35 +624,11 @@ module Bundler
end end
end end
def converge_rubygems_sources
return false unless multisource_allowed?
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
locked_gem_sources.each do |locked_gem_source|
# Merge the remotes from the Gemfile into the Gemfile.lock
changes |= locked_gem_source.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
end
changes
end
def converge_sources def converge_sources
changes = false
changes |= converge_rubygems_sources
# Replace the sources from the Gemfile with the sources from the Gemfile.lock, # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
# source in the Gemfile.lock, use the one from the Gemfile. # source in the Gemfile.lock, use the one from the Gemfile.
changes |= sources.replace_sources!(@locked_sources) changes = sources.replace_sources!(@locked_sources)
sources.all_sources.each do |source| sources.all_sources.each do |source|
# If the source is unlockable and the current command allows an unlock of # If the source is unlockable and the current command allows an unlock of
@ -741,8 +713,6 @@ module Bundler
end end
end end
unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
converged = [] converged = []
@locked_specs.each do |s| @locked_specs.each do |s|
# Replace the locked dependency's source with the equivalent source from the Gemfile # Replace the locked dependency's source with the equivalent source from the Gemfile
@ -754,11 +724,6 @@ module Bundler
next if s.source.nil? next if s.source.nil?
next if @unlock[:sources].include?(s.source.name) next if @unlock[:sources].include?(s.source.name)
# XXX This is a backwards-compatibility fix to preserve the ability to
# unlock a single gem by passing its name via `--source`. See issue #3759
# TODO: delete in Bundler 2
next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
# If the spec is from a path source and it doesn't exist anymore # If the spec is from a path source and it doesn't exist anymore
# then we unlock it. # then we unlock it.
@ -790,7 +755,7 @@ module Bundler
resolve = SpecSet.new(converged) resolve = SpecSet.new(converged)
@locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true) @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false) resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), [], false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
diff = nil diff = nil
# Now, we unlock any sources that do not have anymore gems pinned to it # Now, we unlock any sources that do not have anymore gems pinned to it
@ -912,14 +877,13 @@ module Bundler
end end
def additional_base_requirements_for_resolve def additional_base_requirements_for_resolve
return [] unless @locked_gems return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) } dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
@locked_gems.specs.reduce({}) do |requirements, locked_spec| @locked_gems.specs.reduce({}) do |requirements, locked_spec|
name = locked_spec.name name = locked_spec.name
dependency = dependencies_by_name[name] dependency = dependencies_by_name[name]
next requirements unless dependency
next requirements if @locked_gems.dependencies[name] != dependency next requirements if @locked_gems.dependencies[name] != dependency
next requirements if dependency.source.is_a?(Source::Path) next requirements if dependency && dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}") dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform) requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
requirements requirements

View file

@ -24,9 +24,6 @@ module Bundler
def initialize def initialize
@source = nil @source = nil
@sources = SourceList.new @sources = SourceList.new
@global_rubygems_sources = []
@git_sources = {} @git_sources = {}
@dependencies = [] @dependencies = []
@groups = [] @groups = []
@ -48,7 +45,6 @@ module Bundler
@gemfiles << expanded_gemfile_path @gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s) contents ||= Bundler.read_file(@gemfile.to_s)
instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1) 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 rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \ message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@ -168,7 +164,7 @@ module Bundler
elsif block_given? elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk) with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else else
@global_rubygems_sources << source @sources.add_global_rubygems_remote(source)
end end
end end
@ -222,6 +218,7 @@ module Bundler
end end
def to_definition(lockfile, unlock) def to_definition(lockfile, unlock)
check_primary_source_safety
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles) Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
end end
@ -453,12 +450,7 @@ repo_name ||= user_name
end end
def check_rubygems_source_safety def check_rubygems_source_safety
@sources.global_rubygems_source = @global_rubygems_sources.shift return unless @sources.aggregate_global_source?
return if @global_rubygems_sources.empty?
@global_rubygems_sources.each do |source|
@sources.add_rubygems_remote(source)
end
if Bundler.feature_flag.bundler_3_mode? if Bundler.feature_flag.bundler_3_mode?
msg = "This Gemfile contains multiple primary sources. " \ msg = "This Gemfile contains multiple primary sources. " \

View file

@ -38,7 +38,6 @@ module Bundler
settings_flag(:print_only_version_number) { bundler_3_mode? } settings_flag(:print_only_version_number) { bundler_3_mode? }
settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? } settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? }
settings_flag(:suppress_install_using_messages) { bundler_3_mode? } settings_flag(:suppress_install_using_messages) { bundler_3_mode? }
settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_4_mode? } settings_flag(:update_requires_all_flag) { bundler_4_mode? }
settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? } settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? }

View file

@ -68,8 +68,7 @@ module Bundler
raise CertificateFailureError.new(uri) raise CertificateFailureError.new(uri)
rescue *HTTP_ERRORS => e rescue *HTTP_ERRORS => e
Bundler.ui.trace e Bundler.ui.trace e
case e.message if e.is_a?(SocketError) || e.message =~ /host down:/
when /host down:/, /getaddrinfo: nodename nor servname provided/
raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \ raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
"connection and try again." "connection and try again."
else else

View file

@ -135,7 +135,7 @@ module Bundler
next next
end end
mode = Bundler::WINDOWS ? "wb:UTF-8" : "w" mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb" require "erb"
content = if RUBY_VERSION >= "2.6" content = if RUBY_VERSION >= "2.6"
ERB.new(template, :trim_mode => "-").result(binding) ERB.new(template, :trim_mode => "-").result(binding)
@ -144,7 +144,7 @@ module Bundler
end end
File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask) File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
if Bundler::WINDOWS || options[:all_platforms] if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
File.write("#{binstub_path}.cmd", prefix + content, :mode => mode) File.write("#{binstub_path}.cmd", prefix + content, :mode => mode)
end end
@ -182,7 +182,7 @@ module Bundler
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path) executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
executable_path = executable_path executable_path = executable_path
mode = Bundler::WINDOWS ? "wb:UTF-8" : "w" mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb" require "erb"
content = if RUBY_VERSION >= "2.6" content = if RUBY_VERSION >= "2.6"
ERB.new(template, :trim_mode => "-").result(binding) ERB.new(template, :trim_mode => "-").result(binding)
@ -191,7 +191,7 @@ module Bundler
end end
File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755) File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
if Bundler::WINDOWS || options[:all_platforms] if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n" prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode) File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode)
end end

View file

@ -1,16 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
#--
# Some versions of the Bundler 1.1 RC series introduced corrupted
# lockfiles. There were two major problems:
#
# * multiple copies of the same GIT section appeared in the lockfile
# * when this happened, those sections got multiple copies of gems
# in those sections.
#
# As a result, Bundler 1.1 contains code that fixes the earlier
# corruption. We will remove this fix-up code in Bundler 1.2.
module Bundler module Bundler
class LockfileParser class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
@ -124,12 +113,7 @@ module Bundler
@sources << @current_source @sources << @current_source
when GIT when GIT
@current_source = TYPES[@type].from_lock(@opts) @current_source = TYPES[@type].from_lock(@opts)
# Strip out duplicate GIT sections @sources << @current_source
if @sources.include?(@current_source)
@current_source = @sources.find {|s| s == @current_source }
else
@sources << @current_source
end
when GEM when GEM
@opts["remotes"] = Array(@opts.delete("remote")).reverse @opts["remotes"] = Array(@opts.delete("remote")).reverse
@current_source = TYPES[@type].from_lock(@opts) @current_source = TYPES[@type].from_lock(@opts)
@ -212,9 +196,7 @@ module Bundler
@current_spec = LazySpecification.new(name, version, platform) @current_spec = LazySpecification.new(name, version, platform)
@current_spec.source = @current_source @current_spec.source = @current_source
# Avoid introducing multiple copies of the same spec (caused by @specs[@current_spec.identifier] = @current_spec
# duplicate GIT sections)
@specs[@current_spec.identifier] ||= @current_spec
elsif spaces.size == 6 elsif spaces.size == 6
version = version.split(",").map(&:strip) if version version = version.split(",").map(&:strip) if version
dep = Gem::Dependency.new(name, version) dep = Gem::Dependency.new(name, version)

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-ADD" "1" "May 2021" "" "" .TH "BUNDLE\-ADD" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-BINSTUBS" "1" "May 2021" "" "" .TH "BUNDLE\-BINSTUBS" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CACHE" "1" "May 2021" "" "" .TH "BUNDLE\-CACHE" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CHECK" "1" "May 2021" "" "" .TH "BUNDLE\-CHECK" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CLEAN" "1" "May 2021" "" "" .TH "BUNDLE\-CLEAN" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-CONFIG" "1" "May 2021" "" "" .TH "BUNDLE\-CONFIG" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options \fBbundle\-config\fR \- Set bundler configuration options
@ -274,9 +274,6 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\. \fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\.
. .
.IP "\(bu" 4 .IP "\(bu" 4
\fBunlock_source_unlocks_spec\fR (\fBBUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC\fR): Whether running \fBbundle update \-\-source NAME\fR unlocks a gem with the given name\. Defaults to \fBtrue\fR\.
.
.IP "\(bu" 4
\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\. \fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
. .
.IP "\(bu" 4 .IP "\(bu" 4

View file

@ -260,9 +260,6 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
The location where RubyGems installs binstubs. Defaults to `Gem.bindir`. The location where RubyGems installs binstubs. Defaults to `Gem.bindir`.
* `timeout` (`BUNDLE_TIMEOUT`): * `timeout` (`BUNDLE_TIMEOUT`):
The seconds allowed before timing out for network requests. Defaults to `10`. The seconds allowed before timing out for network requests. Defaults to `10`.
* `unlock_source_unlocks_spec` (`BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC`):
Whether running `bundle update --source NAME` unlocks a gem with the given
name. Defaults to `true`.
* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`): * `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`):
Require passing `--all` to `bundle update` when everything should be updated, Require passing `--all` to `bundle update` when everything should be updated,
and disallow passing no options to `bundle update`. and disallow passing no options to `bundle update`.

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-DOCTOR" "1" "May 2021" "" "" .TH "BUNDLE\-DOCTOR" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems \fBbundle\-doctor\fR \- Checks the bundle for common problems

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-EXEC" "1" "May 2021" "" "" .TH "BUNDLE\-EXEC" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle \fBbundle\-exec\fR \- Execute a command in the context of the bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-GEM" "1" "May 2021" "" "" .TH "BUNDLE\-GEM" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INFO" "1" "May 2021" "" "" .TH "BUNDLE\-INFO" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle \fBbundle\-info\fR \- Show information for the given gem in your bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INIT" "1" "May 2021" "" "" .TH "BUNDLE\-INIT" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory \fBbundle\-init\fR \- Generates a Gemfile into the current working directory

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INJECT" "1" "May 2021" "" "" .TH "BUNDLE\-INJECT" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-INSTALL" "1" "May 2021" "" "" .TH "BUNDLE\-INSTALL" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-LIST" "1" "May 2021" "" "" .TH "BUNDLE\-LIST" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle \fBbundle\-list\fR \- List all the gems in the bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-LOCK" "1" "May 2021" "" "" .TH "BUNDLE\-LOCK" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-OPEN" "1" "May 2021" "" "" .TH "BUNDLE\-OPEN" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-OUTDATED" "1" "May 2021" "" "" .TH "BUNDLE\-OUTDATED" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available \fBbundle\-outdated\fR \- List installed gems with newer versions available

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-PLATFORM" "1" "May 2021" "" "" .TH "BUNDLE\-PLATFORM" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information \fBbundle\-platform\fR \- Displays platform compatibility information

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-PRISTINE" "1" "May 2021" "" "" .TH "BUNDLE\-PRISTINE" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-REMOVE" "1" "May 2021" "" "" .TH "BUNDLE\-REMOVE" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile \fBbundle\-remove\fR \- Removes gems from the Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-SHOW" "1" "May 2021" "" "" .TH "BUNDLE\-SHOW" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-UPDATE" "1" "May 2021" "" "" .TH "BUNDLE\-UPDATE" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions \fBbundle\-update\fR \- Update your gems to the latest available versions
@ -79,7 +79,7 @@ Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR
. .
.TP .TP
\fB\-\-conservative\fR \fB\-\-conservative\fR
Use bundle install conservative update behavior and do not allow shared dependencies to be updated\. Use bundle install conservative update behavior and do not allow indirect dependencies to be updated\.
. .
.SH "UPDATING ALL GEMS" .SH "UPDATING ALL GEMS"
If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\. If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
@ -208,13 +208,13 @@ In this case, the two gems have their own set of dependencies, but they share \f
In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\. In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\.
. .
.P .P
To prevent updating shared dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR: To prevent updating indirect dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR:
. .
.P .P
In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\. In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\.
. .
.P .P
Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent shared dependencies from being updated\. Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent indirect dependencies from being updated\.
. .
.SH "PATCH LEVEL OPTIONS" .SH "PATCH LEVEL OPTIONS"
Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\. Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\.

View file

@ -80,7 +80,7 @@ gem.
Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`. Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
* `--conservative`: * `--conservative`:
Use bundle install conservative update behavior and do not allow shared dependencies to be updated. Use bundle install conservative update behavior and do not allow indirect dependencies to be updated.
## UPDATING ALL GEMS ## UPDATING ALL GEMS
@ -195,7 +195,7 @@ In short, by default, when you update a gem using `bundle update`, bundler will
update all dependencies of that gem, including those that are also dependencies update all dependencies of that gem, including those that are also dependencies
of another gem. of another gem.
To prevent updating shared dependencies, prior to version 1.14 the only option To prevent updating indirect dependencies, prior to version 1.14 the only option
was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html): was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html):
In this scenario, updating the `thin` version manually in the Gemfile(5), In this scenario, updating the `thin` version manually in the Gemfile(5),
@ -203,7 +203,7 @@ and then running [bundle install(1)](bundle-install.1.html) will only update `da
but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section
of [bundle install(1)](bundle-install.1.html). of [bundle install(1)](bundle-install.1.html).
Starting with 1.14, specifying the `--conservative` option will also prevent shared Starting with 1.14, specifying the `--conservative` option will also prevent indirect
dependencies from being updated. dependencies from being updated.
## PATCH LEVEL OPTIONS ## PATCH LEVEL OPTIONS

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE\-VIZ" "1" "May 2021" "" "" .TH "BUNDLE\-VIZ" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "BUNDLE" "1" "May 2021" "" "" .TH "BUNDLE" "1" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBbundle\fR \- Ruby Dependency Management \fBbundle\fR \- Ruby Dependency Management

View file

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "GEMFILE" "5" "May 2021" "" "" .TH "GEMFILE" "5" "June 2021" "" ""
. .
.SH "NAME" .SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs

View file

@ -77,7 +77,7 @@ module Bundler
source_list = SourceList.new source_list = SourceList.new
source_list.add_git_source(git_source_options) if git_source_options source_list.add_git_source(git_source_options) if git_source_options
source_list.global_rubygems_source = rubygems_source if rubygems_source source_list.add_global_rubygems_remote(rubygems_source) if rubygems_source
deps = names.map {|name| Dependency.new name, version } deps = names.map {|name| Dependency.new name, version }

View file

@ -21,7 +21,7 @@ module Bundler
base = SpecSet.new(base) unless base.is_a?(SpecSet) base = SpecSet.new(base) unless base.is_a?(SpecSet)
resolver = new(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) result = resolver.start(requirements)
SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") }) SpecSet.new(SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") }))
end end
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)

View file

@ -44,7 +44,6 @@ module Bundler
silence_deprecations silence_deprecations
silence_root_warning silence_root_warning
suppress_install_using_messages suppress_install_using_messages
unlock_source_unlocks_spec
update_requires_all_flag update_requires_all_flag
use_gem_version_promoter_for_major_updates use_gem_version_promoter_for_major_updates
].freeze ].freeze

View file

@ -73,7 +73,7 @@ module Bundler
def can_lock?(spec) def can_lock?(spec)
return super unless multiple_remotes? return super unless multiple_remotes?
spec.source.is_a?(Rubygems) include?(spec.source)
end end
def options def options
@ -252,19 +252,6 @@ module Bundler
other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth)) other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
end end
def replace_remotes(other_remotes, allow_equivalent = false)
return false if other_remotes == @remotes
equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
@remotes = []
other_remotes.reverse_each do |r|
add_remote r.to_s
end
!equivalent
end
def spec_names def spec_names
if @allow_remote && dependency_api_available? if @allow_remote && dependency_api_available?
remote_specs.spec_names remote_specs.spec_names

View file

@ -28,8 +28,9 @@ module Bundler
@merged_gem_lockfile_sections @merged_gem_lockfile_sections
end end
def merged_gem_lockfile_sections! def merged_gem_lockfile_sections!(replacement_source)
@merged_gem_lockfile_sections = true @merged_gem_lockfile_sections = true
@global_rubygems_source = replacement_source
end end
def aggregate_global_source? def aggregate_global_source?
@ -53,18 +54,17 @@ module Bundler
end end
def add_rubygems_source(options = {}) def add_rubygems_source(options = {})
add_source_to_list Source::Rubygems.new(options), @rubygems_sources new_source = Source::Rubygems.new(options)
return @global_rubygems_source if @global_rubygems_source == new_source
add_source_to_list new_source, @rubygems_sources
end end
def add_plugin_source(source, options = {}) def add_plugin_source(source, options = {})
add_source_to_list Plugin.source(source).new(options), @plugin_sources add_source_to_list Plugin.source(source).new(options), @plugin_sources
end end
def global_rubygems_source=(uri) def add_global_rubygems_remote(uri)
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri, "allow_local" => true)
end
def add_rubygems_remote(uri)
global_rubygems_source.add_remote(uri) global_rubygems_source.add_remote(uri)
global_rubygems_source global_rubygems_source
end end
@ -109,27 +109,26 @@ module Bundler
if merged_gem_lockfile_sections? if merged_gem_lockfile_sections?
[combine_rubygems_sources] [combine_rubygems_sources]
else else
rubygems_sources.sort_by(&:to_s).uniq rubygems_sources.sort_by(&:to_s)
end end
end end
# Returns true if there are changes # Returns true if there are changes
def replace_sources!(replacement_sources) def replace_sources!(replacement_sources)
return true if replacement_sources.empty? return false if replacement_sources.empty?
[path_sources, git_sources, plugin_sources].each do |source_list| @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
source_list.map! do |source|
replacement_sources.find {|s| s == source } || source
end
end
replacement_rubygems = merged_gem_lockfile_sections? && different_sources?(lock_sources, replacement_sources)
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } end
@global_rubygems_source = replacement_rubygems if replacement_rubygems
return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources) # Returns true if there are changes
def expired_sources?(replacement_sources)
return false if replacement_sources.empty?
false lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
different_sources?(lock_sources, replacement_sources)
end end
def local_only! def local_only!
@ -146,6 +145,24 @@ module Bundler
private private
def dup_with_replaced_sources(replacement_sources)
new_source_list = dup
new_source_list.replace_sources!(replacement_sources)
new_source_list
end
def map_sources(replacement_sources)
[path_sources, git_sources, plugin_sources].map do |sources|
sources.map do |source|
replacement_sources.find {|s| s == source } || source
end
end
end
def different_sources?(lock_sources, replacement_sources)
!equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
end
def rubygems_aggregate_class def rubygems_aggregate_class
Source::Rubygems Source::Rubygems
end end

View file

@ -46,11 +46,7 @@ module Bundler
specs << spec specs << spec
end end
check ? true : SpecSet.new(specs) check ? true : specs
end
def valid_for?(deps)
self.for(deps, [], true)
end end
def [](key) def [](key)
@ -77,7 +73,7 @@ module Bundler
end end
def materialize(deps, missing_specs = nil) def materialize(deps, missing_specs = nil)
materialized = self.for(deps, [], false, true, !missing_specs).to_a materialized = self.for(deps, [], false, true, !missing_specs)
materialized.group_by(&:source).each do |source, specs| materialized.group_by(&:source).each do |source, specs|
next unless specs.any?{|s| s.is_a?(LazySpecification) } next unless specs.any?{|s| s.is_a?(LazySpecification) }

View file

@ -1,7 +1,7 @@
# frozen_string_literal: false # frozen_string_literal: false
module Bundler module Bundler
VERSION = "2.2.21".freeze VERSION = "2.2.22".freeze
def self.bundler_major_version def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i @bundler_major_version ||= VERSION.split(".").first.to_i

View file

@ -8,7 +8,7 @@
require 'rbconfig' require 'rbconfig'
module Gem module Gem
VERSION = "3.2.21".freeze VERSION = "3.2.22".freeze
end end
# Must be first since it unloads the prelude from 1.9.2 # Must be first since it unloads the prelude from 1.9.2

View file

@ -7,37 +7,9 @@ class Gem::Commands::CertCommand < Gem::Command
super 'cert', 'Manage RubyGems certificates and signing settings', super 'cert', 'Manage RubyGems certificates and signing settings',
:add => [], :remove => [], :list => [], :build => [], :sign => [] :add => [], :remove => [], :list => [], :build => [], :sign => []
OptionParser.accept OpenSSL::X509::Certificate do |certificate_file| add_option('-a', '--add CERT',
begin 'Add a trusted certificate.') do |cert_file, options|
certificate = OpenSSL::X509::Certificate.new File.read certificate_file options[:add] << open_cert(cert_file)
rescue Errno::ENOENT
raise OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
rescue OpenSSL::X509::CertificateError
raise OptionParser::InvalidArgument,
"#{certificate_file}: invalid X509 certificate"
end
[certificate, certificate_file]
end
OptionParser.accept OpenSSL::PKey::RSA do |key_file|
begin
passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
key = OpenSSL::PKey::RSA.new File.read(key_file), passphrase
rescue Errno::ENOENT
raise OptionParser::InvalidArgument, "#{key_file}: does not exist"
rescue OpenSSL::PKey::RSAError
raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key"
end
raise OptionParser::InvalidArgument,
"#{key_file}: private key not found" unless key.private?
key
end
add_option('-a', '--add CERT', OpenSSL::X509::Certificate,
'Add a trusted certificate.') do |(cert, _), options|
options[:add] << cert
end end
add_option('-l', '--list [FILTER]', add_option('-l', '--list [FILTER]',
@ -60,15 +32,15 @@ class Gem::Commands::CertCommand < Gem::Command
options[:build] << email_address options[:build] << email_address
end end
add_option('-C', '--certificate CERT', OpenSSL::X509::Certificate, add_option('-C', '--certificate CERT',
'Signing certificate for --sign') do |(cert, cert_file), options| 'Signing certificate for --sign') do |cert_file, options|
options[:issuer_cert] = cert options[:issuer_cert] = open_cert(cert_file)
options[:issuer_cert_file] = cert_file options[:issuer_cert_file] = cert_file
end end
add_option('-K', '--private-key KEY', OpenSSL::PKey::RSA, add_option('-K', '--private-key KEY',
'Key for --sign or --build') do |key, options| 'Key for --sign or --build') do |key_file, options|
options[:key] = key options[:key] = open_private_key(key_file)
end end
add_option('-s', '--sign CERT', add_option('-s', '--sign CERT',
@ -97,7 +69,39 @@ class Gem::Commands::CertCommand < Gem::Command
say "Added '#{certificate.subject}'" say "Added '#{certificate.subject}'"
end end
def check_openssl
return if Gem::HAVE_OPENSSL
alert_error "OpenSSL library is required for the cert command"
terminate_interaction 1
end
def open_cert(certificate_file)
check_openssl
OpenSSL::X509::Certificate.new File.read certificate_file
rescue Errno::ENOENT
raise OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
rescue OpenSSL::X509::CertificateError
raise OptionParser::InvalidArgument,
"#{certificate_file}: invalid X509 certificate"
end
def open_private_key(key_file)
check_openssl
passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
key = OpenSSL::PKey::RSA.new File.read(key_file), passphrase
raise OptionParser::InvalidArgument,
"#{key_file}: private key not found" unless key.private?
key
rescue Errno::ENOENT
raise OptionParser::InvalidArgument, "#{key_file}: does not exist"
rescue OpenSSL::PKey::RSAError
raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key"
end
def execute def execute
check_openssl
options[:add].each do |certificate| options[:add].each do |certificate|
add_certificate certificate add_certificate certificate
end end
@ -311,4 +315,4 @@ For further reading on signing gems see `ri Gem::Security`.
# It's simple, but is all we need # It's simple, but is all we need
email =~ /\A.+@.+\z/ email =~ /\A.+@.+\z/
end end
end if Gem::HAVE_OPENSSL end

View file

@ -51,6 +51,13 @@ module Gem::GemcutterUtilities
end end
end end
##
# The OTP code from the command options or from the user's configuration.
def otp
options[:otp] || ENV["GEM_HOST_OTP_CODE"]
end
## ##
# The host to connect to either from the RUBYGEMS_HOST environment variable # The host to connect to either from the RUBYGEMS_HOST environment variable
# or from the user's configuration # or from the user's configuration
@ -126,7 +133,7 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:put, "api/v1/api_key", response = rubygems_api_request(:put, "api/v1/api_key",
sign_in_host, scope: scope) do |request| sign_in_host, scope: scope) do |request|
request.basic_auth email, password request.basic_auth email, password
request["OTP"] = options[:otp] if options[:otp] request["OTP"] = otp if otp
request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params)) request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params))
end end
@ -159,7 +166,7 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:post, "api/v1/api_key", response = rubygems_api_request(:post, "api/v1/api_key",
sign_in_host, scope: scope) do |request| sign_in_host, scope: scope) do |request|
request.basic_auth email, password request.basic_auth email, password
request["OTP"] = options[:otp] if options[:otp] request["OTP"] = otp if otp
request.body = URI.encode_www_form({ name: key_name }.merge(scope_params)) request.body = URI.encode_www_form({ name: key_name }.merge(scope_params))
end end
@ -224,7 +231,7 @@ module Gem::GemcutterUtilities
request_method = Net::HTTP.const_get method.to_s.capitalize request_method = Net::HTTP.const_get method.to_s.capitalize
Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req| Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req|
req["OTP"] = options[:otp] if options[:otp] req["OTP"] = otp if otp
block.call(req) block.call(req)
end end
end end

View file

@ -2421,7 +2421,6 @@ class Gem::Specification < Gem::BasicSpecification
# still have their default values are omitted. # still have their default values are omitted.
def to_ruby def to_ruby
require_relative 'openssl'
mark_version mark_version
result = [] result = []
result << "# -*- encoding: utf-8 -*-" result << "# -*- encoding: utf-8 -*-"
@ -2455,16 +2454,21 @@ class Gem::Specification < Gem::BasicSpecification
:has_rdoc, :has_rdoc,
:default_executable, :default_executable,
:metadata, :metadata,
:signing_key,
] ]
@@attributes.each do |attr_name| @@attributes.each do |attr_name|
next if handled.include? attr_name next if handled.include? attr_name
current_value = self.send(attr_name) current_value = self.send(attr_name)
if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name) if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name)
result << " s.#{attr_name} = #{ruby_code current_value}" unless defined?(OpenSSL::PKey::RSA) && current_value.is_a?(OpenSSL::PKey::RSA) result << " s.#{attr_name} = #{ruby_code current_value}"
end end
end end
if String === signing_key
result << " s.signing_key = #{signing_key.dump}.freeze"
end
if @installed_by_version if @installed_by_version
result << nil result << nil
result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version" result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version"

View file

@ -2,16 +2,6 @@
require "bundler/cli" require "bundler/cli"
using Module.new {
# Some `man` (e.g., on macOS) always highlights the output even to
# non-tty.
refine Spec::Helpers do
def out
super.gsub(/.[\b]/, "")
end
end
} if RUBY_VERSION >= "2.4"
RSpec.describe "bundle executable" do RSpec.describe "bundle executable" do
it "returns non-zero exit status when passed unrecognized options" do it "returns non-zero exit status when passed unrecognized options" do
bundle "--invalid_argument", :raise_on_error => false bundle "--invalid_argument", :raise_on_error => false
@ -42,49 +32,57 @@ RSpec.describe "bundle executable" do
it "aliases e to exec" do it "aliases e to exec" do
bundle "e --help" bundle "e --help"
expect(out).to include("bundle-exec") expect(out_with_macos_man_workaround).to include("bundle-exec")
end end
it "aliases ex to exec" do it "aliases ex to exec" do
bundle "ex --help" bundle "ex --help"
expect(out).to include("bundle-exec") expect(out_with_macos_man_workaround).to include("bundle-exec")
end end
it "aliases exe to exec" do it "aliases exe to exec" do
bundle "exe --help" bundle "exe --help"
expect(out).to include("bundle-exec") expect(out_with_macos_man_workaround).to include("bundle-exec")
end end
it "aliases c to check" do it "aliases c to check" do
bundle "c --help" bundle "c --help"
expect(out).to include("bundle-check") expect(out_with_macos_man_workaround).to include("bundle-check")
end end
it "aliases i to install" do it "aliases i to install" do
bundle "i --help" bundle "i --help"
expect(out).to include("bundle-install") expect(out_with_macos_man_workaround).to include("bundle-install")
end end
it "aliases ls to list" do it "aliases ls to list" do
bundle "ls --help" bundle "ls --help"
expect(out).to include("bundle-list") expect(out_with_macos_man_workaround).to include("bundle-list")
end end
it "aliases package to cache" do it "aliases package to cache" do
bundle "package --help" bundle "package --help"
expect(out).to include("bundle-cache") expect(out_with_macos_man_workaround).to include("bundle-cache")
end end
it "aliases pack to cache" do it "aliases pack to cache" do
bundle "pack --help" bundle "pack --help"
expect(out).to include("bundle-cache") expect(out_with_macos_man_workaround).to include("bundle-cache")
end
private
# Some `man` (e.g., on macOS) always highlights the output even to
# non-tty.
def out_with_macos_man_workaround
out.gsub(/.[\b]/, "")
end end
end end

View file

@ -194,7 +194,7 @@ RSpec.describe Bundler::Definition do
context "eager unlock" do context "eager unlock" do
let(:source_list) do let(:source_list) do
Bundler::SourceList.new.tap do |source_list| Bundler::SourceList.new.tap do |source_list|
source_list.global_rubygems_source = file_uri_for(gem_repo4) source_list.add_global_rubygems_remote(file_uri_for(gem_repo4))
end end
end end
@ -258,7 +258,7 @@ RSpec.describe Bundler::Definition do
bundled_app_lock, bundled_app_lock,
updated_deps_in_gemfile, updated_deps_in_gemfile,
source_list, source_list,
:gems => ["shared_owner_a"], :lock_shared_dependencies => true :gems => ["shared_owner_a"], :conservative => true
) )
locked = definition.send(:converge_locked_specs).map(&:name) locked = definition.send(:converge_locked_specs).map(&:name)
expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b] expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b]

View file

@ -231,16 +231,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
end end
end end
context "when error message is about getaddrinfo issues" do context "when error message is not about host down" do
let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" }
it "should raise a Bundler::Fetcher::NetworkDownError" do
expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
/Could not reach host www.uri-to-fetch.com/)
end
end
context "when error message is about neither host down or getaddrinfo" do
let(:message) { "other error about network" } let(:message) { "other error about network" }
it "should raise a Bundler::HTTPError" do it "should raise a Bundler::HTTPError" do

View file

@ -115,15 +115,15 @@ RSpec.describe Bundler::SourceList do
end end
end end
describe "#add_rubygems_remote", :bundler => "< 3" do describe "#add_global_rubygems_remote" do
let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") } let!(:returned_source) { source_list.add_global_rubygems_remote("https://rubygems.org/") }
it "returns the aggregate rubygems source" do it "returns the aggregate rubygems source" do
expect(returned_source).to be_instance_of(Bundler::Source::Rubygems) expect(returned_source).to be_instance_of(Bundler::Source::Rubygems)
end end
it "adds the provided remote to the beginning of the aggregate source" do it "adds the provided remote to the beginning of the aggregate source" do
source_list.add_rubygems_remote("https://othersource.org") source_list.add_global_rubygems_remote("https://othersource.org")
expect(returned_source.remotes).to eq [ expect(returned_source.remotes).to eq [
Bundler::URI("https://othersource.org/"), Bundler::URI("https://othersource.org/"),
Bundler::URI("https://rubygems.org/"), Bundler::URI("https://rubygems.org/"),
@ -212,22 +212,22 @@ RSpec.describe Bundler::SourceList do
describe "#path_sources" do describe "#path_sources" do
it "returns an empty array when no path sources have been added" do it "returns an empty array when no path sources have been added" do
source_list.add_rubygems_remote("https://rubygems.org") source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_git_source("uri" => "git://host/path.git") source_list.add_git_source("uri" => "git://host/path.git")
expect(source_list.path_sources).to be_empty expect(source_list.path_sources).to be_empty
end end
it "returns path sources in the reverse order that they were added" do it "returns path sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git") source_list.add_git_source("uri" => "git://third-git.org/path.git")
source_list.add_rubygems_remote("https://fifth-rubygems.org") source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem") source_list.add_path_source("path" => "/third/path/to/gem")
source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem") source_list.add_path_source("path" => "/second/path/to/gem")
source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git") source_list.add_git_source("uri" => "git://second-git.org/path.git")
source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem") source_list.add_path_source("path" => "/first/path/to/gem")
source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git") source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.path_sources).to eq [ expect(source_list.path_sources).to eq [
@ -240,7 +240,7 @@ RSpec.describe Bundler::SourceList do
describe "#git_sources" do describe "#git_sources" do
it "returns an empty array when no git sources have been added" do it "returns an empty array when no git sources have been added" do
source_list.add_rubygems_remote("https://rubygems.org") source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem") source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.git_sources).to be_empty expect(source_list.git_sources).to be_empty
@ -248,15 +248,15 @@ RSpec.describe Bundler::SourceList do
it "returns git sources in the reverse order that they were added" do it "returns git sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git") source_list.add_git_source("uri" => "git://third-git.org/path.git")
source_list.add_rubygems_remote("https://fifth-rubygems.org") source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem") source_list.add_path_source("path" => "/third/path/to/gem")
source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem") source_list.add_path_source("path" => "/second/path/to/gem")
source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git") source_list.add_git_source("uri" => "git://second-git.org/path.git")
source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem") source_list.add_path_source("path" => "/first/path/to/gem")
source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git") source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.git_sources).to eq [ expect(source_list.git_sources).to eq [
@ -269,7 +269,7 @@ RSpec.describe Bundler::SourceList do
describe "#plugin_sources" do describe "#plugin_sources" do
it "returns an empty array when no plugin sources have been added" do it "returns an empty array when no plugin sources have been added" do
source_list.add_rubygems_remote("https://rubygems.org") source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem") source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.plugin_sources).to be_empty expect(source_list.plugin_sources).to be_empty
@ -279,13 +279,13 @@ RSpec.describe Bundler::SourceList do
source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git") source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git")
source_list.add_git_source("https://new-git.org") source_list.add_git_source("https://new-git.org")
source_list.add_path_source("path" => "/third/path/to/gem") source_list.add_path_source("path" => "/third/path/to/gem")
source_list.add_rubygems_remote("https://fourth-rubygems.org") source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem") source_list.add_path_source("path" => "/second/path/to/gem")
source_list.add_rubygems_remote("https://third-rubygems.org") source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git") source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git")
source_list.add_rubygems_remote("https://second-rubygems.org") source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem") source_list.add_path_source("path" => "/first/path/to/gem")
source_list.add_rubygems_remote("https://first-rubygems.org") source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git") source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git")
expect(source_list.plugin_sources).to eq [ expect(source_list.plugin_sources).to eq [
@ -339,7 +339,7 @@ RSpec.describe Bundler::SourceList do
describe "#get" do describe "#get" do
context "when it includes an equal source" do context "when it includes an equal source" do
let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) } let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) }
before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") } before { @equal_source = source_list.add_global_rubygems_remote("https://rubygems.org") }
it "returns the equal source" do it "returns the equal source" do
expect(source_list.get(rubygems_source)).to be @equal_source expect(source_list.get(rubygems_source)).to be @equal_source

View file

@ -32,6 +32,8 @@ RSpec.describe "bundle doctor" do
unwritable_file = double("file") unwritable_file = double("file")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] } allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] }
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with(unwritable_file).and_return(true)
allow(File).to receive(:stat).with(unwritable_file) { stat } allow(File).to receive(:stat).with(unwritable_file) { stat }
allow(stat).to receive(:uid) { Process.uid } allow(stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(unwritable_file) { true } allow(File).to receive(:writable?).with(unwritable_file) { true }
@ -47,7 +49,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true) allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true)
expect { doctor.run }.not_to(raise_error, @stdout.string) expect { doctor.run }.not_to(raise_error, @stdout.string)
expect(@stdout.string).to be_empty expect(@stdout.string).to be_empty
@ -57,7 +58,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false) allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false)
expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string
The following gems are missing OS dependencies: The following gems are missing OS dependencies:
@ -67,12 +67,32 @@ RSpec.describe "bundle doctor" do
end end
end end
context "when home contains broken symlinks" do
before(:each) do
@broken_symlink = double("file")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@broken_symlink] }
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with(@broken_symlink) { false }
end
it "exits with an error if home contains files that are not readable/writable" do
expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
expect(@stdout.string).to include(
"Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
end
context "when home contains files that are not readable/writable" do context "when home contains files that are not readable/writable" do
before(:each) do before(:each) do
@stat = double("stat") @stat = double("stat")
@unwritable_file = double("file") @unwritable_file = double("file")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] } allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] }
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with(@unwritable_file) { true }
allow(File).to receive(:stat).with(@unwritable_file) { @stat } allow(File).to receive(:stat).with(@unwritable_file) { @stat }
end end

View file

@ -241,6 +241,94 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
end end
it "does not go to an older version, even if the version upgrade that could cause another gem to downgrade is activated first" do
build_repo4 do
# countries is processed before country_select by the resolver due to having less spec groups (groups of versions with the same dependencies) (2 vs 3)
build_gem "countries", "2.1.4"
build_gem "countries", "3.1.0"
build_gem "countries", "4.0.0" do |s|
s.add_dependency "sixarm_ruby_unaccent", "~> 1.1"
end
build_gem "country_select", "1.2.0"
build_gem "country_select", "2.1.4" do |s|
s.add_dependency "countries", "~> 2.0"
end
build_gem "country_select", "3.1.1" do |s|
s.add_dependency "countries", "~> 2.0"
end
build_gem "country_select", "5.1.0" do |s|
s.add_dependency "countries", "~> 3.0"
end
build_gem "sixarm_ruby_unaccent", "1.1.0"
end
gemfile <<~G
source "#{file_uri_for(gem_repo4)}"
gem "country_select"
gem "countries"
G
lockfile <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
countries (3.1.0)
country_select (5.1.0)
countries (~> 3.0)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
countries
country_select
BUNDLED WITH
#{Bundler::VERSION}
L
previous_lockfile = lockfile
bundle "lock --update"
expect(lockfile).to eq(previous_lockfile)
end
it "does not downgrade indirect dependencies unnecessarily" do
build_repo4 do
build_gem "a" do |s|
s.add_dependency "b"
s.add_dependency "c"
end
build_gem "b"
build_gem "c"
build_gem "c", "2.0"
end
install_gemfile <<-G, :verbose => true
source "#{file_uri_for(gem_repo4)}"
gem "a"
G
expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
update_repo4 do
build_gem "b", "2.0" do |s|
s.add_dependency "c", "< 2"
end
end
bundle "update", :all => true, :verbose => true
expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
end
it "should still downgrade if forced by the Gemfile" do it "should still downgrade if forced by the Gemfile" do
build_repo4 do build_repo4 do
build_gem "a" build_gem "a"
@ -411,18 +499,7 @@ RSpec.describe "bundle update" do
build_repo2 build_repo2
end end
it "should not update gems not included in the source that happen to have the same name", :bundler => "< 3" do it "should not update gems not included in the source that happen to have the same name" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
bundle "update --source activesupport"
expect(the_bundle).to include_gem "activesupport 3.0"
end
it "should not update gems not included in the source that happen to have the same name", :bundler => "3" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gem "activesupport" gem "activesupport"
@ -433,19 +510,15 @@ RSpec.describe "bundle update" do
expect(the_bundle).not_to include_gem "activesupport 3.0" expect(the_bundle).not_to include_gem "activesupport 3.0"
end end
context "with unlock_source_unlocks_spec set to false" do it "should not update gems not included in the source that happen to have the same name" do
before { bundle "config set unlock_source_unlocks_spec false" } install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
it "should not update gems not included in the source that happen to have the same name" do bundle "update --source activesupport"
install_gemfile <<-G expect(the_bundle).not_to include_gems "activesupport 3.0"
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
bundle "update --source activesupport"
expect(the_bundle).not_to include_gems "activesupport 3.0"
end
end end
end end
@ -465,20 +538,7 @@ RSpec.describe "bundle update" do
G G
end end
it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "fred", "2.0"
build_gem "harry", "2.0" do |s|
s.add_dependency "fred"
end
end
bundle "update --source harry"
expect(the_bundle).to include_gems "harry 2.0"
expect(the_bundle).to include_gems "fred 1.0"
end
it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
update_repo2 do update_repo2 do
build_gem "fred", "2.0" build_gem "fred", "2.0"
build_gem "harry", "2.0" do |s| build_gem "harry", "2.0" do |s|
@ -510,21 +570,7 @@ RSpec.describe "bundle update" do
G G
end end
it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "george", "2.0"
build_gem "harry", "2.0" do |s|
s.add_dependency "george"
end
end
bundle "update --source harry"
expect(the_bundle).to include_gems "harry 2.0"
expect(the_bundle).to include_gems "fred 1.0"
expect(the_bundle).to include_gems "george 1.0"
end
it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
update_repo2 do update_repo2 do
build_gem "george", "2.0" build_gem "george", "2.0"
build_gem "harry", "2.0" do |s| build_gem "harry", "2.0" do |s|
@ -1106,9 +1152,9 @@ RSpec.describe "bundle update conservative" do
gem 'shared_owner_b' gem 'shared_owner_b'
G G
lockfile <<-L lockfile <<~L
GEM GEM
remote: #{file_uri_for(gem_repo4)} remote: #{file_uri_for(gem_repo4)}/
specs: specs:
isolated_dep (2.0.1) isolated_dep (2.0.1)
isolated_owner (1.0.1) isolated_owner (1.0.1)
@ -1120,12 +1166,12 @@ RSpec.describe "bundle update conservative" do
shared_dep (~> 5.0) shared_dep (~> 5.0)
PLATFORMS PLATFORMS
ruby #{specific_local_platform}
DEPENDENCIES DEPENDENCIES
isolated_owner
shared_owner_a shared_owner_a
shared_owner_b shared_owner_b
isolated_owner
BUNDLED WITH BUNDLED WITH
#{Bundler::VERSION} #{Bundler::VERSION}
@ -1147,7 +1193,42 @@ RSpec.describe "bundle update conservative" do
it "should not eagerly unlock with --conservative" do it "should not eagerly unlock with --conservative" do
bundle "update --conservative shared_owner_a isolated_owner" bundle "update --conservative shared_owner_a isolated_owner"
expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1" expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
end
it "should only update direct dependencies when fully updating with --conservative" do
bundle "update --conservative"
expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.2"
end
it "should only change direct dependencies when updating the lockfile with --conservative" do
bundle "lock --update --conservative"
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.2)
isolated_dep (~> 2.0)
shared_dep (5.0.1)
shared_owner_a (3.0.2)
shared_dep (~> 5.0)
shared_owner_b (4.0.2)
shared_dep (~> 5.0)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
isolated_owner
shared_owner_a
shared_owner_b
BUNDLED WITH
#{Bundler::VERSION}
L
end end
it "should match bundle install conservative update behavior when not eagerly unlocking" do it "should match bundle install conservative update behavior when not eagerly unlocking" do

View file

@ -26,6 +26,38 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
end end
end end
context "eval-ed Gemfile points to an internal gemspec and uses a scoped source that duplicates the main Gemfile global source" do
before do
build_repo2 do
build_gem "rails", "6.1.3.2"
build_gem "zip-zip", "0.3"
end
create_file bundled_app("gems/Gemfile"), <<-G
gemspec :path => "\#{__dir__}/gunks"
source "#{file_uri_for(gem_repo2)}" do
gem "zip-zip"
end
G
end
it "installs and finds gems correctly" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails"
eval_gemfile File.join(__dir__, "gems/Gemfile")
G
expect(out).to include("Resolving dependencies")
expect(out).to include("Bundle complete")
expect(the_bundle).to include_gem "rails 6.1.3.2"
end
end
context "eval-ed Gemfile has relative-path gems" do context "eval-ed Gemfile has relative-path gems" do
before do before do
build_lib("a", :path => bundled_app("gems/a")) build_lib("a", :path => bundled_app("gems/a"))

View file

@ -247,7 +247,33 @@ RSpec.describe "bundle install with gems on multiple sources" do
bundle :install, :artifice => "compact_index" bundle :install, :artifice => "compact_index"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: https://gem.repo2") expect(err).to include("Installed from: https://gem.repo2")
expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo1/
remote: https://gem.repo2/
specs:
rack (1.0.0)
GEM
remote: https://gem.repo3/
specs:
depends_on_rack (1.0.1)
rack
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
depends_on_rack!
BUNDLED WITH
#{Bundler::VERSION}
L
previous_lockfile = lockfile
expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
expect(lockfile).to eq(previous_lockfile)
end end
it "fails", :bundler => "3" do it "fails", :bundler => "3" do
@ -945,7 +971,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1) rack (0.9.1)
PLATFORMS PLATFORMS
ruby #{specific_local_platform}
DEPENDENCIES DEPENDENCIES
rack! rack!
@ -1254,6 +1280,25 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(out).to include("Using example 0.1.0") expect(out).to include("Using example 0.1.0")
end end
it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do
gemfile <<-G
source "https://gem.repo1"
source "https://gem.repo4" do
gem "example"
end
G
simulate_bundler_version_when_missing_prerelease_default_gem_activation do
ruby <<~R, :raise_on_error => false
require 'bundler/setup'
R
end
expect(last_command).to be_failure
expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.")
end
context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do
it "succeeds but warns, suggesting a source block" do it "succeeds but warns, suggesting a source block" do
build_repo4 do build_repo4 do
@ -1310,4 +1355,74 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(the_bundle).not_to be_locked expect(the_bundle).not_to be_locked
end end
end end
context "when upgrading a lockfile suffering from dependency confusion" do
before do
build_repo4 do
build_gem "mime-types", "3.0.0"
end
build_repo2 do
build_gem "capybara", "2.5.0" do |s|
s.add_dependency "mime-types", ">= 1.16"
end
build_gem "mime-types", "3.3.1"
end
gemfile <<~G
source "https://gem.repo2"
gem "capybara", "~> 2.5.0"
source "https://gem.repo4" do
gem "mime-types", "~> 3.0"
end
G
lockfile <<-L
GEM
remote: https://gem.repo2/
remote: https://gem.repo4/
specs:
capybara (2.5.0)
mime-types (>= 1.16)
mime-types (3.3.1)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
capybara (~> 2.5.0)
mime-types (~> 3.0)!
L
end
it "upgrades the lockfile correctly" do
bundle "lock --update", :artifice => "compact_index"
expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo2/
specs:
capybara (2.5.0)
mime-types (>= 1.16)
GEM
remote: https://gem.repo4/
specs:
mime-types (3.0.0)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
capybara (~> 2.5.0)
mime-types (~> 3.0)!
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
end end

View file

@ -399,7 +399,7 @@ The checksum of /versions does not match the checksum provided by the server! So
api_request_limit = low_api_request_limit_for(gem_repo2) api_request_limit = low_api_request_limit_for(gem_repo2)
install_gemfile <<-G, :artifice => "compact_index_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) install_gemfile <<-G, :artifice => "compact_index_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}" source "#{source_uri}"
source "#{source_uri}/extra" do source "#{source_uri}/extra" do
gem "back_deps" gem "back_deps"
@ -421,7 +421,7 @@ The checksum of /versions does not match the checksum provided by the server! So
api_request_limit = low_api_request_limit_for(gem_repo4) api_request_limit = low_api_request_limit_for(gem_repo4)
install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}" source "#{source_uri}"
source "#{source_uri}/extra" do source "#{source_uri}/extra" do
gem "back_deps" gem "back_deps"

View file

@ -371,7 +371,7 @@ RSpec.describe "gemcutter's dependency API" do
api_request_limit = low_api_request_limit_for(gem_repo2) api_request_limit = low_api_request_limit_for(gem_repo2)
install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}" source "#{source_uri}"
source "#{source_uri}/extra" source "#{source_uri}/extra"
gem "back_deps" gem "back_deps"
@ -392,7 +392,7 @@ RSpec.describe "gemcutter's dependency API" do
api_request_limit = low_api_request_limit_for(gem_repo2) api_request_limit = low_api_request_limit_for(gem_repo2)
install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation) install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}" source "#{source_uri}"
source "#{source_uri}/extra" do source "#{source_uri}/extra" do
gem "back_deps" gem "back_deps"

View file

@ -181,8 +181,11 @@ RSpec.describe "global gem caching" do
bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2 bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2
# activesupport is installed and both are in the global cache # activesupport is installed and both are in the global cache
expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2 simulate_bundler_version_when_missing_prerelease_default_gem_activation do
expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2 expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2
end
expect(source_global_cache("rack-1.0.0.gem")).to exist expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist expect(source_global_cache("activesupport-2.3.5.gem")).to exist
end end

View file

@ -1178,83 +1178,6 @@ RSpec.describe "the lockfile format" do
G G
end end
# Some versions of the Bundler 1.1 RC series introduced corrupted
# lockfiles. There were two major problems:
#
# * multiple copies of the same GIT section appeared in the lockfile
# * when this happened, those sections got multiple copies of gems
# in those sections.
it "fixes corrupted lockfiles" do
build_git "omg", :path => lib_path("omg")
revision = revision_for(lib_path("omg"))
gemfile <<-G
source "#{file_uri_for(gem_repo2)}/"
gem "omg", :git => "#{lib_path("omg")}", :branch => 'master'
G
bundle "config set --local path vendor"
bundle :install
expect(the_bundle).to include_gems "omg 1.0"
# Create a Gemfile.lock that has duplicate GIT sections
lockfile <<-L
GIT
remote: #{lib_path("omg")}
revision: #{revision}
branch: master
specs:
omg (1.0)
GIT
remote: #{lib_path("omg")}
revision: #{revision}
branch: master
specs:
omg (1.0)
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
omg!
BUNDLED WITH
#{Bundler::VERSION}
L
FileUtils.rm_rf(bundled_app("vendor"))
bundle "install"
expect(the_bundle).to include_gems "omg 1.0"
# Confirm that duplicate specs do not appear
lockfile_should_be(<<-L)
GIT
remote: #{lib_path("omg")}
revision: #{revision}
branch: master
specs:
omg (1.0)
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
omg!
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "raises a helpful error message when the lockfile is missing deps" do it "raises a helpful error message when the lockfile is missing deps" do
lockfile <<-L lockfile <<-L
GEM GEM
@ -1326,7 +1249,10 @@ RSpec.describe "the lockfile format" do
expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) }
expect(File.read(bundled_app_lock)).to match("\r\n") expect(File.read(bundled_app_lock)).to match("\r\n")
expect(the_bundle).to include_gems "rack 1.2"
simulate_bundler_version_when_missing_prerelease_default_gem_activation do
expect(the_bundle).to include_gems "rack 1.2"
end
end end
end end

View file

@ -211,133 +211,6 @@ RSpec.describe "real world edgecases", :realworld => true do
expect(err).to be_empty expect(err).to be_empty
end end
it "checks out git repos when the lockfile is corrupted" do
gemfile <<-G
source "https://rubygems.org"
git_source(:github) {|repo| "https://github.com/\#{repo}.git" }
gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
G
lockfile <<-L
GIT
remote: https://github.com/carlhuda/rails-bundler-test.git
revision: 369e28a87419565f1940815219ea9200474589d4
branch: master
specs:
actionpack (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
activerecord (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activesupport (3.2.2)
i18n (~> 0.6)
multi_json (~> 1.0)
GIT
remote: https://github.com/carlhuda/rails-bundler-test.git
revision: 369e28a87419565f1940815219ea9200474589d4
branch: master
specs:
actionpack (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
activerecord (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activesupport (3.2.2)
i18n (~> 0.6)
multi_json (~> 1.0)
GIT
remote: https://github.com/carlhuda/rails-bundler-test.git
revision: 369e28a87419565f1940815219ea9200474589d4
branch: master
specs:
actionpack (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.2)
activesupport (= 3.2.2)
builder (~> 3.0.0)
activerecord (3.2.2)
activemodel (= 3.2.2)
activesupport (= 3.2.2)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activesupport (3.2.2)
i18n (~> 0.6)
multi_json (~> 1.0)
GEM
remote: https://rubygems.org/
specs:
arel (3.0.2)
builder (3.0.0)
erubis (2.7.0)
hike (1.2.1)
i18n (0.6.0)
journey (1.0.3)
multi_json (1.1.0)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
rack-test (0.6.1)
rack (>= 1.0)
sprockets (2.1.2)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
tilt (1.3.3)
tzinfo (0.3.32)
PLATFORMS
ruby
DEPENDENCIES
actionpack!
activerecord!
activesupport!
L
bundle :lock
expect(err).to be_empty
end
it "outputs a helpful error message when gems have invalid gemspecs" do it "outputs a helpful error message when gems have invalid gemspecs" do
install_gemfile <<-G, :standalone => true, :raise_on_error => false install_gemfile <<-G, :standalone => true, :raise_on_error => false
source 'https://rubygems.org' source 'https://rubygems.org'
@ -349,14 +222,14 @@ RSpec.describe "real world edgecases", :realworld => true do
end end
it "doesn't hang on big gemfile" do it "doesn't hang on big gemfile" do
skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G gemfile <<~G
# frozen_string_literal: true # frozen_string_literal: true
source "https://rubygems.org" source "https://rubygems.org"
ruby "2.7.2" ruby "2.7.3"
gem "rails" gem "rails"
gem "pg", ">= 0.18", "< 2.0" gem "pg", ">= 0.18", "< 2.0"
@ -461,7 +334,7 @@ RSpec.describe "real world edgecases", :realworld => true do
end end
it "doesn't hang on tricky gemfile" do it "doesn't hang on tricky gemfile" do
skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G gemfile <<~G
source 'https://rubygems.org' source 'https://rubygems.org'
@ -487,7 +360,7 @@ RSpec.describe "real world edgecases", :realworld => true do
end end
it "doesn't hang on nix gemfile" do it "doesn't hang on nix gemfile" do
skip "Only for ruby 3.0.0" if RUBY_VERSION != "3.0.0" skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/
gemfile <<~G gemfile <<~G
source "https://rubygems.org" do source "https://rubygems.org" do

View file

@ -4,17 +4,19 @@ require "spec_helper"
RSpec.describe "bundle install with complex dependencies", :realworld => true do RSpec.describe "bundle install with complex dependencies", :realworld => true do
it "resolves quickly" do it "resolves quickly" do
start_time = Time.now gemfile <<-G
install_gemfile <<-G
source 'https://rubygems.org' source 'https://rubygems.org'
gem "actionmailer" gem "actionmailer"
gem "mongoid", ">= 0.10.2" gem "mongoid", ">= 0.10.2"
G G
start_time = Time.now
bundle "lock"
duration = Time.now - start_time duration = Time.now - start_time
expect(duration.to_f).to be < 120 # seconds expect(duration.to_f).to be < 12 # seconds
end end
end end

View file

@ -13,6 +13,7 @@ require "bundler"
require "rspec/core" require "rspec/core"
require "rspec/expectations" require "rspec/expectations"
require "rspec/mocks" require "rspec/mocks"
require "rspec/support/differ"
require_relative "support/builders" require_relative "support/builders"
require_relative "support/build_metadata" require_relative "support/build_metadata"

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"]
require_relative "path"
require "bundler/source"
require "bundler/source/rubygems"
module Bundler
class Source
class Rubygems < Source
remove_const :API_REQUEST_LIMIT
API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i
end
end
end
end

View file

@ -35,28 +35,3 @@ module Gem
end end
end end
end end
if ENV["BUNDLER_SPEC_WINDOWS"] == "true"
require_relative "path"
require "bundler/constants"
module Bundler
remove_const :WINDOWS if defined?(WINDOWS)
WINDOWS = true
end
end
if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"]
require_relative "path"
require "bundler/source"
require "bundler/source/rubygems"
module Bundler
class Source
class Rubygems < Source
remove_const :API_REQUEST_LIMIT
API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i
end
end
end
end

View file

@ -455,20 +455,15 @@ module Spec
end end
def simulate_windows(platform = mswin) def simulate_windows(platform = mswin)
old = ENV["BUNDLER_SPEC_WINDOWS"]
ENV["BUNDLER_SPEC_WINDOWS"] = "true"
simulate_platform platform do simulate_platform platform do
simulate_bundler_version_when_missing_prerelease_default_gem_activation do simulate_bundler_version_when_missing_prerelease_default_gem_activation do
yield yield
end end
end end
ensure
ENV["BUNDLER_SPEC_WINDOWS"] = old
end end
# workaround for missing https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1
def simulate_bundler_version_when_missing_prerelease_default_gem_activation def simulate_bundler_version_when_missing_prerelease_default_gem_activation
return yield unless Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") return yield unless rubygems_version_failing_to_activate_bundler_prereleases
old = ENV["BUNDLER_VERSION"] old = ENV["BUNDLER_VERSION"]
ENV["BUNDLER_VERSION"] = Bundler::VERSION ENV["BUNDLER_VERSION"] = Bundler::VERSION
@ -477,15 +472,20 @@ module Spec
ENV["BUNDLER_VERSION"] = old ENV["BUNDLER_VERSION"] = old
end end
# workaround for missing https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1
def env_for_missing_prerelease_default_gem_activation def env_for_missing_prerelease_default_gem_activation
if Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") if rubygems_version_failing_to_activate_bundler_prereleases
{ "BUNDLER_VERSION" => Bundler::VERSION } { "BUNDLER_VERSION" => Bundler::VERSION }
else else
{} {}
end end
end end
# versions providing a bundler version finder but not including
# https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1
def rubygems_version_failing_to_activate_bundler_prereleases
Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") && Gem.rubygems_version >= Gem::Version.new("2.7.0")
end
def revision_for(path) def revision_for(path)
sys_exec("git rev-parse HEAD", :dir => path).strip sys_exec("git rev-parse HEAD", :dir => path).strip
end end

View file

@ -118,14 +118,14 @@ module Spec
opts[:raise_on_error] = false opts[:raise_on_error] = false
@errors = names.map do |full_name| @errors = names.map do |full_name|
name, version, platform = full_name.split(/\s+/) name, version, platform = full_name.split(/\s+/)
require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/") require_path = name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name) version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
source_const = "#{Spec::Builders.constantize(name)}_SOURCE" source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
ruby <<~R, opts ruby <<~R, opts
require '#{lib_dir}/bundler' require 'bundler'
Bundler.setup(#{groups}) Bundler.setup(#{groups})
require '#{require_path}.rb' require '#{require_path}'
actual_version, actual_platform = #{version_const}.split(/\s+/, 2) actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}') unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
puts actual_version puts actual_version
@ -170,7 +170,7 @@ module Spec
name, version = name.split(/\s+/, 2) name, version = name.split(/\s+/, 2)
ruby <<-R, opts ruby <<-R, opts
begin begin
require '#{lib_dir}/bundler' require 'bundler'
Bundler.setup(#{groups}) Bundler.setup(#{groups})
rescue Bundler::GemNotFound, Bundler::GitError rescue Bundler::GemNotFound, Bundler::GitError
exit 0 exit 0

View file

@ -67,6 +67,10 @@ module Spec
@spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec") @spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec")
end end
def api_request_limit_hack_file
spec_dir.join("support/api_request_limit_hax.rb")
end
def man_dir def man_dir
@man_dir ||= lib_dir.join("bundler/man") @man_dir ||= lib_dir.join("bundler/man")
end end

View file

@ -48,6 +48,8 @@ class TestGemExtRakeBuilder < Gem::TestCase
end end
def test_class_no_openssl_override def test_class_no_openssl_override
pend 'openssl is missing' unless Gem::HAVE_OPENSSL
create_temp_mkrf_file('task :default') create_temp_mkrf_file('task :default')
rake = util_spec 'rake' do |s| rake = util_spec 'rake' do |s|

View file

@ -14,6 +14,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
Gem.configuration.disable_default_gem_server = nil Gem.configuration.disable_default_gem_server = nil
ENV['RUBYGEMS_HOST'] = nil ENV['RUBYGEMS_HOST'] = nil
ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil Gem.configuration.rubygems_api_key = nil
@cmd = Gem::Command.new '', 'summary' @cmd = Gem::Command.new '', 'summary'
@ -22,6 +23,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
def teardown def teardown
ENV['RUBYGEMS_HOST'] = nil ENV['RUBYGEMS_HOST'] = nil
ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil Gem.configuration.rubygems_api_key = nil
credential_teardown credential_teardown
@ -186,6 +188,16 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert_match %r{Access Denied.}, @sign_in_ui.output assert_match %r{Access Denied.}, @sign_in_ui.output
end end
def test_signin_with_env_otp_code
ENV['GEM_HOST_OTP_CODE'] = '111111'
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
util_sign_in [api_key, 200, 'OK']
assert_match 'Signed in with API key:', @sign_in_ui.output
assert_equal '111111', @fetcher.last_request['OTP']
end
def test_sign_in_with_correct_otp_code def test_sign_in_with_correct_otp_code
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."

View file

@ -5,7 +5,7 @@ GEM
diff-lcs (1.4.4) diff-lcs (1.4.4)
minitest (5.14.4) minitest (5.14.4)
parallel (1.19.2) parallel (1.19.2)
parser (3.0.0.0) parser (3.0.1.0)
ast (~> 2.4.1) ast (~> 2.4.1)
power_assert (2.0.0) power_assert (2.0.0)
rainbow (3.0.0) rainbow (3.0.0)
@ -56,4 +56,4 @@ DEPENDENCIES
test-unit test-unit
BUNDLED WITH BUNDLED WITH
2.2.21 2.2.22

View file

@ -40,4 +40,4 @@ DEPENDENCIES
webrick (= 1.7.0) webrick (= 1.7.0)
BUNDLED WITH BUNDLED WITH
2.2.21 2.2.22