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

Sync bundler & rubygems

This commit is contained in:
David Rodríguez 2021-04-21 13:54:29 +02:00 committed by Hiroshi SHIBATA
parent 15160e9b4f
commit 5b0abba931
Notes: git 2021-05-11 11:30:05 +09:00
60 changed files with 1041 additions and 266 deletions

View file

@ -34,9 +34,10 @@ Gem::Specification.new do |s|
s.required_ruby_version = ">= 2.3.0" s.required_ruby_version = ">= 2.3.0"
s.required_rubygems_version = ">= 2.5.2" s.required_rubygems_version = ">= 2.5.2"
s.files = (Dir.glob("lib/bundler/**/*", File::FNM_DOTMATCH) + Dir.glob("libexec/bundle*")).reject {|f| File.directory?(f) } s.files = Dir.glob("lib/bundler{.rb,/**/*}", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
s.files += ["lib/bundler.rb"] # include the gemspec itself because warbler breaks w/o it
s.files += %w[lib/bundler/bundler.gemspec]
s.bindir = "libexec" s.bindir = "libexec"
s.executables = %w[bundle bundler] s.executables = %w[bundle bundler]

View file

@ -510,8 +510,8 @@ module Bundler
By default, setting a configuration value sets it for all projects By default, setting a configuration value sets it for all projects
on the machine. on the machine.
If a global setting is superceded by local configuration, this command If a global setting is superseded by local configuration, this command
will show the current value, as well as any superceded values and will show the current value, as well as any superseded values and
where they were specified. where they were specified.
D D
require_relative "cli/config" require_relative "cli/config"

View file

@ -94,6 +94,8 @@ module Bundler
end end
def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems) def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems)
return unless locked_gems
locked_names = locked_gems.specs.map(&:name).uniq locked_names = locked_gems.specs.map(&:name).uniq
names.-(locked_names).each do |g| names.-(locked_names).each do |g|
raise GemNotFound, gem_not_found_message(g, locked_names) raise GemNotFound, gem_not_found_message(g, locked_names)

View file

@ -50,16 +50,20 @@ module Bundler
content = response.body content = response.body
SharedHelpers.filesystem_access(local_temp_path) do etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
correct_response = SharedHelpers.filesystem_access(local_temp_path) do
if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero? if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) } local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
etag_for(local_temp_path) == etag
else else
local_temp_path.open("wb") {|f| f << content } local_temp_path.open("wb") {|f| f << content }
etag.length.zero? || etag_for(local_temp_path) == etag
end end
end end
etag = (response["ETag"] || "").gsub(%r{\AW/}, "") if correct_response
if etag.length.zero? || etag_for(local_temp_path) == etag
SharedHelpers.filesystem_access(local_path) do SharedHelpers.filesystem_access(local_path) do
FileUtils.mv(local_temp_path, local_path) FileUtils.mv(local_temp_path, local_path)
end end

View file

@ -20,6 +20,7 @@ module Bundler
2.5 2.5
2.6 2.6
2.7 2.7
3.0
].freeze ].freeze
KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze

View file

@ -166,16 +166,14 @@ module Bundler
end end
def resolve_with_cache! def resolve_with_cache!
raise "Specs already loaded" if @specs
sources.cached! sources.cached!
specs resolve
end end
def resolve_remotely! def resolve_remotely!
return if @specs
@remote = true @remote = true
sources.remote! sources.remote!
specs resolve
end end
# For given dependency list returns a SpecSet with Gemspec of all the required # For given dependency list returns a SpecSet with Gemspec of all the required

View file

@ -96,15 +96,11 @@ module Bundler
def gem_platforms(valid_platforms) def gem_platforms(valid_platforms)
return valid_platforms if @platforms.empty? return valid_platforms if @platforms.empty?
valid_generic_platforms = valid_platforms.map {|p| [p, GemHelpers.generic(p)] }.to_h valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
@gem_platforms ||= expanded_platforms.compact.uniq
filtered_generic_platforms = valid_generic_platforms.values & @gem_platforms
valid_generic_platforms.select {|_, v| filtered_generic_platforms.include?(v) }.keys
end end
def expanded_platforms def expanded_platforms
@platforms.map {|pl| PLATFORM_MAP[pl] } @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq
end end
def should_include? def should_include?

View file

@ -47,7 +47,8 @@ module Bundler
remote_uri = filter_uri(remote_uri) remote_uri = filter_uri(remote_uri)
super "Authentication is required for #{remote_uri}.\n" \ super "Authentication is required for #{remote_uri}.\n" \
"Please supply credentials for this source. You can do this by running:\n" \ "Please supply credentials for this source. You can do this by running:\n" \
" bundle config set --global #{remote_uri} username:password" "`bundle config set --global #{remote_uri} username:password`\n" \
"or by storing the credentials in the `#{Settings.key_for(remote_uri)}` environment variable"
end end
end end
# This error is raised if HTTP authentication is provided, but incorrect. # This error is raised if HTTP authentication is provided, but incorrect.

View file

@ -68,11 +68,16 @@ module Bundler
compact_index_request :fetch_spec compact_index_request :fetch_spec
def available? def available?
return nil unless SharedHelpers.md5_available? unless SharedHelpers.md5_available?
user_home = Bundler.user_home Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API")
return nil unless user_home.directory? && user_home.writable? return nil
end
if fetch_uri.scheme == "file"
Bundler.ui.debug("Using a local server, bundler won't use the CompactIndex API")
return false
end
# Read info file checksums out of /versions, so we can know if gems are up to date # Read info file checksums out of /versions, so we can know if gems are up to date
fetch_uri.scheme != "file" && compact_index_client.update_and_parse_checksums! compact_index_client.update_and_parse_checksums!
rescue CompactIndexClient::Updater::MisMatchedChecksumError => e rescue CompactIndexClient::Updater::MisMatchedChecksumError => e
Bundler.ui.debug(e.message) Bundler.ui.debug(e.message)
nil nil

View file

@ -14,8 +14,10 @@ module Bundler
def fetch(uri, headers = {}, counter = 0) def fetch(uri, headers = {}, counter = 0)
raise HTTPError, "Too many redirects" if counter >= redirect_limit raise HTTPError, "Too many redirects" if counter >= redirect_limit
filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
response = request(uri, headers) response = request(uri, headers)
Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}") Bundler.ui.debug("HTTP #{response.code} #{response.message} #{filtered_uri}")
case response case response
when Net::HTTPSuccess, Net::HTTPNotModified when Net::HTTPSuccess, Net::HTTPNotModified
@ -40,7 +42,7 @@ module Bundler
raise BadAuthenticationError, uri.host if uri.userinfo raise BadAuthenticationError, uri.host if uri.userinfo
raise AuthenticationRequiredError, uri.host raise AuthenticationRequiredError, uri.host
when Net::HTTPNotFound when Net::HTTPNotFound
raise FallbackError, "Net::HTTPNotFound: #{URICredentialsFilter.credential_filtered_uri(uri)}" raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}"
else else
raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}" raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}"
end end
@ -49,7 +51,9 @@ module Bundler
def request(uri, headers) def request(uri, headers)
validate_uri_scheme!(uri) validate_uri_scheme!(uri)
Bundler.ui.debug "HTTP GET #{uri}" filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
Bundler.ui.debug "HTTP GET #{filtered_uri}"
req = Net::HTTP::Get.new uri.request_uri, headers req = Net::HTTP::Get.new uri.request_uri, headers
if uri.user if uri.user
user = CGI.unescape(uri.user) user = CGI.unescape(uri.user)
@ -69,7 +73,7 @@ module Bundler
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
raise HTTPError, "Network error while fetching #{URICredentialsFilter.credential_filtered_uri(uri)}" \ raise HTTPError, "Network error while fetching #{filtered_uri}" \
" (#{e})" " (#{e})"
end end
end end

View file

