summaryrefslogtreecommitdiff
path: root/lib/bundler
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2022-08-22 11:50:00 +0900
committernagachika <nagachika@ruby-lang.org>2022-09-03 15:54:07 +0900
commit522b75f1b666051f86a3c8961fd4255e560c5020 (patch)
tree85315021fac815517ce3e68f1883533aa4b35747 /lib/bundler
parent44c926f3a94346809c68574e0277dae3917992c6 (diff)
Merge RubyGems-3.3.20 and Bundler-2.3.20
Diffstat (limited to 'lib/bundler')
-rw-r--r--lib/bundler/cli.rb8
-rw-r--r--lib/bundler/cli/install.rb7
-rw-r--r--lib/bundler/cli/outdated.rb15
-rw-r--r--lib/bundler/cli/platform.rb2
-rw-r--r--lib/bundler/definition.rb72
-rw-r--r--lib/bundler/fetcher.rb12
-rw-r--r--lib/bundler/gem_helpers.rb8
-rw-r--r--lib/bundler/incomplete_specification.rb12
-rw-r--r--lib/bundler/installer.rb9
-rw-r--r--lib/bundler/installer/standalone.rb2
-rw-r--r--lib/bundler/lazy_specification.rb42
-rw-r--r--lib/bundler/man/bundle-cache.16
-rw-r--r--lib/bundler/man/bundle-cache.1.ronn7
-rw-r--r--lib/bundler/man/bundle-config.14
-rw-r--r--lib/bundler/man/bundle-config.1.ronn6
-rw-r--r--lib/bundler/man/bundle-install.14
-rw-r--r--lib/bundler/man/bundle-install.1.ronn6
-rw-r--r--lib/bundler/man/bundle-platform.120
-rw-r--r--lib/bundler/man/bundle-platform.1.ronn21
-rw-r--r--lib/bundler/man/bundle.19
-rw-r--r--lib/bundler/man/bundle.1.ronn7
-rw-r--r--lib/bundler/resolver.rb3
-rw-r--r--lib/bundler/ruby_dsl.rb2
-rw-r--r--lib/bundler/ruby_version.rb10
-rw-r--r--lib/bundler/rubygems_ext.rb13
-rw-r--r--lib/bundler/source/metadata.rb2
-rw-r--r--lib/bundler/source_list.rb4
-rw-r--r--lib/bundler/spec_set.rb43
-rw-r--r--lib/bundler/version.rb2
29 files changed, 244 insertions, 114 deletions
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index e1c284130b..5bf0f4fa3a 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -218,6 +218,8 @@ module Bundler
"Specify the number of jobs to run in parallel"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "prefer-local", :type => :boolean, :banner =>
+ "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
method_option "no-cache", :type => :boolean, :banner =>
"Don't update the existing gem cache."
method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
@@ -236,7 +238,7 @@ module Bundler
"Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
method_option "trust-policy", :alias => "P", :type => :string, :banner =>
"Gem trust policy (like gem install -P). Must be one of " +
- Bundler.rubygems.security_policy_keys.join("|")
+ Bundler.rubygems.security_policy_keys.join("|")
method_option "without", :type => :array, :banner =>
"Exclude gems that are part of the specified named group."
method_option "with", :type => :array, :banner =>
@@ -399,9 +401,9 @@ module Bundler
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
method_option "source", :type => :array, :banner => "Check against a specific source"
- method_option "filter-strict", :type => :boolean, :banner =>
+ method_option "filter-strict", :type => :boolean, :aliases => "--strict", :banner =>
"Only list newer versions allowed by your Gemfile requirements"
- method_option "strict", :type => :boolean, :aliases => "--update-strict", :banner =>
+ method_option "update-strict", :type => :boolean, :banner =>
"Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version"
method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)"
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index e9b85f7f6f..851ae9b840 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -147,8 +147,11 @@ module Bundler
def normalize_settings
Bundler.settings.set_command_option :path, nil if options[:system]
Bundler.settings.set_command_option_if_given :path, options[:path]
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
- Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
+
+ if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
+ Bundler.settings.temporary(:path_relative_to_cwd => false) do
+ Bundler.settings.set_command_option :path, "bundle"
+ end
end
bin_option = options["binstubs"]
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index d5183b060b..e9f93fec39 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -46,7 +46,7 @@ module Bundler
Bundler::CLI::Common.configure_gem_version_promoter(
Bundler.definition,
- options
+ options.merge(:strict => @strict)
)
definition_resolution = proc do
@@ -129,6 +129,12 @@ module Bundler
private
+ def loaded_from_for(spec)
+ return unless spec.respond_to?(:loaded_from)
+
+ spec.loaded_from
+ end
+
def groups_text(group_text, groups)
"#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\""
end
@@ -184,7 +190,10 @@ module Bundler
def print_gem(current_spec, active_spec, dependency, groups)
spec_version = "#{active_spec.version}#{active_spec.git_version}"
- spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from
+ if Bundler.ui.debug?
+ loaded_from = loaded_from_for(active_spec)
+ spec_version += " (from #{loaded_from})" if loaded_from
+ end
current_version = "#{current_spec.version}#{current_spec.git_version}"
if dependency && dependency.specific?
@@ -211,7 +220,7 @@ module Bundler
dependency = dependency.requirement if dependency
ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s]
- ret_val << active_spec.loaded_from.to_s if Bundler.ui.debug?
+ ret_val << loaded_from_for(active_spec).to_s if Bundler.ui.debug?
ret_val
end
diff --git a/lib/bundler/cli/platform.rb b/lib/bundler/cli/platform.rb
index 068c765aad..16d4e0145a 100644
--- a/lib/bundler/cli/platform.rb
+++ b/lib/bundler/cli/platform.rb
@@ -9,7 +9,7 @@ module Bundler
def run
platforms, ruby_version = Bundler.ui.silence do
- locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version
+ locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version.gsub(/p\d+\Z/, "")
gemfile_ruby_version = Bundler.definition.ruby_version && Bundler.definition.ruby_version.single_version_string
[Bundler.definition.platforms.map {|p| "* #{p}" },
locked_ruby_version || gemfile_ruby_version]
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index d55ee29ebc..21c06e55ba 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -70,6 +70,7 @@ module Bundler
@unlock = unlock
@optional_groups = optional_groups
@remote = false
+ @prefer_local = false
@specs = nil
@ruby_version = ruby_version
@gemfiles = gemfiles
@@ -170,6 +171,13 @@ module Bundler
resolve
end
+ def resolve_prefering_local!
+ @prefer_local = true
+ @remote = true
+ sources.remote!
+ resolve
+ end
+
def resolve_with_cache!
sources.cached!
resolve
@@ -476,6 +484,7 @@ module Bundler
def reresolve
last_resolve = converge_locked_specs
+ remove_ruby_from_platforms_if_necessary!(dependencies)
expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true)
Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end
@@ -516,10 +525,8 @@ module Bundler
end
end
- unless specs["bundler"].any?
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
- specs["bundler"] = bundler
- end
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
+ specs["bundler"] = bundler
specs
end
@@ -528,6 +535,19 @@ module Bundler
@remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
+ def pin_locally_available_names(source_requirements)
+ source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
+ local_source = original_source.dup
+ local_source.local_only!
+
+ new_source_requirements[name] = if local_source.specs.search(name).any?
+ local_source
+ else
+ original_source
+ end
+ end
+ end
+
def current_ruby_platform_locked?
return false unless generic_local_platform == Gem::Platform::RUBY
return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
@@ -719,16 +739,24 @@ module Bundler
specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
end
+ @specs_that_changed_sources = []
+
specs.each do |s|
- # Replace the locked dependency's source with the equivalent source from the Gemfile
dep = @dependencies.find {|d| s.satisfies?(d) }
- s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
+ s.source = if dep && dep.source
+ gemfile_source = dep.source
+ lockfile_source = s.source
- next if @unlock[:sources].include?(s.source.name)
+ @specs_that_changed_sources << s if gemfile_source != lockfile_source
- # If the spec is from a path source and it doesn't exist anymore
- # then we unlock it.
+ gemfile_source
+ else
+ sources.get_with_fallback(s.source)
+ end
+
+ next if @unlock[:sources].include?(s.source.name)
# Path sources have special logic
if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
@@ -765,7 +793,7 @@ module Bundler
def metadata_dependencies
@metadata_dependencies ||= [
- Dependency.new("Ruby\0", RubyVersion.system.gem_version),
+ Dependency.new("Ruby\0", Gem.ruby_version),
Dependency.new("RubyGems\0", Gem::VERSION),
]
end
@@ -792,7 +820,9 @@ module Bundler
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
source_requirements = if precompute_source_requirements_for_indirect_dependencies?
- { :default => sources.default_source }.merge(source_map.all_requirements)
+ all_requirements = source_map.all_requirements
+ all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
+ { :default => sources.default_source }.merge(all_requirements)
else
{ :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
end
@@ -802,9 +832,18 @@ module Bundler
end
source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
+ verify_changed_sources!
source_requirements
end
+ def verify_changed_sources!
+ @specs_that_changed_sources.each do |s|
+ if s.source.specs.search(s.name).empty?
+ raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
+ end
+ end
+ end
+
def requested_groups
values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
@@ -844,6 +883,17 @@ module Bundler
end
end
+ def remove_ruby_from_platforms_if_necessary!(dependencies)
+ return if Bundler.frozen_bundle? ||
+ Bundler.local_platform == Gem::Platform::RUBY ||
+ !platforms.include?(Gem::Platform::RUBY) ||
+ (@new_platform && platforms.last == Gem::Platform::RUBY) ||
+ !@originally_locked_specs.incomplete_ruby_specs?(dependencies)
+
+ remove_platform(Gem::Platform::RUBY)
+ add_current_platform
+ end
+
def source_map
@source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index e9d5dd505c..e399a50cfd 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -240,8 +240,8 @@ module Bundler
def connection
@connection ||= begin
needs_ssl = remote_uri.scheme == "https" ||
- Bundler.settings[:ssl_verify_mode] ||
- Bundler.settings[:ssl_client_cert]
+ Bundler.settings[:ssl_verify_mode] ||
+ Bundler.settings[:ssl_client_cert]
raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
con = PersistentHTTP.new :name => "bundler", :proxy => :ENV
@@ -256,8 +256,8 @@ module Bundler
end
ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
- (Gem.configuration.ssl_client_cert if
- Gem.configuration.respond_to?(:ssl_client_cert))
+ (Gem.configuration.ssl_client_cert if
+ Gem.configuration.respond_to?(:ssl_client_cert))
if ssl_client_cert
pem = File.read(ssl_client_cert)
con.cert = OpenSSL::X509::Certificate.new(pem)
@@ -288,8 +288,8 @@ module Bundler
def bundler_cert_store
store = OpenSSL::X509::Store.new
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
- (Gem.configuration.ssl_ca_cert if
- Gem.configuration.respond_to?(:ssl_ca_cert))
+ (Gem.configuration.ssl_ca_cert if
+ Gem.configuration.respond_to?(:ssl_ca_cert))
if ssl_ca_cert
if File.directory? ssl_ca_cert
store.add_path ssl_ca_cert
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index 6bc4fb4991..0d50d8687b 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -44,6 +44,12 @@ module Bundler
def select_best_platform_match(specs, platform)
matching = specs.select {|spec| spec.match_platform(platform) }
+
+ sort_best_platform_match(matching, platform)
+ end
+ module_function :select_best_platform_match
+
+ def sort_best_platform_match(matching, platform)
exact = matching.select {|spec| spec.platform == platform }
return exact if exact.any?
@@ -52,7 +58,7 @@ module Bundler
sorted_matching.take_while {|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
end
- module_function :select_best_platform_match
+ module_function :sort_best_platform_match
class PlatformMatch
def self.specificity_score(spec_platform, user_platform)
diff --git a/lib/bundler/incomplete_specification.rb b/lib/bundler/incomplete_specification.rb
new file mode 100644
index 0000000000..6d0b9b901c
--- /dev/null
+++ b/lib/bundler/incomplete_specification.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Bundler
+ class IncompleteSpecification
+ attr_reader :name, :platform
+
+ def initialize(name, platform)
+ @name = name
+ @platform = platform
+ end
+ end
+end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index f195d36600..b7b0e36dfd 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -268,7 +268,14 @@ module Bundler
return false if @definition.nothing_changed? && !@definition.missing_specs?
end
- options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
+ if options["local"]
+ @definition.resolve_with_cache!
+ elsif options["prefer-local"]
+ @definition.resolve_prefering_local!
+ else
+ @definition.resolve_remotely!
+ end
+
true
end
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index 248b677233..2756626f8a 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -47,7 +47,7 @@ module Bundler
end
def bundler_path
- Bundler.root.join(Bundler.settings[:path], "bundler")
+ Bundler.root.join(Bundler.settings[:path].to_s, "bundler")
end
def gem_path(path, spec)
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 21e75d2126..5b40bec5a8 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -76,35 +76,35 @@ module Bundler
end
def materialize_for_installation
- __materialize__(ruby_platform_materializes_to_ruby_platform? ? platform : Bundler.local_platform)
- end
+ source.local!
+
+ candidates = if source.is_a?(Source::Path) || !ruby_platform_materializes_to_ruby_platform?
+ target_platform = ruby_platform_materializes_to_ruby_platform? ? platform : Bundler.local_platform
+
+ source.specs.search(Dependency.new(name, version)).select do |spec|
+ MatchPlatform.platforms_match?(spec.platform, target_platform)
+ end
+ else
+ source.specs.search(self)
+ end
- def materialize_for_resolution
- return self unless Gem::Platform.match_spec?(self)
+ return self if candidates.empty?
- __materialize__(platform)
+ __materialize__(candidates)
end
- def __materialize__(platform)
- @specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
- source.gemspec.tap {|s| s.source = source }
- else
- search_object = if source.is_a?(Source::Path)
- Dependency.new(name, version)
- else
- ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version)
- end
- candidates = source.specs.search(search_object)
- same_platform_candidates = candidates.select do |spec|
- MatchPlatform.platforms_match?(spec.platform, platform)
- end
- installable_candidates = same_platform_candidates.select do |spec|
+ def __materialize__(candidates)
+ @specification = begin
+ search = candidates.reverse.find do |spec|
spec.is_a?(StubSpecification) ||
(spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version))
end
- search = installable_candidates.last || same_platform_candidates.last
- search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
+ if search.nil? && Bundler.frozen_bundle?
+ search = candidates.last
+ else
+ search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
+ end
search
end
end
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 4903015881..fdaaa3b92a 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -9,6 +9,9 @@
.SH "SYNOPSIS"
\fBbundle cache\fR
.
+.P
+alias: \fBpackage\fR, \fBpack\fR
+.
.SH "DESCRIPTION"
Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
.
@@ -53,3 +56,6 @@ One way to be sure that you have the right platformed versions of all your gems
.
.P
By default, bundle cache(1) \fIbundle\-cache\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle cache \-\-no\-install\fR\.
+.
+.SH "HISTORY"
+In Bundler 2\.1, \fBcache\fR took in the functionalities of \fBpackage\fR and now \fBpackage\fR and \fBpack\fR are aliases of \fBcache\fR\.
diff --git a/lib/bundler/man/bundle-cache.1.ronn b/lib/bundler/man/bundle-cache.1.ronn
index 383adb2ba3..46906d2b48 100644
--- a/lib/bundler/man/bundle-cache.1.ronn
+++ b/lib/bundler/man/bundle-cache.1.ronn
@@ -5,6 +5,8 @@ bundle-cache(1) -- Package your needed `.gem` files into your application
`bundle cache`
+alias: `package`, `pack`
+
## DESCRIPTION
Copy all of the `.gem` files needed to run the application into the
@@ -70,3 +72,8 @@ By default, [bundle cache(1)](bundle-cache.1.html) fetches and also
installs the gems to the default location. To package the
dependencies to `vendor/cache` without installing them to the
local install location, you can run `bundle cache --no-install`.
+
+## HISTORY
+
+In Bundler 2.1, `cache` took in the functionalities of `package` and now
+`package` and `pack` are aliases of `cache`.
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index b5cee57f29..9f7887ca91 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -51,7 +51,7 @@ Executing \fBbundle config unset <name>\fR will delete the configuration in both
Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
.
.P
-Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the configuration only from the local application\.
+Executing \fBbundle config unset \-\-local <name>\fR will delete the configuration only from the local application\.
.
.P
Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
@@ -298,7 +298,7 @@ The following is a list of all configuration keys and their purpose\. You can le
.IP "" 0
.
.P
-In general, you should set these settings per\-application by using the applicable flag to the bundle install(1) \fIbundle\-install\.1\.html\fR or bundle package(1) \fIbundle\-package\.1\.html\fR command\.
+In general, you should set these settings per\-application by using the applicable flag to the bundle install(1) \fIbundle\-install\.1\.html\fR or bundle cache(1) \fIbundle\-cache\.1\.html\fR command\.
.
.P
You can set them globally either via environment variables or \fBbundle config\fR, whichever is preferable for your setup\. If you use both, environment variables will take preference over global settings\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index e2af773141..905c85fcd9 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -43,8 +43,8 @@ local and global sources.
Executing `bundle config unset --global <name>` will delete the configuration
only from the user configuration.
-Executing `bundle config unset --local <name> <value>` will delete the
-configuration only from the local application.
+Executing `bundle config unset --local <name>` will delete the configuration
+only from the local application.
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration.
@@ -280,7 +280,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
A `:`-separated list of groups whose gems bundler should not install.
In general, you should set these settings per-application by using the applicable
-flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command.
+flag to the [bundle install(1)](bundle-install.1.html) or [bundle cache(1)](bundle-cache.1.html) command.
You can set them globally either via environment variables or `bundle config`,
whichever is preferable for your setup. If you use both, environment variables
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index c742efd142..8e94fe2437 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -70,6 +70,10 @@ The maximum number of parallel download and install jobs\. The default is the nu
Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
.
.TP
+\fB\-\-prefer\-local\fR
+Force using locally installed gems, or gems already present in Rubygems\' cache or in \fBvendor/cache\fR, when resolving, even if newer versions are available remotely\. Only attempt to connect to \fBrubygems\.org\fR for gems that are not present locally\.
+.
+.TP
\fB\-\-no\-cache\fR
Do not update the cache in \fBvendor/cache\fR with the newly bundled gems\. This does not remove any gems in the cache but keeps the newly bundled gems from being cached during the install\.
.
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index bec05187f3..47200ac2d5 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -109,6 +109,12 @@ automatically and that requires `bundler` to silently remember them. Since
appropriate platform-specific gem exists on `rubygems.org` it will not be
found.
+* `--prefer-local`:
+ Force using locally installed gems, or gems already present in Rubygems' cache
+ or in `vendor/cache`, when resolving, even if newer versions are available
+ remotely. Only attempt to connect to `rubygems.org` for gems that are not
+ present locally.
+
* `--no-cache`:
Do not update the cache in `vendor/cache` with the newly bundled gems. This
does not remove any gems in the cache but keeps the newly bundled gems from
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index 344ad93083..f5a90c59e9 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -10,7 +10,7 @@
\fBbundle platform\fR [\-\-ruby]
.
.SH "DESCRIPTION"
-\fBplatform\fR will display information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
+\fBplatform\fR displays information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
.
.P
For instance, using this Gemfile(5):
@@ -21,7 +21,7 @@ For instance, using this Gemfile(5):
source "https://rubygems\.org"
-ruby "1\.9\.3"
+ruby "3\.1\.2"
gem "rack"
.
@@ -30,7 +30,7 @@ gem "rack"
.IP "" 0
.
.P
-If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following output:
+If you run \fBbundle platform\fR on Ruby 3\.1\.2, it displays the following output:
.
.IP "" 4
.
@@ -39,10 +39,13 @@ If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following
Your platform is: x86_64\-linux
Your app has gems that work on these platforms:
+* arm64\-darwin\-21
* ruby
+* x64\-mingw\-ucrt
+* x86_64\-linux
Your Gemfile specifies a Ruby version requirement:
-* ruby 1\.9\.3
+* ruby 3\.1\.2
Your current platform satisfies the Ruby version requirement\.
.
@@ -51,11 +54,18 @@ Your current platform satisfies the Ruby version requirement\.
.IP "" 0
.
.P
-\fBplatform\fR will list all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It will also let you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it will tell you what part does not\.
+\fBplatform\fR lists all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It also lets you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it tells you what part does not\.
.
.SH "OPTIONS"
.
.TP
\fB\-\-ruby\fR
It will display the ruby directive information, so you don\'t have to parse it from the Gemfile(5)\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+bundle\-lock(1) \fIbundle\-lock\.1\.ronn\fR
+.
+.IP "" 0
diff --git a/lib/bundler/man/bundle-platform.1.ronn b/lib/bundler/man/bundle-platform.1.ronn
index b5d3283fb6..eb9baa1c62 100644
--- a/lib/bundler/man/bundle-platform.1.ronn
+++ b/lib/bundler/man/bundle-platform.1.ronn
@@ -7,36 +7,43 @@ bundle-platform(1) -- Displays platform compatibility information
## DESCRIPTION
-`platform` will display information from your Gemfile, Gemfile.lock, and Ruby
+`platform` displays information from your Gemfile, Gemfile.lock, and Ruby
VM about your platform.
For instance, using this Gemfile(5):
source "https://rubygems.org"
- ruby "1.9.3"
+ ruby "3.1.2"
gem "rack"
-If you run `bundle platform` on Ruby 1.9.3, it will display the following output:
+If you run `bundle platform` on Ruby 3.1.2, it displays the following output:
Your platform is: x86_64-linux
Your app has gems that work on these platforms:
+ * arm64-darwin-21
* ruby
+ * x64-mingw-ucrt
+ * x86_64-linux
Your Gemfile specifies a Ruby version requirement:
- * ruby 1.9.3
+ * ruby 3.1.2
Your current platform satisfies the Ruby version requirement.
-`platform` will list all the platforms in your `Gemfile.lock` as well as the
-`ruby` directive if applicable from your Gemfile(5). It will also let you know
+`platform` lists all the platforms in your `Gemfile.lock` as well as the
+`ruby` directive if applicable from your Gemfile(5). It also lets you know
if the `ruby` directive requirement has been met. If `ruby` directive doesn't
-match the running Ruby VM, it will tell you what part does not.
+match the running Ruby VM, it tells you what part does not.
## OPTIONS
* `--ruby`:
It will display the ruby directive information, so you don't have to
parse it from the Gemfile(5).
+
+## SEE ALSO
+
+* [bundle-lock(1)](bundle-lock.1.ronn)
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index c46c37c708..f683e78cc6 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -43,8 +43,8 @@ Install the gems specified by the \fBGemfile\fR or \fBGemfile\.lock\fR
Update dependencies to their latest versions
.
.TP
-\fBbundle package(1)\fR \fIbundle\-package\.1\.html\fR
-Package the \.gem files required by your application into the \fBvendor/cache\fR directory
+\fBbundle cache(1)\fR \fIbundle\-cache\.1\.html\fR
+Package the \.gem files required by your application into the \fBvendor/cache\fR directory (aliases: \fBbundle package\fR, \fBbundle pack\fR)
.
.TP
\fBbundle exec(1)\fR \fIbundle\-exec\.1\.html\fR
@@ -81,7 +81,7 @@ Show the source location of a particular gem in the bundle
Show all of the outdated gems in the current bundle
.
.TP
-\fBbundle console(1)\fR
+\fBbundle console(1)\fR (deprecated)
Start an IRB session in the current bundle
.
.TP
@@ -127,9 +127,6 @@ When running a command that isn\'t listed in PRIMARY COMMANDS or UTILITIES, Bund
These commands are obsolete and should no longer be used:
.
.IP "\(bu" 4
-\fBbundle cache(1)\fR
-.
-.IP "\(bu" 4
\fBbundle inject(1)\fR
.
.IP "" 0
diff --git a/lib/bundler/man/bundle.1.ronn b/lib/bundler/man/bundle.1.ronn
index fa247ab365..8f0159eee5 100644
--- a/lib/bundler/man/bundle.1.ronn
+++ b/lib/bundler/man/bundle.1.ronn
@@ -36,9 +36,9 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle update(1)`](bundle-update.1.html):
Update dependencies to their latest versions
-* [`bundle package(1)`](bundle-package.1.html):
+* [`bundle cache(1)`](bundle-cache.1.html):
Package the .gem files required by your application into the
- `vendor/cache` directory
+ `vendor/cache` directory (aliases: `bundle package`, `bundle pack`)
* [`bundle exec(1)`](bundle-exec.1.html):
Execute a script in the current bundle
@@ -67,7 +67,7 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle outdated(1)`](bundle-outdated.1.html):
Show all of the outdated gems in the current bundle
-* `bundle console(1)`:
+* `bundle console(1)` (deprecated):
Start an IRB session in the current bundle
* [`bundle open(1)`](bundle-open.1.html):
@@ -107,5 +107,4 @@ and execute it, passing down any extra arguments to it.
These commands are obsolete and should no longer be used:
-* `bundle cache(1)`
* `bundle inject(1)`
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 40bc247b32..ca1bdbda7b 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -28,10 +28,11 @@ module Bundler
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
@source_requirements = source_requirements
@metadata_requirements = metadata_requirements
+ @base = base
@resolver = Molinillo::Resolver.new(self, self)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
- @base = base.materialized_for_resolution do |ls|
+ base.each do |ls|
dep = Dependency.new(ls.name, ls.version)
@base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
end
diff --git a/lib/bundler/ruby_dsl.rb b/lib/bundler/ruby_dsl.rb
index f6ba220cd5..3b3a0583a5 100644
--- a/lib/bundler/ruby_dsl.rb
+++ b/lib/bundler/ruby_dsl.rb
@@ -9,7 +9,7 @@ module Bundler
raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
if options[:engine] == "ruby" && options[:engine_version] &&
- ruby_version != Array(options[:engine_version])
+ ruby_version != Array(options[:engine_version])
raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
end
@ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])
diff --git a/lib/bundler/ruby_version.rb b/lib/bundler/ruby_version.rb
index 3f51cf4528..9161c6afde 100644
--- a/lib/bundler/ruby_version.rb
+++ b/lib/bundler/ruby_version.rb
@@ -32,12 +32,12 @@ module Bundler
@engine = engine && engine.to_s || "ruby"
@engine_versions = (engine_version && Array(engine_version)) || @versions
@engine_gem_version = Gem::Requirement.create(@engine_versions.first).requirements.first.last
- @patchlevel = patchlevel
+ @patchlevel = patchlevel || (@gem_version.prerelease? ? "-1" : nil)
end
def to_s(versions = self.versions)
output = String.new("ruby #{versions_string(versions)}")
- output << "p#{patchlevel}" if patchlevel
+ output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
output
@@ -46,7 +46,7 @@ module Bundler
# @private
PATTERN = /
ruby\s
- ([\d.]+) # ruby version
+ (\d+\.\d+\.\d+(?:\.\S+)?) # ruby version
(?:p(-?\d+))? # optional patchlevel
(?:\s\((\S+)\s(.+)\))? # optional engine info
/xo.freeze
@@ -103,8 +103,8 @@ module Bundler
def self.system
ruby_engine = RUBY_ENGINE.dup
- ruby_version = RUBY_VERSION.dup
- ruby_engine_version = RUBY_ENGINE_VERSION.dup
+ ruby_version = Gem.ruby_version.to_s
+ ruby_engine_version = RUBY_ENGINE == "ruby" ? ruby_version : RUBY_ENGINE_VERSION.dup
patchlevel = RUBY_PATCHLEVEL.to_s
@ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index a47692d1f2..938c58e64d 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -17,6 +17,15 @@ require "rubygems/source"
require_relative "match_platform"
+# Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
+# versions and ignore patchlevels
+# (https://github.com/rubygems/rubygems/pull/5472,
+# https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
+# 3.3.12 support is dropped.
+unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
+ Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
+end
+
module Gem
class Specification
include ::Bundler::MatchPlatform
@@ -146,6 +155,10 @@ module Gem
alias_method :eql?, :==
+ def force_ruby_platform
+ false
+ end
+
def encode_with(coder)
to_yaml_properties.each do |ivar|
coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 185fe70824..23531b8bd4 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -5,7 +5,7 @@ module Bundler
class Metadata < Source
def specs
@specs ||= Index.build do |idx|
- idx << Gem::Specification.new("Ruby\0", RubyVersion.system.gem_version)
+ idx << Gem::Specification.new("Ruby\0", Gem.ruby_version)
idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
s.required_rubygems_version = Gem::Requirement.default
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index a4773397c7..6ea2910d18 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -101,6 +101,10 @@ module Bundler
source_list_for(source).find {|s| equivalent_source?(source, s) }
end
+ def get_with_fallback(source)
+ get(source) || default_source
+ end
+
def lock_sources
lock_other_sources + lock_rubygems_sources
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index a7a95e49bc..14733269d6 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -13,14 +13,16 @@ module Bundler
def for(dependencies, check = false, platforms = [nil])
handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
- deps = dependencies.product(platforms).map {|dep, platform| [dep.name, platform && dep.force_ruby_platform ? Gem::Platform::RUBY : platform] }
+ deps = dependencies.product(platforms)
specs = []
loop do
break unless dep = deps.shift
- next if handled.key?(dep)
- handled[dep] = true
+ key = [dep[0].name, dep[1]]
+ next if handled.key?(key)
+
+ handled[key] = true
specs_for_dep = specs_for_dependency(*dep)
if specs_for_dep.any?
@@ -28,17 +30,13 @@ module Bundler
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
- deps << [d.name, dep[1]]
+ deps << [d, dep[1]]
end
elsif check
- specs << IncompleteSpecification.new(*dep)
+ specs << IncompleteSpecification.new(*key)
end
end
- if spec = lookup["bundler"].first
- specs << spec
- end
-
specs
end
@@ -66,13 +64,8 @@ module Bundler
end
def materialize(deps)
- materialized = self.for(deps, true).uniq
+ materialized = self.for(deps, true)
- materialized.map! do |s|
- next s unless s.is_a?(LazySpecification)
- s.source.local!
- s.materialize_for_installation || s
- end
SpecSet.new(materialized)
end
@@ -82,7 +75,6 @@ module Bundler
def materialized_for_all_platforms
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
- s.source.local!
s.source.remote!
spec = s.materialize_for_installation
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
@@ -90,13 +82,8 @@ module Bundler
end
end
- def materialized_for_resolution
- materialized = @specs.map do |s|
- spec = s.materialize_for_resolution
- yield spec if spec
- spec
- end.compact
- SpecSet.new(materialized)
+ def incomplete_ruby_specs?(deps)
+ self.class.new(self.for(deps, true, [Gem::Platform::RUBY])).incomplete_specs.any?
end
def missing_specs
@@ -181,13 +168,13 @@ module Bundler
@specs.sort_by(&:name).each {|s| yield s }
end
- def specs_for_dependency(name, platform)
- specs_for_name = lookup[name]
+ def specs_for_dependency(dep, platform)
+ specs_for_name = lookup[dep.name]
if platform.nil?
- GemHelpers.select_best_platform_match(specs_for_name.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
+ matching_specs = specs_for_name.map {|s| s.materialize_for_installation if Gem::Platform.match_spec?(s) }.compact
+ GemHelpers.sort_best_platform_match(matching_specs, Bundler.local_platform)
else
- specs_for_name_and_platform = GemHelpers.select_best_platform_match(specs_for_name, platform)
- specs_for_name_and_platform.any? ? specs_for_name_and_platform : specs_for_name
+ GemHelpers.select_best_platform_match(specs_for_name, dep.force_ruby_platform ? Gem::Platform::RUBY : platform)
end
end
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index f01d90b943..f15165f86d 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.3.19".freeze
+ VERSION = "2.3.20".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i