@ -199,7 +199,7 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\. Defaults to \fBtrue\fR when \fB\-\-deployment\fR is used\. \fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\. Defaults to \fBtrue\fR when \fB\-\-deployment\fR is used\.
. .
.IP "\(bu" 4 .IP "\(bu" 4
\fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR): Sets a GitHub username or organization to be used in \fBREADME\fR file when you create a new gem via \fBbundle gem\fR command\. It can be overriden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\. \fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR): Sets a GitHub username or organization to be used in \fBREADME\fR file when you create a new gem via \fBbundle gem\fR command\. It can be overridden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\.
. .
.IP "\(bu" 4 .IP "\(bu" 4
\fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\. \fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\.
@ -470,6 +470,23 @@ export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic
. .
.IP "" 0 .IP "" 0
. .
.P
Note that any configured credentials will be redacted by informative commands such as \fBbundle config list\fR or \fBbundle config get\fR, unless you use the \fB\-\-parseable\fR flag\. This is to avoid unintentially leaking credentials when copy\-pasting bundler output\.
.
.P
Also note that to guarantee a sane mapping between valid environment variable names and valid host names, bundler makes the following transformations:
.
.IP "\(bu" 4
Any \fB\-\fR characters in a host name are mapped to a triple dash (\fB___\fR) in the corresponding enviroment variable\.
.
.IP "\(bu" 4
Any \fB\.\fR characters in a host name are mapped to a double dash (\fB__\fR) in the corresponding environment variable\.
.
.IP "" 0
.
.P
This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you\'ll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.
.
.SH "CONFIGURE BUNDLER DIRECTORIES" .SH "CONFIGURE BUNDLER DIRECTORIES"
Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
. .

View file

@ -196,7 +196,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
Defaults to `true` when `--deployment` is used. Defaults to `true` when `--deployment` is used.
* `gem.github_username` (`BUNDLE_GEM__GITHUB_USERNAME`): * `gem.github_username` (`BUNDLE_GEM__GITHUB_USERNAME`):
Sets a GitHub username or organization to be used in `README` file when you Sets a GitHub username or organization to be used in `README` file when you
create a new gem via `bundle gem` command. It can be overriden by passing an create a new gem via `bundle gem` command. It can be overridden by passing an
explicit `--github-username` flag to `bundle gem`. explicit `--github-username` flag to `bundle gem`.
* `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`): * `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`):
Sets the `--key` parameter for `gem push` when using the `rake release` Sets the `--key` parameter for `gem push` when using the `rake release`
@ -376,6 +376,23 @@ where you can use personal OAuth tokens:
export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic
Note that any configured credentials will be redacted by informative commands
such as `bundle config list` or `bundle config get`, unless you use the
`--parseable` flag. This is to avoid unintentially leaking credentials when
copy-pasting bundler output.
Also note that to guarantee a sane mapping between valid environment variable
names and valid host names, bundler makes the following transformations:
* Any `-` characters in a host name are mapped to a triple dash (`___`) in the
corresponding enviroment variable.
* Any `.` characters in a host name are mapped to a double dash (`__`) in the
corresponding environment variable.
This means that if you have a gem server named `my.gem-host.com`, you'll need to
use the `BUNDLE_MY__GEM___HOST__COM` variable to configure credentials for it
through ENV.
## CONFIGURE BUNDLER DIRECTORIES ## CONFIGURE BUNDLER DIRECTORIES

View file

@ -164,7 +164,7 @@ module Bundler
end end
# To be called from Cli class to pass the command and argument to # To be called from Cli class to pass the command and argument to
# approriate plugin class # appropriate plugin class
def exec_command(command, args) def exec_command(command, args)
raise UndefinedCommandError, "Command `#{command}` not found" unless command? command raise UndefinedCommandError, "Command `#{command}` not found" unless command? command
@ -183,7 +183,7 @@ module Bundler
!index.source_plugin(name.to_s).nil? !index.source_plugin(name.to_s).nil?
end end
# @return [Class] that handles the source. The calss includes API::Source # @return [Class] that handles the source. The class includes API::Source
def source(name) def source(name)
raise UnknownSourceError, "Source #{name} not found" unless source? name raise UnknownSourceError, "Source #{name} not found" unless source? name

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) 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)
@ -46,9 +46,6 @@ module Bundler
@gem_version_promoter = gem_version_promoter @gem_version_promoter = gem_version_promoter
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major? @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
@no_aggregate_global_source = @source_requirements[:global].nil? @no_aggregate_global_source = @source_requirements[:global].nil?
@variant_specific_names = []
@generic_names = ["Ruby\0", "RubyGems\0"]
end end
def start(requirements) def start(requirements)
@ -112,24 +109,14 @@ module Bundler
include Molinillo::SpecificationProvider include Molinillo::SpecificationProvider
def dependencies_for(specification) def dependencies_for(specification)
all_dependencies = specification.dependencies_for_activated_platforms specification.dependencies_for_activated_platforms
if @variant_specific_names.include?(specification.name)
@variant_specific_names |= all_dependencies.map(&:name) - @generic_names
else
generic_names, variant_specific_names = specification.partitioned_dependency_names_for_activated_platforms
@variant_specific_names |= variant_specific_names - @generic_names
@generic_names |= generic_names
end
all_dependencies
end end
def search_for(dependency_proxy) def search_for(dependency_proxy)
platform = dependency_proxy.__platform platform = dependency_proxy.__platform
dependency = dependency_proxy.dep dependency = dependency_proxy.dep
name = dependency.name name = dependency.name
search_result = @search_for[dependency_proxy] ||= begin @search_for[dependency_proxy] ||= begin
results = results_for(dependency, @base[name]) results = results_for(dependency, @base[name])
if vertex = @base_dg.vertex_named(name) if vertex = @base_dg.vertex_named(name)
@ -181,22 +168,6 @@ module Bundler
@gem_version_promoter.sort_versions(dependency, spec_groups) @gem_version_promoter.sort_versions(dependency, spec_groups)
end end
end end
unless search_result.empty?
specific_dependency = @variant_specific_names.include?(name)
return search_result unless specific_dependency
search_result.each do |sg|
if @generic_names.include?(name)
@variant_specific_names -= [name]
sg.activate_all_platforms!
else
sg.activate_platform!(platform)
end
end
end
search_result
end end
def index_for(dependency) def index_for(dependency)

View file

@ -21,14 +21,10 @@ module Bundler
@version = exemplary_spec.version @version = exemplary_spec.version
@source = exemplary_spec.source @source = exemplary_spec.source
@all_platforms = relevant_platforms
@activated_platforms = relevant_platforms @activated_platforms = relevant_platforms
@dependencies = Hash.new do |dependencies, platforms| @dependencies = Hash.new do |dependencies, platforms|
dependencies[platforms] = dependencies_for(platforms) dependencies[platforms] = dependencies_for(platforms)
end end
@partitioned_dependency_names = Hash.new do |partitioned_dependency_names, platforms|
partitioned_dependency_names[platforms] = partitioned_dependency_names_for(platforms)
end
@specs = specs @specs = specs
end end
@ -45,14 +41,6 @@ module Bundler
end.flatten.compact.uniq end.flatten.compact.uniq
end end
def activate_platform!(platform)
self.activated_platforms = [platform]
end
def activate_all_platforms!
self.activated_platforms = @all_platforms
end
def to_s def to_s
activated_platforms_string = sorted_activated_platforms.join(", ") activated_platforms_string = sorted_activated_platforms.join(", ")
"#{name} (#{version}) (#{activated_platforms_string})" "#{name} (#{version}) (#{activated_platforms_string})"
@ -62,10 +50,6 @@ module Bundler
@dependencies[activated_platforms] @dependencies[activated_platforms]
end end
def partitioned_dependency_names_for_activated_platforms
@partitioned_dependency_names[activated_platforms]
end
def ==(other) def ==(other)
return unless other.is_a?(SpecGroup) return unless other.is_a?(SpecGroup)
name == other.name && name == other.name &&
@ -100,14 +84,6 @@ module Bundler
end.flatten end.flatten
end end
def partitioned_dependency_names_for(platforms)
return @dependencies[platforms].map(&:name), [] if platforms.size == 1
@dependencies[platforms].partition do |dep_proxy|
@dependencies[platforms].count {|dp| dp.dep == dep_proxy.dep } == platforms.size
end.map {|deps| deps.map(&:name) }
end
def __dependencies(platform) def __dependencies(platform)
dependencies = [] dependencies = []
@specs[platform].first.dependencies.each do |dep| @specs[platform].first.dependencies.each do |dep|

View file

@ -49,7 +49,7 @@ module Bundler
raise e raise e
end end
return true unless name return true unless name
Bundler.ui.info "" unless Bundler.ui.debug? # Add new line incase dots preceded this Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug? Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug?
end end

View file

@ -13,6 +13,7 @@ module Bundler
auto_install auto_install
cache_all cache_all
cache_all_platforms cache_all_platforms
clean
default_install_uses_path default_install_uses_path
deployment deployment
disable_checksum_validation disable_checksum_validation
@ -25,11 +26,14 @@ module Bundler
force_ruby_platform force_ruby_platform
forget_cli_options forget_cli_options
frozen frozen
gem.changelog
gem.coc gem.coc
gem.mit gem.mit
git.allow_insecure
global_gem_cache global_gem_cache
ignore_messages ignore_messages
init_gems_rb init_gems_rb
inline
no_install no_install
no_prune no_prune
path_relative_to_cwd path_relative_to_cwd
@ -59,6 +63,22 @@ module Bundler
without without
].freeze ].freeze
STRING_KEYS = %w[
bin
cache_path
console
gem.ci
gem.github_username
gem.linter
gem.rubocop
gem.test
gemfile
path
shebang
system_bindir
trust-policy
].freeze
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
"BUNDLE_SILENCE_DEPRECATIONS" => false, "BUNDLE_SILENCE_DEPRECATIONS" => false,
"BUNDLE_DISABLE_VERSION_CHECK" => true, "BUNDLE_DISABLE_VERSION_CHECK" => true,
@ -124,8 +144,8 @@ module Bundler
keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys
keys.map do |key| keys.map do |key|
key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase
end end.sort
end end
def local_overrides def local_overrides
@ -171,19 +191,19 @@ module Bundler
locations = [] locations = []
if value = @temporary[key] if value = @temporary[key]
locations << "Set for the current command: #{converted_value(value, exposed_key).inspect}" locations << "Set for the current command: #{printable_value(value, exposed_key).inspect}"
end end
if value = @local_config[key] if value = @local_config[key]
locations << "Set for your local app (#{local_config_file}): #{converted_value(value, exposed_key).inspect}" locations << "Set for your local app (#{local_config_file}): #{printable_value(value, exposed_key).inspect}"
end end
if value = @env_config[key] if value = @env_config[key]
locations << "Set via #{key}: #{converted_value(value, exposed_key).inspect}" locations << "Set via #{key}: #{printable_value(value, exposed_key).inspect}"
end end
if value = @global_config[key] if value = @global_config[key]
locations << "Set for the current user (#{global_config_file}): #{converted_value(value, exposed_key).inspect}" locations << "Set for the current user (#{global_config_file}): #{printable_value(value, exposed_key).inspect}"
end end
return ["You have not configured a value for `#{exposed_key}`"] if locations.empty? return ["You have not configured a value for `#{exposed_key}`"] if locations.empty?
@ -275,9 +295,7 @@ module Bundler
end end
def key_for(key) def key_for(key)
key = Settings.normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key self.class.key_for(key)
key = key.to_s.gsub(".", "__").upcase
"BUNDLE_#{key}"
end end
private private
@ -312,6 +330,10 @@ module Bundler
BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s)) BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
end end
def is_string(name)
STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.")
end
def to_bool(value) def to_bool(value)
case value case value
when nil, /\A(false|f|no|n|0|)\z/i, false when nil, /\A(false|f|no|n|0|)\z/i, false
@ -329,6 +351,14 @@ module Bundler
ARRAY_KEYS.include?(key.to_s) ARRAY_KEYS.include?(key.to_s)
end end
def is_credential(key)
key == "gem.push_key"
end
def is_userinfo(value)
value.include?(":")
end
def to_array(value) def to_array(value)
return [] unless value return [] unless value
value.split(":").map(&:to_sym) value.split(":").map(&:to_sym)
@ -375,6 +405,21 @@ module Bundler
end end
end end
def printable_value(value, key)
converted = converted_value(value, key)
return converted unless converted.is_a?(String)
if is_string(key)
converted
elsif is_credential(key)
"[REDACTED]"
elsif is_userinfo(converted)
converted.gsub(/:.*$/, ":[REDACTED]")
else
converted
end
end
def global_config_file def global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty? if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
Pathname.new(ENV["BUNDLE_CONFIG"]) Pathname.new(ENV["BUNDLE_CONFIG"])
@ -414,6 +459,12 @@ module Bundler
\z \z
/ix.freeze /ix.freeze
def self.key_for(key)
key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
"BUNDLE_#{key}"
end
# TODO: duplicates Rubygems#normalize_uri # TODO: duplicates Rubygems#normalize_uri
# TODO: is this the correct place to validate mirror URIs? # TODO: is this the correct place to validate mirror URIs?
def self.normalize_uri(uri) def self.normalize_uri(uri)

View file

@ -423,11 +423,11 @@ module Bundler
def fetch_names(fetchers, dependency_names, index, override_dupes) def fetch_names(fetchers, dependency_names, index, override_dupes)
fetchers.each do |f| fetchers.each do |f|
if dependency_names if dependency_names
Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug? Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
index.use f.specs_with_retry(dependency_names, self), override_dupes index.use f.specs_with_retry(dependency_names, self), override_dupes
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
else else
Bundler.ui.info "Fetching source index from #{f.uri}" Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
index.use f.specs_with_retry(nil, self), override_dupes index.use f.specs_with_retry(nil, self), override_dupes
end end
end end

View file

@ -78,11 +78,17 @@ module Bundler
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).to_a
deps = materialized.map(&:name).uniq
materialized.group_by(&:source).each do |source, specs|
next unless specs.any?{|s| s.is_a?(LazySpecification) }
source.local!
names = -> { specs.map(&:name).uniq }
source.double_check_for(names)
end
materialized.map! do |s| materialized.map! do |s|
next s unless s.is_a?(LazySpecification) next s unless s.is_a?(LazySpecification)
s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
s.source.local!
spec = s.__materialize__ spec = s.__materialize__
unless spec unless spec
unless missing_specs unless missing_specs
@ -99,12 +105,17 @@ module Bundler
# This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform) # This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
# @return [Array<Gem::Specification>] # @return [Array<Gem::Specification>]
def materialized_for_all_platforms def materialized_for_all_platforms
names = @specs.map(&:name).uniq @specs.group_by(&:source).each do |source, specs|
next unless specs.any?{|s| s.is_a?(LazySpecification) }
source.local!
source.remote!
names = -> { specs.map(&:name).uniq }
source.double_check_for(names)
end
@specs.map do |s| @specs.map do |s|
next s unless s.is_a?(LazySpecification) next s unless s.is_a?(LazySpecification)
s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
s.source.local!
s.source.remote!
spec = s.__materialize__ spec = s.__materialize__
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
spec spec

View file

@ -39,6 +39,6 @@ Gem::Specification.new do |spec|
# Uncomment to register a new dependency of your gem # Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0" # spec.add_dependency "example-gem", "~> 1.0"
# For more information and examples about making a new gem, checkout our # For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html # guide at: https://bundler.io/guides/creating_gem.html
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Bundler::Molinillo module Bundler::Molinillo
# Provides information about specifcations and dependencies to the resolver, # Provides information about specifications and dependencies to the resolver,
# allowing the {Resolver} class to remain generic while still providing power # allowing the {Resolver} class to remain generic while still providing power
# and flexibility. # and flexibility.
# #

View file

@ -252,7 +252,7 @@ class Bundler::Thor
# flag<Regexp|String>:: the regexp or string to be replaced # flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block # replacement<String>:: the replacement, can be also given as a block
# config<Hash>:: give :verbose => false to not log the status, and # config<Hash>:: give :verbose => false to not log the status, and
# :force => true, to force the replacement regardles of runner behavior. # :force => true, to force the replacement regardless of runner behavior.
# #
# ==== Example # ==== Example
# #

View file

@ -626,7 +626,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Try requiring the gem version *or* stdlib version of psych. # Try requiring the gem version *or* stdlib version of psych.
require 'psych' require 'psych'
rescue ::LoadError rescue ::LoadError
# If we can't load psych, thats fine, go on. # If we can't load psych, that's fine, go on.
else else
# If 'yaml' has already been required, then we have to # If 'yaml' has already been required, then we have to
# be sure to switch it over to the newly loaded psych. # be sure to switch it over to the newly loaded psych.

View file

@ -130,7 +130,7 @@ You can use `i` command instead of `install`.
end end
def usage # :nodoc: def usage # :nodoc:
"#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags" "#{program_name} [options] GEMNAME [GEMNAME ...] -- --build-flags"
end end
def check_install_dir # :nodoc: def check_install_dir # :nodoc:

View file

@ -36,7 +36,7 @@ class Gem::Commands::OpenCommand < Gem::Command
end end
def usage # :nodoc: def usage # :nodoc:
"#{program_name} GEMNAME [-e COMMAND]" "#{program_name} [-e COMMAND] GEMNAME"
end end
def get_env_editor def get_env_editor

View file

@ -24,7 +24,7 @@ data you will need to change them immediately and yank your gem.
end end
def usage # :nodoc: def usage # :nodoc:
"#{program_name} GEM -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST]" "#{program_name} -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST] GEM"
end end
def initialize def initialize

View file

@ -60,12 +60,13 @@ module Gem::Deprecate
target = klass ? "#{self}." : "#{self.class}#" target = klass ? "#{self}." : "#{self.class}#"
msg = [ "NOTE: #{target}#{name} is deprecated", msg = [ "NOTE: #{target}#{name} is deprecated",
repl == :none ? " with no replacement" : "; use #{repl} instead", repl == :none ? " with no replacement" : "; use #{repl} instead",
". It will be removed on or after %4d-%02d-01." % [year, month], ". It will be removed on or after %4d-%02d." % [year, month],
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}", "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
] ]
warn "#{msg.join}." unless Gem::Deprecate.skip warn "#{msg.join}." unless Gem::Deprecate.skip
send old, *args, &block send old, *args, &block
end end
ruby2_keywords name if respond_to?(:ruby2_keywords, true)
end end
end end
@ -90,6 +91,7 @@ module Gem::Deprecate
warn "#{msg.join}." unless Gem::Deprecate.skip warn "#{msg.join}." unless Gem::Deprecate.skip
send old, *args, &block send old, *args, &block
end end
ruby2_keywords name if respond_to?(:ruby2_keywords, true)
end end
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Gem::Resolver::Molinillo module Gem::Resolver::Molinillo
# Provides information about specifcations and dependencies to the resolver, # Provides information about specifications and dependencies to the resolver,
# allowing the {Resolver} class to remain generic while still providing power # allowing the {Resolver} class to remain generic while still providing power
# and flexibility. # and flexibility.
# #

View file

@ -38,7 +38,6 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
context "when bundler doesn't have permissions on Dir.tmpdir" do context "when bundler doesn't have permissions on Dir.tmpdir" do
it "Errno::EACCES is raised" do it "Errno::EACCES is raised" do
local_path # create local path before stubbing mktmpdir
allow(Bundler::Dir).to receive(:mktmpdir) { raise Errno::EACCES } allow(Bundler::Dir).to receive(:mktmpdir) { raise Errno::EACCES }
expect do expect do

View file

@ -113,6 +113,20 @@ RSpec.describe Bundler::Env do
end end
end end
context "when there's bundler config with credentials" do
before do
bundle "config set https://localgemserver.test/ user:pass"
end
let(:output) { described_class.report(:print_gemfile => true) }
it "prints the config with redacted values" do
expect(output).to include("https://localgemserver.test")
expect(output).to include("user:[REDACTED]")
expect(output).to_not include("user:pass")
end
end
context "when Gemfile contains a gemspec and print_gemspecs is true" do context "when Gemfile contains a gemspec and print_gemspecs is true" do
let(:gemspec) do let(:gemspec) do
strip_whitespace(<<-GEMSPEC) strip_whitespace(<<-GEMSPEC)

View file

@ -83,6 +83,11 @@ RSpec.describe Bundler::Fetcher::Downloader do
/Authentication is required for www.uri-to-fetch.com/) /Authentication is required for www.uri-to-fetch.com/)
end end
it "should raise a Bundler::Fetcher::AuthenticationRequiredError with advices" do
expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
/`bundle config set --global www\.uri-to-fetch\.com username:password`.*`BUNDLE_WWW__URI___TO___FETCH__COM`/m)
end
context "when the there are credentials provided in the request" do context "when the there are credentials provided in the request" do
let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") } let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") }

View file

@ -28,7 +28,7 @@ RSpec.describe Bundler::Plugin::DSL do
expect(dsl.inferred_plugins).to eq(["bundler-source-news"]) expect(dsl.inferred_plugins).to eq(["bundler-source-news"])
end end
it "registers a source type plugin only once for multiple declataions" do it "registers a source type plugin only once for multiple declarations" do
expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once
dsl.source("some_random_url", :type => "news") {} dsl.source("some_random_url", :type => "news") {}

View file

@ -22,7 +22,7 @@ RSpec.describe Bundler::Plugin::Index do
expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name)) expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name))
end end
it "load_paths is available for retrival" do it "load_paths is available for retrieval" do
expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s]) expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s])
end end

View file

@ -211,14 +211,10 @@ RSpec.describe "bundle cache" do
end end
context "with --all-platforms" do context "with --all-platforms" do
before do
skip "doesn't put gems where it should" if Gem.win_platform?
end
it "puts the gems in vendor/cache even for other rubies" do it "puts the gems in vendor/cache even for other rubies" do
gemfile <<-D gemfile <<-D
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"
gem 'rack', :platforms => :ruby_19 gem 'rack', :platforms => [:ruby_20, :x64_mingw_20]
D D
bundle "cache --all-platforms" bundle "cache --all-platforms"
@ -236,11 +232,11 @@ RSpec.describe "bundle cache" do
bundle "config set --local without wo" bundle "config set --local without wo"
install_gemfile <<-G install_gemfile <<-G
source "file:#{gem_repo1}" source "#{file_uri_for(gem_repo1)}"
gem "rack" gem "rack"
group :wo do group :wo do
gem "weakling" gem "weakling"
gem "uninstallable", :source => "file:#{gem_repo4}" gem "uninstallable", :source => "#{file_uri_for(gem_repo4)}"
end end
G G
@ -255,6 +251,21 @@ RSpec.describe "bundle cache" do
expect(the_bundle).to include_gem "rack 1.0" expect(the_bundle).to include_gem "rack 1.0"
expect(the_bundle).not_to include_gems "weakling", "uninstallable" expect(the_bundle).not_to include_gems "weakling", "uninstallable"
end end
it "does not fail to cache gems in excluded groups when there's a lockfile but gems not previously installed" do
bundle "config set --local without wo"
gemfile <<-G
source "https://my.gem.repo.1"
gem "rack"
group :wo do
gem "weakling"
end
G
bundle :lock, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
bundle :cache, "all-platforms" => true, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
end
end end
context "with frozen configured" do context "with frozen configured" do

View file

@ -199,7 +199,7 @@ RSpec.describe "bundle clean" do
revision = revision_for(git_path) revision = revision_for(git_path)
gemfile <<-G gemfile <<-G
source "file://#{gem_repo1}" source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0" gem "rack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do git "#{git_path}", :ref => "#{revision}" do

View file

@ -408,6 +408,14 @@ E
expect(out).to eq "spec_run=true" expect(out).to eq "spec_run=true"
end end
it "list with credentials" do
bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\"\n\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
expect(out).to eq "gems.myserver.com=user:password\nspec_run=true"
end
it "get" do it "get" do
ENV["BUNDLE_BAR"] = "bar_val" ENV["BUNDLE_BAR"] = "bar_val"

View file

@ -1,24 +1,24 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "bundle outdated" do RSpec.describe "bundle outdated" do
before :each do describe "with no arguments" do
build_repo2 do before do
build_git "foo", :path => lib_path("foo") build_repo2 do
build_git "zebra", :path => lib_path("zebra") build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end
describe "with no arguments" do
it "returns a sorted list of outdated gems" do it "returns a sorted list of outdated gems" do
update_repo2 do update_repo2 do
build_gem "activesupport", "3.0" build_gem "activesupport", "3.0"
@ -102,6 +102,23 @@ RSpec.describe "bundle outdated" do
end end
describe "with --verbose option" do describe "with --verbose option" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end
it "shows the location of the latest version's gemspec if installed" do it "shows the location of the latest version's gemspec if installed" do
bundle "config set clean false" bundle "config set clean false"
@ -134,8 +151,79 @@ RSpec.describe "bundle outdated" do
end end
end end
describe "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do
before do
build_repo2 do
build_gem "dotenv", "2.7.6"
build_gem "oj", "3.11.3"
build_gem "oj", "3.11.5"
build_gem "vcr", "6.0.0"
end
build_repo gem_repo3 do
build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s|
s.add_dependency "oj"
end
end
gemfile <<~G
source "https://gem.repo2"
gem "dotenv"
source "https://gem.repo3" do
gem 'pkg-gem-flowbyte-with-dep'
end
gem "vcr",source: "https://gem.repo2"
G
lockfile <<~L
GEM
remote: https://gem.repo2/
remote: https://gem.repo3/
specs:
dotenv (2.7.6)
oj (3.11.3)
pkg-gem-flowbyte-with-dep (1.0.0)
oj
vcr (6.0.0)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
dotenv
pkg-gem-flowbyte-with-dep!
vcr!
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "works" do
bundle :install, :artifice => :compact_index
bundle :outdated, :artifice => :compact_index, :raise_on_error => false
expected_output = <<~TABLE
Gem Current Latest Requested Groups
oj 3.11.3 3.11.5
TABLE
expect(out).to include(expected_output.strip)
end
end
describe "with --group option" do describe "with --group option" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -201,7 +289,10 @@ RSpec.describe "bundle outdated" do
describe "with --groups option and outdated transitive dependencies" do describe "with --groups option and outdated transitive dependencies" do
before do before do
update_repo2 do build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
build_gem "bar", %w[2.0.0] build_gem "bar", %w[2.0.0]
build_gem "bar_dependant", "7.0" do |s| build_gem "bar_dependant", "7.0" do |s|
@ -234,6 +325,11 @@ RSpec.describe "bundle outdated" do
describe "with --groups option" do describe "with --groups option" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -272,6 +368,24 @@ RSpec.describe "bundle outdated" do
end end
describe "with --local option" do describe "with --local option" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
group :development, :test do
gem 'activesupport', '2.3.5'
gem "duradura", '7.0'
end
G
end
it "uses local cache to return a list of outdated gems" do it "uses local cache to return a list of outdated gems" do
update_repo2 do update_repo2 do
build_gem "activesupport", "2.3.4" build_gem "activesupport", "2.3.4"
@ -305,10 +419,23 @@ RSpec.describe "bundle outdated" do
shared_examples_for "a minimal output is desired" do shared_examples_for "a minimal output is desired" do
context "and gems are outdated" do context "and gems are outdated" do
before do before do
update_repo2 do build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
build_gem "activesupport", "3.0" build_gem "activesupport", "3.0"
build_gem "weakling", "0.2" build_gem "weakling", "0.2"
end end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end end
it "outputs a sorted list of outdated gems with a more minimal format" do it "outputs a sorted list of outdated gems with a more minimal format" do
@ -341,6 +468,21 @@ RSpec.describe "bundle outdated" do
describe "with specified gems" do describe "with specified gems" do
it "returns list of outdated gems" do it "returns list of outdated gems" do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "3.0" build_gem "activesupport", "3.0"
update_git "foo", :path => lib_path("foo") update_git "foo", :path => lib_path("foo")
@ -358,6 +500,23 @@ RSpec.describe "bundle outdated" do
end end
describe "pre-release gems" do describe "pre-release gems" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end
context "without the --pre option" do context "without the --pre option" do
it "ignores pre-release versions" do it "ignores pre-release versions" do
update_repo2 do update_repo2 do
@ -413,6 +572,23 @@ RSpec.describe "bundle outdated" do
filter_strict_option = Bundler.feature_flag.bundler_2_mode? ? :"filter-strict" : :strict filter_strict_option = Bundler.feature_flag.bundler_2_mode? ? :"filter-strict" : :strict
describe "with --#{filter_strict_option} option" do describe "with --#{filter_strict_option} option" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end
it "only reports gems that have a newer version that matches the specified dependency version requirements" do it "only reports gems that have a newer version that matches the specified dependency version requirements" do
update_repo2 do update_repo2 do
build_gem "activesupport", "3.0" build_gem "activesupport", "3.0"
@ -521,6 +697,23 @@ RSpec.describe "bundle outdated" do
end end
describe "with invalid gem name" do describe "with invalid gem name" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
end
it "returns could not find gem name" do it "returns could not find gem name" do
bundle "outdated invalid_gem_name", :raise_on_error => false bundle "outdated invalid_gem_name", :raise_on_error => false
expect(err).to include("Could not find gem 'invalid_gem_name'.") expect(err).to include("Could not find gem 'invalid_gem_name'.")
@ -546,12 +739,16 @@ RSpec.describe "bundle outdated" do
context "after bundle install --deployment", :bundler => "< 3" do context "after bundle install --deployment", :bundler => "< 3" do
before do before do
install_gemfile <<-G, :deployment => true, :raise_on_error => false build_repo2
gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gem "rack" gem "rack"
gem "foo" gem "foo"
G G
bundle :lock
bundle :install, :deployment => true
end end
it "outputs a helpful message about being in deployment mode" do it "outputs a helpful message about being in deployment mode" do
@ -568,6 +765,11 @@ RSpec.describe "bundle outdated" do
context "after bundle config set --local deployment true" do context "after bundle config set --local deployment true" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -591,6 +793,8 @@ RSpec.describe "bundle outdated" do
context "update available for a gem on a different platform" do context "update available for a gem on a different platform" do
before do before do
build_repo2
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gem "laduradura", '= 5.15.2' gem "laduradura", '= 5.15.2'
@ -604,6 +808,10 @@ RSpec.describe "bundle outdated" do
end end
context "update available for a gem on the same platform while multiple platforms used for gem" do context "update available for a gem on the same platform while multiple platforms used for gem" do
before do
build_repo2
end
it "reports that updates are available if the Ruby platform is used" do it "reports that updates are available if the Ruby platform is used" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -643,6 +851,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "major version updates are detected" do shared_examples_for "major version updates are detected" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "3.3.5" build_gem "activesupport", "3.3.5"
build_gem "weakling", "0.8.0" build_gem "weakling", "0.8.0"
@ -654,6 +877,21 @@ RSpec.describe "bundle outdated" do
context "when on a new machine" do context "when on a new machine" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
simulate_new_machine simulate_new_machine
update_git "foo", :path => lib_path("foo") update_git "foo", :path => lib_path("foo")
@ -669,6 +907,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "minor version updates are detected" do shared_examples_for "minor version updates are detected" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "2.7.5" build_gem "activesupport", "2.7.5"
build_gem "weakling", "2.0.1" build_gem "weakling", "2.0.1"
@ -680,6 +933,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version updates are detected" do shared_examples_for "patch version updates are detected" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "2.3.7" build_gem "activesupport", "2.3.7"
build_gem "weakling", "0.3.1" build_gem "weakling", "0.3.1"
@ -698,6 +966,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "major version is ignored" do shared_examples_for "major version is ignored" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "3.3.5" build_gem "activesupport", "3.3.5"
build_gem "weakling", "1.0.1" build_gem "weakling", "1.0.1"
@ -709,6 +992,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "minor version is ignored" do shared_examples_for "minor version is ignored" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "2.4.5" build_gem "activesupport", "2.4.5"
build_gem "weakling", "0.3.1" build_gem "weakling", "0.3.1"
@ -720,6 +1018,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version is ignored" do shared_examples_for "patch version is ignored" do
before do before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
build_git "zebra", :path => lib_path("zebra")
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
gem "weakling", "~> 0.0.1"
gem "duradura", '7.0'
gem "terranova", '8'
G
update_repo2 do update_repo2 do
build_gem "activesupport", "2.3.6" build_gem "activesupport", "2.3.6"
build_gem "weakling", "0.0.4" build_gem "weakling", "0.0.4"

View file

@ -203,6 +203,16 @@ RSpec.describe "bundle pristine", :ruby_repo do
end end
end end
context "when BUNDLE_GEMFILE doesn't exist" do
before do
bundle "pristine", :env => { "BUNDLE_GEMFILE" => "does/not/exist" }, :raise_on_error => false
end
it "shows a meaningful error" do
expect(err).to eq("#{bundled_app("does/not/exist")} not found")
end
end
def find_spec(name) def find_spec(name)
without_env_side_effects do without_env_side_effects do
Bundler.definition.specs[name].first Bundler.definition.specs[name].first

View file

@ -229,7 +229,7 @@ RSpec.describe "bundle remove" do
end end
end end
context "when the gem is present in mutiple groups" do context "when the gem is present in multiple groups" do
it "removes all empty blocks" do it "removes all empty blocks" do
gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"
@ -333,7 +333,7 @@ RSpec.describe "bundle remove" do
end end
describe "arbitrary gemfile" do describe "arbitrary gemfile" do
context "when mutiple gems are present in same line" do context "when multiple gems are present in same line" do
it "shows warning for gems not removed" do it "shows warning for gems not removed" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"

View file

@ -1,18 +1,18 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe "bundle update" do RSpec.describe "bundle update" do
before :each do describe "with no arguments" do
build_repo2 before do
build_repo2
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gem "activesupport" gem "activesupport"
gem "rack-obama" gem "rack-obama"
gem "platform_specific" gem "platform_specific"
G G
end end
describe "with no arguments", :bundler => "< 3" do
it "updates the entire bundle" do it "updates the entire bundle" do
update_repo2 do update_repo2 do
build_gem "rack", "1.2" do |s| build_gem "rack", "1.2" do |s|
@ -39,7 +39,18 @@ RSpec.describe "bundle update" do
end end
end end
describe "with --all", :bundler => "3" do describe "with --all" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "updates the entire bundle" do it "updates the entire bundle" do
update_repo2 do update_repo2 do
build_gem "rack", "1.2" do |s| build_gem "rack", "1.2" do |s|
@ -55,6 +66,8 @@ RSpec.describe "bundle update" do
end end
it "doesn't delete the Gemfile.lock file if something goes wrong" do it "doesn't delete the Gemfile.lock file if something goes wrong" do
install_gemfile ""
gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
gem "activesupport" gem "activesupport"
@ -102,6 +115,17 @@ RSpec.describe "bundle update" do
end end
describe "--quiet argument" do describe "--quiet argument" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "hides UI messages" do it "hides UI messages" do
bundle "update --quiet" bundle "update --quiet"
expect(out).not_to include("Bundle updated!") expect(out).not_to include("Bundle updated!")
@ -109,6 +133,17 @@ RSpec.describe "bundle update" do
end end
describe "with a top level dependency" do describe "with a top level dependency" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "unlocks all child dependencies that are unrelated to other locked dependencies" do it "unlocks all child dependencies that are unrelated to other locked dependencies" do
update_repo2 do update_repo2 do
build_gem "rack", "1.2" do |s| build_gem "rack", "1.2" do |s|
@ -124,6 +159,17 @@ RSpec.describe "bundle update" do
end end
describe "with an unknown dependency" do describe "with an unknown dependency" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "should inform the user" do it "should inform the user" do
bundle "update halting-problem-solver", :raise_on_error => false bundle "update halting-problem-solver", :raise_on_error => false
expect(err).to include "Could not find gem 'halting-problem-solver'" expect(err).to include "Could not find gem 'halting-problem-solver'"
@ -135,6 +181,17 @@ RSpec.describe "bundle update" do
end end
describe "with a child dependency" do describe "with a child dependency" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "should update the child dependency" do it "should update the child dependency" do
update_repo2 do update_repo2 do
build_gem "rack", "1.2" do |s| build_gem "rack", "1.2" do |s|
@ -212,6 +269,17 @@ RSpec.describe "bundle update" do
end end
describe "with --local option" do describe "with --local option" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "doesn't hit repo2" do it "doesn't hit repo2" do
FileUtils.rm_rf(gem_repo2) FileUtils.rm_rf(gem_repo2)
@ -221,6 +289,10 @@ RSpec.describe "bundle update" do
end end
describe "with --group option" do describe "with --group option" do
before do
build_repo2
end
it "should update only specified group gems" do it "should update only specified group gems" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -257,7 +329,7 @@ RSpec.describe "bundle update" do
end end
context "when there is a source with the same name as a gem in a group" do context "when there is a source with the same name as a gem in a group" do
before :each do before do
build_git "foo", :path => lib_path("activesupport") build_git "foo", :path => lib_path("activesupport")
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -299,6 +371,17 @@ RSpec.describe "bundle update" do
end end
describe "in a frozen bundle" do describe "in a frozen bundle" do
before do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
gem "platform_specific"
G
end
it "should fail loudly", :bundler => "< 3" do it "should fail loudly", :bundler => "< 3" do
bundle "install --deployment" bundle "install --deployment"
bundle "update", :all => true, :raise_on_error => false bundle "update", :all => true, :raise_on_error => false
@ -324,6 +407,10 @@ RSpec.describe "bundle update" do
end end
describe "with --source option" do describe "with --source option" do
before do
build_repo2
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", :bundler => "< 3" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" source "#{file_uri_for(gem_repo2)}"
@ -449,10 +536,130 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0" expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0"
end end
end end
it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
bundle "update", :all => true
expect(out).to include("Using activesupport 2.3.5")
update_repo2 do
build_gem "activesupport", "3.0"
end
bundle "update", :all => true
expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
end
context "with suppress_install_using_messages set" do
before { bundle "config set suppress_install_using_messages true" }
it "only prints `Using` for versions that have changed" do
build_repo4 do
build_gem "bar"
build_gem "foo"
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "bar"
gem "foo"
G
bundle "update", :all => true
expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
update_repo4 do
build_gem "foo", "2.0"
end
bundle "update", :all => true
out.sub!("Removing foo (1.0)\n", "")
expect(out).to match(/Resolving dependencies\.\.\.\.*\nFetching foo 2\.0 \(was 1\.0\)\nInstalling foo 2\.0 \(was 1\.0\)\nBundle updated/)
end
end
it "shows error message when Gemfile.lock is not preset and gem is specified" do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
bundle "update nonexisting", :raise_on_error => false
expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
expect(exitstatus).to eq(22)
end
context "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do
before do
build_repo2 do
build_gem "dotenv", "2.7.6"
build_gem "oj", "3.11.3"
build_gem "oj", "3.11.5"
build_gem "vcr", "6.0.0"
end
build_repo gem_repo3 do
build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s|
s.add_dependency "oj"
end
end
gemfile <<~G
source "https://gem.repo2"
gem "dotenv"
source "https://gem.repo3" do
gem 'pkg-gem-flowbyte-with-dep'
end
gem "vcr",source: "https://gem.repo2"
G
lockfile <<~L
GEM
remote: https://gem.repo2/
remote: https://gem.repo3/
specs:
dotenv (2.7.6)
oj (3.11.3)
pkg-gem-flowbyte-with-dep (1.0.0)
oj
vcr (6.0.0)
PLATFORMS
#{specific_local_platform}
DEPENDENCIES
dotenv
pkg-gem-flowbyte-with-dep!
vcr!
BUNDLED WITH
#{Bundler::VERSION}
L
end
it "works" do
bundle :install, :artifice => :compact_index
bundle "update oj", :artifice => :compact_index
expect(out).to include("Bundle updated!")
expect(the_bundle).to include_gems "oj 3.11.5"
end
end
end end
RSpec.describe "bundle update in more complicated situations" do RSpec.describe "bundle update in more complicated situations" do
before :each do before do
build_repo2 build_repo2
end end
@ -640,7 +847,7 @@ RSpec.describe "bundle update without a Gemfile.lock" do
end end
RSpec.describe "bundle update when a gem depends on a newer version of bundler" do RSpec.describe "bundle update when a gem depends on a newer version of bundler" do
before(:each) do before do
build_repo2 do build_repo2 do
build_gem "rails", "3.0.1" do |s| build_gem "rails", "3.0.1" do |s|
s.add_dependency "bundler", Bundler::VERSION.succ s.add_dependency "bundler", Bundler::VERSION.succ
@ -663,66 +870,6 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
end end
end end
RSpec.describe "bundle update" do
it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
build_repo2
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
bundle "update", :all => true
expect(out).to include("Using activesupport 2.3.5")
update_repo2 do
build_gem "activesupport", "3.0"
end
bundle "update", :all => true
expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
end
context "with suppress_install_using_messages set" do
before { bundle "config set suppress_install_using_messages true" }
it "only prints `Using` for versions that have changed" do
build_repo4 do
build_gem "bar"
build_gem "foo"
end
install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "bar"
gem "foo"
G
bundle "update", :all => true
expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
update_repo4 do
build_gem "foo", "2.0"
end
bundle "update", :all => true
out.sub!("Removing foo (1.0)\n", "")
expect(out).to match(/Resolving dependencies\.\.\.\.*\nFetching foo 2\.0 \(was 1\.0\)\nInstalling foo 2\.0 \(was 1\.0\)\nBundle updated/)
end
end
it "shows error message when Gemfile.lock is not preset and gem is specified" do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
bundle "update nonexisting", :raise_on_error => false
expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
expect(exitstatus).to eq(22)
end
end
RSpec.describe "bundle update --ruby" do RSpec.describe "bundle update --ruby" do
before do before do
install_gemfile <<-G install_gemfile <<-G

View file

@ -567,4 +567,57 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(the_bundle).not_to include_gem "rack" expect(the_bundle).not_to include_gem "rack"
end end
end end
context "with multiple platforms and resolving for more specific platforms" do
before do
build_lib("chef", :path => tmp.join("chef")) do |s|
s.version = "17.1.17"
s.write "chef-universal-mingw32.gemspec", build_spec("chef", "17.1.17", "universal-mingw32") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby
end
end
it "does not remove the platform specific specs from the lockfile when updating" do
build_repo4 do
build_gem "win32-api", "1.5.3" do |s|
s.platform = "universal-mingw32"
end
end
gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gemspec :path => "../chef"
G
initial_lockfile = <<~L
PATH
remote: ../chef
specs:
chef (17.1.17)
chef (17.1.17-universal-mingw32)
win32-api (~> 1.5.3)
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
win32-api (1.5.3-universal-mingw32)
PLATFORMS
ruby
x64-mingw32
x86-mingw32
DEPENDENCIES
chef!
BUNDLED WITH
#{Bundler::VERSION}
L
lockfile initial_lockfile
bundle "update"
expect(lockfile).to eq initial_lockfile
end
end
end end

View file

@ -90,7 +90,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
gem "thin" # comes first to test name sorting gem "thin" # comes first to test name sorting
gem "rack" gem "rack"
end end
gem "rack-obama" # shoud come from repo3! gem "rack-obama" # should come from repo3!
G G
end end
@ -596,7 +596,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
L L
end end
it "it keeps the currrent lockfile format and upgrades the requested gem when running bundle update with an argument, and warns", :bundler => "< 3" do it "it keeps the current lockfile format and upgrades the requested gem when running bundle update with an argument, and warns", :bundler => "< 3" do
bundle "update concurrent-ruby" bundle "update concurrent-ruby"
expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.") expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
@ -921,7 +921,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"
gem "rack" # shoud come from repo1! gem "rack" # should come from repo1!
G G
end end
@ -974,7 +974,10 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "re-resolving" do context "re-resolving" do
context "when there is a mix of sources in the gemfile" do context "when there is a mix of sources in the gemfile" do
before do before do
build_repo3 build_repo gem_repo3 do
build_gem "rack"
end
build_lib "path1" build_lib "path1"
build_lib "path2" build_lib "path2"
build_git "git1" build_git "git1"

View file

@ -614,6 +614,17 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0"
end end
it "passes basic authentication details and strips out creds also in verbose mode" do
gemfile <<-G
source "#{basic_auth_source_uri}"
gem "rack"
G
bundle :install, :verbose => true, :artifice => "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
gemfile <<-G gemfile <<-G
source "#{basic_auth_source_uri}" source "#{basic_auth_source_uri}"
@ -815,6 +826,28 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0"
end end
it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no Etag" do
build_repo4 do
build_gem "rack", "0.9.1"
end
install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem 'rack', '0.9.1'
G
update_repo4 do
build_gem "rack", "1.0.0"
end
install_gemfile <<-G, :artifice => "compact_index_partial_update_no_etag_not_incremental", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem 'rack', '1.0.0'
G
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "performs full update of compact index info cache if range is not satisfiable" do it "performs full update of compact index info cache if range is not satisfiable" do
gemfile <<-G gemfile <<-G
source "#{source_uri}" source "#{source_uri}"

View file

@ -586,6 +586,17 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0"
end end
it "passes basic authentication details and strips out creds also in verbose mode" do
gemfile <<-G
source "#{basic_auth_source_uri}"
gem "rack"
G
bundle :install, :verbose => true, :artifice => "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "strips http basic authentication creds for modern index" do it "strips http basic authentication creds for modern index" do
gemfile <<-G gemfile <<-G
source "#{basic_auth_source_uri}" source "#{basic_auth_source_uri}"
@ -630,6 +641,22 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0"
end end
describe "with host including dashes" do
before do
gemfile <<-G
source "http://local-gemserver.test"
gem "rack"
G
end
it "reads authentication details from a valid ENV variable" do
bundle :install, :artifice => "endpoint_strict_basic_authentication", :env => { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" }
expect(out).to include("Fetching gem metadata from http://local-gemserver.test")
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
describe "with authentication details in bundle config" do describe "with authentication details in bundle config" do
before do before do
gemfile <<-G gemfile <<-G

View file

@ -33,7 +33,7 @@ RSpec.describe "bundle install" do
end end
end end
context "when a dependecy includes a post install message" do context "when a dependency includes a post install message" do
it "should display the post install message" do it "should display the post install message" do
gemfile <<-G gemfile <<-G
source "#{file_uri_for(gem_repo1)}" source "#{file_uri_for(gem_repo1)}"

View file

@ -38,7 +38,11 @@ RSpec.describe "bundle install" do
describe "when prerelease gems are not available" do describe "when prerelease gems are not available" do
it "still works" do it "still works" do
build_repo3 build_repo gem_repo3 do
build_gem "rack"
end
FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
install_gemfile <<-G install_gemfile <<-G
source "#{file_uri_for(gem_repo3)}" source "#{file_uri_for(gem_repo3)}"
gem "rack" gem "rack"

View file

@ -170,9 +170,16 @@ RSpec.describe "The library itself" do
it "documents all used settings" do it "documents all used settings" do
exemptions = %w[ exemptions = %w[
forget_cli_options forget_cli_options
gem.changelog
gem.ci
gem.coc gem.coc
gem.linter
gem.mit gem.mit
gem.rubocop
gem.test
git.allow_insecure
inline inline
trust-policy
use_gem_version_promoter_for_major_updates use_gem_version_promoter_for_major_updates
] ]
@ -182,6 +189,7 @@ RSpec.describe "The library itself" do
Bundler::Settings::BOOL_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::BOOL_KEYS" } Bundler::Settings::BOOL_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::BOOL_KEYS" }
Bundler::Settings::NUMBER_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::NUMBER_KEYS" } Bundler::Settings::NUMBER_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::NUMBER_KEYS" }
Bundler::Settings::ARRAY_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::ARRAY_KEYS" } Bundler::Settings::ARRAY_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::ARRAY_KEYS" }
Bundler::Settings::STRING_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::STRING_KEYS" }
key_pattern = /([a-z\._-]+)/i key_pattern = /([a-z\._-]+)/i
lib_tracked_files.each do |filename| lib_tracked_files.each do |filename|
@ -215,7 +223,7 @@ RSpec.describe "The library itself" do
end end
it "ships the correct set of files" do it "ships the correct set of files" do
git_list = git_ls_files(ruby_core? ? "lib/bundler lib/bundler.rb man/bundle* man/gemfile* libexec/bundle*" : "lib man exe CHANGELOG.md LICENSE.md README.md bundler.gemspec") git_list = git_ls_files(ruby_core? ? "lib/bundler lib/bundler.rb libexec/bundle*" : "lib exe CHANGELOG.md LICENSE.md README.md bundler.gemspec")
gem_list = loaded_gemspec.files gem_list = loaded_gemspec.files

View file

@ -349,14 +349,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"
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 +461,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"
gemfile <<~G gemfile <<~G
source 'https://rubygems.org' source 'https://rubygems.org'
@ -487,7 +487,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"
gemfile <<~G gemfile <<~G
source "https://rubygems.org" do source "https://rubygems.org" do

View file

@ -293,7 +293,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "installs inline gems to the system path regardless" do it "installs inline gems to the system path regardless" do
script <<-RUBY, :env => { "BUNDLE_PATH" => "./vendor/inline" } script <<-RUBY, :env => { "BUNDLE_PATH" => "./vendor/inline" }
gemfile(true) do gemfile(true) do
source "file://#{gem_repo1}" source "#{file_uri_for(gem_repo1)}"
gem "rack" gem "rack"
end end
RUBY RUBY

View file

@ -4,7 +4,6 @@ require "bundler/psyched_yaml"
require "bundler/vendored_fileutils" require "bundler/vendored_fileutils"
require "bundler/vendored_uri" require "bundler/vendored_uri"
require "digest" require "digest"
require "tmpdir"
if File.expand_path(__FILE__) =~ %r{([^\w/\.:\-])} if File.expand_path(__FILE__) =~ %r{([^\w/\.:\-])}
abort "The bundler specs cannot be run from a path that contains special characters (particularly #{$1.inspect})" abort "The bundler specs cannot be run from a path that contains special characters (particularly #{$1.inspect})"
@ -74,6 +73,7 @@ RSpec.configure do |config|
Spec::Rubygems.test_setup Spec::Rubygems.test_setup
ENV["BUNDLE_SPEC_RUN"] = "true" ENV["BUNDLE_SPEC_RUN"] = "true"
ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil
ENV["XDG_CONFIG_HOME"] = nil
ENV["GEMRC"] = nil ENV["GEMRC"] = nil
# Don't wrap output in tests # Don't wrap output in tests
@ -111,16 +111,6 @@ RSpec.configure do |config|
end end
end end
config.around :each do |example|
Dir.mktmpdir("bundler_commands_console") do |dir|
xdg_config_home_backup = ENV.delete("XDG_CONFIG_HOME")
ENV["XDG_CONFIG_HOME"] = dir
example.run
ensure
ENV["XDG_CONFIG_HOME"] = xdg_config_home_backup
end
end
config.after :suite do config.after :suite do
FileUtils.rm_r Spec::Path.pristine_system_gem_path FileUtils.rm_r Spec::Path.pristine_system_gem_path
end end

View file

@ -62,7 +62,7 @@ class CompactIndexAPI < Endpoint
body.byteslice(range) body.byteslice(range)
end end
def gems(gem_repo = GEM_REPO) def gems(gem_repo = default_gem_repo)
@gems ||= {} @gems ||= {}
@gems[gem_repo] ||= begin @gems[gem_repo] ||= begin
specs = Bundler::Deprecate.skip_during do specs = Bundler::Deprecate.skip_during do
@ -80,7 +80,7 @@ class CompactIndexAPI < Endpoint
CompactIndex::Dependency.new(d.name, reqs) CompactIndex::Dependency.new(d.name, reqs)
end end
checksum = begin checksum = begin
Digest(:SHA256).file("#{GEM_REPO}/gems/#{spec.original_name}.gem").base64digest Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").base64digest
rescue StandardError rescue StandardError
nil nil
end end

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
require_relative "compact_index"
Artifice.deactivate
class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
def partial_update_no_etag
response_body = yield
headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
content_type "text/plain"
requested_range_for(response_body)
end
get "/versions" do
partial_update_no_etag do
file = tmp("versions.list")
FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
lines = file.contents([], :calculate_info_checksums => true).split("\n")
name, versions, checksum = lines.last.split(" ")
# shuffle versions so new versions are not appended to the end
[*lines[0..-2], [name, versions.split(",").reverse.join(","), checksum].join(" ")].join("\n")
end
end
get "/info/:name" do
partial_update_no_etag do
gem = gems.find {|g| g.name == params[:name] }
lines = CompactIndex.info(gem ? gem.versions : []).split("\n")
# shuffle versions so new versions are not appended to the end
[lines.first, lines.last, *lines[1..-2]].join("\n")
end
end
end
Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental)

View file

@ -26,7 +26,6 @@ class Endpoint < Sinatra::Base
@all_requests ||= [] @all_requests ||= []
end end
GEM_REPO = Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
set :raise_errors, true set :raise_errors, true
set :show_exceptions, false set :show_exceptions, false
@ -41,7 +40,22 @@ class Endpoint < Sinatra::Base
helpers do helpers do
include Spec::Path include Spec::Path
def dependencies_for(gem_names, gem_repo = GEM_REPO) def default_gem_repo
if ENV["BUNDLER_SPEC_GEM_REPO"]
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"])
else
case request.host
when "gem.repo2"
Spec::Path.gem_repo2
when "gem.repo3"
Spec::Path.gem_repo3
else
Spec::Path.gem_repo1
end
end
end
def dependencies_for(gem_names, gem_repo = default_gem_repo)
return [] if gem_names.nil? || gem_names.empty? return [] if gem_names.nil? || gem_names.empty?
all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename| all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
@ -74,11 +88,11 @@ class Endpoint < Sinatra::Base
end end
get "/fetch/actual/gem/:id" do get "/fetch/actual/gem/:id" do
File.binread("#{GEM_REPO}/quick/Marshal.4.8/#{params[:id]}") File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
end end
get "/gems/:id" do get "/gems/:id" do
File.binread("#{GEM_REPO}/gems/#{params[:id]}") File.binread("#{default_gem_repo}/gems/#{params[:id]}")
end end
get "/api/v1/dependencies" do get "/api/v1/dependencies" do
@ -86,11 +100,11 @@ class Endpoint < Sinatra::Base
end end
get "/specs.4.8.gz" do get "/specs.4.8.gz" do
File.binread("#{GEM_REPO}/specs.4.8.gz") File.binread("#{default_gem_repo}/specs.4.8.gz")
end end
get "/prerelease_specs.4.8.gz" do get "/prerelease_specs.4.8.gz" do
File.binread("#{GEM_REPO}/prerelease_specs.4.8.gz") File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
end end
end end

View file

@ -14,7 +14,7 @@ class Windows < Sinatra::Base
set :show_exceptions, false set :show_exceptions, false
helpers do helpers do
def gem_repo def default_gem_repo
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1) Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
end end
end end
@ -26,7 +26,7 @@ class Windows < Sinatra::Base
files.each do |file| files.each do |file|
get "/#{file}" do get "/#{file}" do
File.binread gem_repo.join(file) File.binread default_gem_repo.join(file)
end end
end end

View file

@ -192,13 +192,6 @@ module Spec
update_repo2(&blk) if block_given? update_repo2(&blk) if block_given?
end end
def build_repo3
build_repo gem_repo3 do
build_gem "rack"
end
FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
end
# A repo that has no pre-installed gems included. (The caller completely # A repo that has no pre-installed gems included. (The caller completely
# determines the contents with the block.) # determines the contents with the block.)
def build_repo4(&blk) def build_repo4(&blk)

View file

@ -87,9 +87,11 @@ module Spec
env = options.delete(:env) || {} env = options.delete(:env) || {}
requires = options.delete(:requires) || [] requires = options.delete(:requires) || []
realworld = RSpec.current_example.metadata[:realworld]
options[:verbose] = true if options[:verbose].nil? && realworld
artifice = options.delete(:artifice) do artifice = options.delete(:artifice) do
if RSpec.current_example.metadata[:realworld] if realworld
"vcr" "vcr"
else else
"fail" "fail"

View file

@ -98,7 +98,7 @@ module Spec
gem_activate(gem_name) gem_activate(gem_name)
load Gem.bin_path(gem_name, bin_container) load Gem.bin_path(gem_name, bin_container)
rescue Gem::LoadError => e rescue Gem::LoadError => e
abort "We couln't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`" abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
end end
def gem_activate(gem_name) def gem_activate(gem_name)

View file

@ -49,6 +49,22 @@ class TestDeprecate < Gem::TestCase
@message = "bar" @message = "bar"
end end
rubygems_deprecate :foo, :bar rubygems_deprecate :foo, :bar
def foo_arg(msg)
@message = "foo" + msg
end
def bar_arg(msg)
@message = "bar" + msg
end
rubygems_deprecate :foo_arg, :bar_arg
def foo_kwarg(message:)
@message = "foo" + message
end
def bar_kwarg(message:)
@message = "bar" + message
end
rubygems_deprecate :foo_kwarg, :bar_kwarg
end end
class OtherThing class OtherThing
@ -61,6 +77,22 @@ class TestDeprecate < Gem::TestCase
@message = "bar" @message = "bar"
end end
deprecate :foo, :bar, 2099, 3 deprecate :foo, :bar, 2099, 3
def foo_arg(msg)
@message = "foo" + msg
end
def bar_arg(msg)
@message = "bar" + msg
end
deprecate :foo_arg, :bar_arg, 2099, 3
def foo_kwarg(message:)
@message = "foo" + message
end
def bar_kwarg(message:)
@message = "bar" + message
end
deprecate :foo_kwarg, :bar_kwarg, 2099, 3
end end
def test_deprecated_method_calls_the_old_method def test_deprecated_method_calls_the_old_method
@ -68,6 +100,10 @@ class TestDeprecate < Gem::TestCase
thing = Thing.new thing = Thing.new
thing.foo thing.foo
assert_equal "foo", thing.message assert_equal "foo", thing.message
thing.foo_arg("msg")
assert_equal "foomsg", thing.message
thing.foo_kwarg(message: "msg")
assert_equal "foomsg", thing.message
end end
end end
@ -75,10 +111,14 @@ class TestDeprecate < Gem::TestCase
out, err = capture_io do out, err = capture_io do
thing = Thing.new thing = Thing.new
thing.foo thing.foo
thing.foo_arg("msg")
thing.foo_kwarg(message: "msg")
end end
assert_equal "", out assert_equal "", out
assert_match(/Thing#foo is deprecated; use bar instead\./, err) assert_match(/Thing#foo is deprecated; use bar instead\./, err)
assert_match(/Thing#foo_arg is deprecated; use bar_arg instead\./, err)
assert_match(/Thing#foo_kwarg is deprecated; use bar_kwarg instead\./, err)
assert_match(/in Rubygems [0-9]+/, err) assert_match(/in Rubygems [0-9]+/, err)
end end
@ -104,10 +144,14 @@ class TestDeprecate < Gem::TestCase
out, err = capture_io do out, err = capture_io do
thing = OtherThing.new thing = OtherThing.new
thing.foo thing.foo
thing.foo_arg("msg")
thing.foo_kwarg(message: "msg")
end end
assert_equal "", out assert_equal "", out
assert_match(/Thing#foo is deprecated; use bar instead\./, err) assert_match(/OtherThing#foo is deprecated; use bar instead\./, err)
assert_match(/on or after 2099-03-01/, err) assert_match(/OtherThing#foo_arg is deprecated; use bar_arg instead\./, err)
assert_match(/OtherThing#foo_kwarg is deprecated; use bar_kwarg instead\./, err)
assert_match(/on or after 2099-03/, err)
end end
end end

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)

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)