summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler/definition.rb71
-rw-r--r--lib/bundler/inline.rb1
-rw-r--r--lib/bundler/installer.rb10
-rw-r--r--lib/bundler/lazy_specification.rb11
-rw-r--r--lib/bundler/resolver.rb104
-rw-r--r--lib/bundler/resolver/base.rb45
-rw-r--r--lib/bundler/resolver/candidate.rb7
-rw-r--r--lib/bundler/resolver/package.rb13
-rw-r--r--lib/bundler/shared_helpers.rb2
-rw-r--r--lib/bundler/source/rubygems.rb2
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb24
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb2
-rw-r--r--spec/bundler/commands/lock_spec.rb283
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb177
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb2
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb2
-rw-r--r--spec/bundler/runtime/inline_spec.rb26
-rw-r--r--spec/bundler/support/indexes.rb21
18 files changed, 521 insertions, 282 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 09a756abc7..9763298504 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -159,13 +159,6 @@ module Bundler
resolve
end
- def resolve_prefering_local!
- @prefer_local = true
- @remote = true
- sources.remote!
- resolve
- end
-
def resolve_with_cache!
sources.cached!
resolve
@@ -177,6 +170,23 @@ module Bundler
resolve
end
+ def resolution_mode=(options)
+ if options["local"]
+ @remote = false
+ else
+ @remote = true
+ @prefer_local = options["prefer-local"]
+ end
+ end
+
+ def setup_sources_for_resolve
+ if @remote == false
+ sources.cached!
+ else
+ sources.remote!
+ end
+ end
+
# For given dependency list returns a SpecSet with Gemspec of all the required
# dependencies.
# 1. The method first resolves the dependencies specified in Gemfile
@@ -473,31 +483,19 @@ module Bundler
private
def resolver
- @resolver ||= begin
- last_resolve = converge_locked_specs
- remove_ruby_from_platforms_if_necessary!(current_dependencies)
- Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve))
- end
+ @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
end
def expanded_dependencies
- @expanded_dependencies ||= dependencies + metadata_dependencies
+ dependencies + metadata_dependencies
end
def resolution_packages
@resolution_packages ||= begin
- packages = Hash.new do |h, k|
- h[k] = Resolver::Package.new(k, @platforms, @originally_locked_specs, @unlock[:gems])
- end
-
- expanded_dependencies.each do |dep|
- name = dep.name
- platforms = dep.gem_platforms(@platforms)
-
- packages[name] = Resolver::Package.new(name, platforms, @originally_locked_specs, @unlock[:gems], :dependency => dep)
- end
-
- packages
+ last_resolve = converge_locked_specs
+ remove_ruby_from_platforms_if_necessary!(current_dependencies)
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, :locked_specs => @originally_locked_specs, :unlock => @unlock[:gems], :prerelease => gem_version_promoter.pre?)
+ additional_base_requirements_for_resolve(packages, last_resolve)
end
end
@@ -531,13 +529,15 @@ module Bundler
break if incomplete_specs.empty?
Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
- @resolve = start_resolution(:exclude_specs => incomplete_specs)
+ setup_sources_for_resolve
+ resolution_packages.delete(incomplete_specs)
+ @resolve = start_resolution
specs = resolve.materialize(dependencies)
still_incomplete_specs = specs.incomplete_specs
if still_incomplete_specs == incomplete_specs
- package = resolution_packages[incomplete_specs.first.name]
+ package = resolution_packages.get_package(incomplete_specs.first.name)
resolver.raise_not_found! package
end
@@ -550,14 +550,14 @@ module Bundler
specs
end
- def start_resolution(exclude_specs: [])
- result = resolver.start(expanded_dependencies, resolution_packages, :exclude_specs => exclude_specs)
+ def start_resolution
+ result = resolver.start
SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms))
end
def precompute_source_requirements_for_indirect_dependencies?
- @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
+ sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
def pin_locally_available_names(source_requirements)
@@ -885,11 +885,12 @@ module Bundler
current == proposed
end
- def additional_base_requirements_for_resolve(last_resolve)
- return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
- converge_specs(@originally_locked_specs - last_resolve).map do |locked_spec|
- Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
- end.uniq
+ def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
+ return resolution_packages unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
+ converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
+ resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
+ end
+ resolution_packages
end
def remove_ruby_from_platforms_if_necessary!(dependencies)
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index 855ae5526a..5c184f67a1 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -31,6 +31,7 @@
#
def gemfile(install = false, options = {}, &gemfile)
require_relative "../bundler"
+ Bundler.reset!
opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new }
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 04d7dc6f23..680e812ac8 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -249,17 +249,13 @@ module Bundler
# returns whether or not a re-resolve was needed
def resolve_if_needed(options)
+ @definition.resolution_mode = options
+
if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
return false if @definition.nothing_changed? && !@definition.missing_specs?
end
- if options["local"]
- @definition.resolve_with_cache!
- elsif options["prefer-local"]
- @definition.resolve_prefering_local!
- else
- @definition.resolve_remotely!
- end
+ @definition.setup_sources_for_resolve
true
end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index dccfe48bba..6749892930 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -89,7 +89,7 @@ module Bundler
installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
- specification = __materialize__(installable_candidates)
+ specification = __materialize__(installable_candidates, :fallback_to_non_installable => false)
return specification unless specification.nil?
if target_platform != platform
@@ -102,13 +102,18 @@ module Bundler
__materialize__(candidates)
end
- def __materialize__(candidates)
+ # If in frozen mode, we fallback to a non-installable candidate because by
+ # doing this we avoid re-resolving and potentially end up changing the
+ # lock file, which is not allowed. In that case, we will give a proper error
+ # about the mismatch higher up the stack, right before trying to install the
+ # bad gem.
+ def __materialize__(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
search = candidates.reverse.find do |spec|
spec.is_a?(StubSpecification) ||
(spec.matches_current_ruby? &&
spec.matches_current_rubygems?)
end
- if search.nil? && Bundler.frozen_bundle?
+ if search.nil? && fallback_to_non_installable
search = candidates.last
else
search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index df9ce2ff3f..8237ff53fe 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -9,26 +9,21 @@ module Bundler
class Resolver
require_relative "vendored_pub_grub"
require_relative "resolver/base"
- require_relative "resolver/package"
require_relative "resolver/candidate"
require_relative "resolver/incompatibility"
require_relative "resolver/root"
include GemHelpers
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements)
- @source_requirements = source_requirements
- @base = Resolver::Base.new(base, additional_base_requirements)
+ def initialize(base, gem_version_promoter)
+ @source_requirements = base.source_requirements
+ @base = base
@gem_version_promoter = gem_version_promoter
end
- def start(requirements, packages, exclude_specs: [])
- exclude_specs.each do |spec|
- remove_from_candidates(spec)
- end
-
- @requirements = requirements
- @packages = packages
+ def start
+ @requirements = @base.requirements
+ @packages = @base.packages
root, logger = setup_solver
@@ -78,33 +73,26 @@ module Bundler
rescue PubGrub::SolveFailure => e
incompatibility = e.incompatibility
- names_to_unlock = []
- extended_explanation = nil
+ names_to_unlock, names_to_allow_prereleases_for, extended_explanation = find_names_to_relax(incompatibility)
- while incompatibility.conflict?
- cause = incompatibility.cause
- incompatibility = cause.incompatibility
-
- incompatibility.terms.each do |term|
- name = term.package.name
- names_to_unlock << name if base_requirements[name]
+ names_to_relax = names_to_unlock + names_to_allow_prereleases_for
- no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
- next unless no_versions_incompat
+ if names_to_relax.any?
+ if names_to_unlock.any?
+ Bundler.ui.debug "Found conflicts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
- extended_explanation = no_versions_incompat.extended_explanation
+ @base.unlock_names(names_to_unlock)
end
- end
-
- names_to_unlock.uniq!
- if names_to_unlock.any?
- Bundler.ui.debug "Found conflicts with locked dependencies. Retrying with #{names_to_unlock.join(", ")} unlocked...", true
+ if names_to_allow_prereleases_for.any?
+ Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retrying considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
- @base.unlock_names(names_to_unlock)
+ @base.include_prereleases(names_to_allow_prereleases_for)
+ end
root, logger = setup_solver
+ Bundler.ui.debug "Retrying resolution...", true
retry
end
@@ -118,6 +106,35 @@ module Bundler
raise SolveFailure.new(explanation)
end
+ def find_names_to_relax(incompatibility)
+ names_to_unlock = []
+ names_to_allow_prereleases_for = []
+ extended_explanation = nil
+
+ while incompatibility.conflict?
+ cause = incompatibility.cause
+ incompatibility = cause.incompatibility
+
+ incompatibility.terms.each do |term|
+ package = term.package
+ name = package.name
+
+ if base_requirements[name]
+ names_to_unlock << name
+ elsif package.ignores_prereleases?
+ names_to_allow_prereleases_for << name
+ end
+
+ no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
+ next unless no_versions_incompat
+
+ extended_explanation = no_versions_incompat.extended_explanation
+ end
+ end
+
+ [names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, extended_explanation]
+ end
+
def parse_dependency(package, dependency)
range = if repository_for(package).is_a?(Source::Gemspec)
PubGrub::VersionRange.any
@@ -215,7 +232,7 @@ module Bundler
def all_versions_for(package)
name = package.name
- results = (@base[name] + @all_specs[name]).uniq {|spec| [spec.version.hash, spec.platform] }
+ results = (@base[name] + filter_prereleases(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
locked_requirement = base_requirements[name]
results = filter_matching_specs(results, locked_requirement) if locked_requirement
@@ -284,6 +301,12 @@ module Bundler
end
end
+ def filter_prereleases(specs, package)
+ return specs unless package.ignores_prereleases?
+
+ specs.reject {|s| s.version.prerelease? }
+ end
+
def requirement_satisfied_by?(requirement, spec)
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
end
@@ -304,25 +327,20 @@ module Bundler
@base.base_requirements
end
- def remove_from_candidates(spec)
- @base.delete(spec)
- end
-
def prepare_dependencies(requirements, packages)
to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
name = dep_package.name
- # If a dependency is scoped to a platform different from the current
- # one, we ignore it. However, it may reappear during resolution as a
- # transitive dependency of another package, so we need to reset the
- # package so the proper versions are considered if reintroduced later.
- if dep_package.platforms.empty?
- @packages.delete(name)
- next
+ next [dep_package, dep_constraint] if name == "bundler"
+
+ versions = versions_for(dep_package, dep_constraint.range)
+ if versions.empty? && dep_package.ignores_prereleases?
+ @sorted_versions.delete(dep_package)
+ dep_package.consider_prereleases!
+ versions = versions_for(dep_package, dep_constraint.range)
end
+ next [dep_package, dep_constraint] unless versions.empty?
- next [dep_package, dep_constraint] if name == "bundler"
- next [dep_package, dep_constraint] unless versions_for(dep_package, dep_constraint.range).empty?
next unless dep_package.current_platform?
raise_not_found!(dep_package)
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
index 78b798f4ec..6921c047a7 100644
--- a/lib/bundler/resolver/base.rb
+++ b/lib/bundler/resolver/base.rb
@@ -1,19 +1,47 @@
# frozen_string_literal: true
+require_relative "package"
+
module Bundler
class Resolver
class Base
- def initialize(base, additional_base_requirements)
+ attr_reader :packages, :requirements, :source_requirements
+
+ def initialize(source_requirements, dependencies, base, platforms, options)
+ @source_requirements = source_requirements
+
@base = base
- @additional_base_requirements = additional_base_requirements
+
+ @packages = Hash.new do |hash, name|
+ hash[name] = Package.new(name, platforms, **options)
+ end
+
+ @requirements = dependencies.map do |dep|
+ dep_platforms = dep.gem_platforms(platforms)
+
+ # Dependencies scoped to external platforms are ignored
+ next if dep_platforms.empty?
+
+ name = dep.name
+
+ @packages[name] = Package.new(name, dep_platforms, **options.merge(:dependency => dep))
+
+ dep
+ end.compact
end
def [](name)
@base[name]
end
- def delete(spec)
- @base.delete(spec)
+ def delete(specs)
+ specs.each do |spec|
+ @base.delete(spec)
+ end
+ end
+
+ def get_package(name)
+ @packages[name]
end
def base_requirements
@@ -24,10 +52,14 @@ module Bundler
names.each do |name|
@base.delete_by_name(name)
- @additional_base_requirements.reject! {|dep| dep.name == name }
+ @base_requirements.delete(name)
end
+ end
- @base_requirements = nil
+ def include_prereleases(names)
+ names.each do |name|
+ get_package(name).consider_prereleases!
+ end
end
private
@@ -38,7 +70,6 @@ module Bundler
req = Gem::Requirement.new(ls.version)
base_requirements[ls.name] = req
end
- @additional_base_requirements.each {|d| base_requirements[d.name] = d.requirement }
base_requirements
end
end
diff --git a/lib/bundler/resolver/candidate.rb b/lib/bundler/resolver/candidate.rb
index 681f9aca73..e695ef08ee 100644
--- a/lib/bundler/resolver/candidate.rb
+++ b/lib/bundler/resolver/candidate.rb
@@ -26,9 +26,8 @@ module Bundler
def initialize(version, specs: [])
@spec_group = Resolver::SpecGroup.new(specs)
- @platforms = specs.map(&:platform).sort_by(&:to_s).uniq
@version = Gem::Version.new(version)
- @ruby_only = @platforms == [Gem::Platform::RUBY]
+ @ruby_only = specs.map(&:platform).uniq == [Gem::Platform::RUBY]
end
def dependencies
@@ -88,9 +87,7 @@ module Bundler
end
def to_s
- return @version.to_s if @platforms.empty? || @ruby_only
-
- "#{@version} (#{@platforms.join(", ")})"
+ @version.to_s
end
end
end
diff --git a/lib/bundler/resolver/package.rb b/lib/bundler/resolver/package.rb
index 7d64632860..7499a75006 100644
--- a/lib/bundler/resolver/package.rb
+++ b/lib/bundler/resolver/package.rb
@@ -15,12 +15,13 @@ module Bundler
class Package
attr_reader :name, :platforms, :dependency, :locked_version
- def initialize(name, platforms, locked_specs, unlock, dependency: nil)
+ def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, dependency: nil)
@name = name
@platforms = platforms
@locked_version = locked_specs[name].first&.version
@unlock = unlock
@dependency = dependency || Dependency.new(name, @locked_version)
+ @prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
end
def to_s
@@ -47,8 +48,16 @@ module Bundler
@unlock.empty? || @unlock.include?(name)
end
+ def ignores_prereleases?
+ @prerelease == :ignore
+ end
+
def prerelease_specified?
- @dependency.prerelease?
+ @prerelease == :consider_first
+ end
+
+ def consider_prereleases!
+ @prerelease = :consider_last
end
def force_ruby_platform?
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 0a6afe0e5a..794a03e62d 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -284,7 +284,7 @@ module Bundler
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
- Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__)
+ Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__) unless RUBY_VERSION < "2.7"
end
def set_path
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 7eefd291a2..c39071705a 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -292,7 +292,7 @@ module Bundler
end
def dependency_api_available?
- api_fetchers.any?
+ @allow_remote && api_fetchers.any?
end
protected
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index e944f387d3..b5c0f69795 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -16,6 +16,10 @@ RSpec.describe Bundler::GemVersionPromoter do
Bundler::SpecSet.new(build_spec(name, v))
end
+ def build_package(name, platforms, locked_specs, unlock)
+ Bundler::Resolver::Package.new(name, platforms, :locked_specs => locked_specs, :unlock => unlock)
+ end
+
# Rightmost (highest array index) in result is most preferred.
# Leftmost (lowest array index) in result is least preferred.
# `build_candidates` has all versions of gem in index.
@@ -35,7 +39,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when keeping build_spec, keep current, next release" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.8"), []),
build_candidates(%w[1.7.8 1.7.9 1.8.0])
)
expect(versions(res)).to eq %w[1.7.8 1.7.9]
@@ -43,7 +47,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking prefer next release first" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.8"), []),
build_candidates(%w[1.7.8 1.7.9 1.8.0])
)
expect(versions(res)).to eq %w[1.7.8 1.7.9]
@@ -51,7 +55,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking keep current when already at latest release" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.9"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.9"), []),
build_candidates(%w[1.7.9 1.8.0 2.0.0])
)
expect(versions(res)).to eq %w[1.7.9]
@@ -68,7 +72,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking favor next releases, remove minor and major increases" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), []),
+ build_package("foo", [], build_spec_set("foo", "0.2.0"), []),
build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1])
)
expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0]
@@ -76,7 +80,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when keep locked, keep current, then favor next release, remove minor and major increases" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), ["bar"]),
+ build_package("foo", [], build_spec_set("foo", "0.2.0"), ["bar"]),
build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1])
)
expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0]
@@ -93,7 +97,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.7"), ["bar"]),
+ build_package("foo", [], build_spec_set("foo", "1.7.7"), ["bar"]),
build_candidates(%w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1])
)
expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7]
@@ -101,7 +105,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking favor next release, then current over minor increase" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.8"), []),
build_candidates(%w[1.7.7 1.7.8 1.7.9 1.8.0])
)
expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9]
@@ -109,7 +113,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking do proper integer comparison, not string" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.8"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.8"), []),
build_candidates(%w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0])
)
expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15]
@@ -117,7 +121,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "leave current when unlocking but already at latest release" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "1.7.9"), []),
+ build_package("foo", [], build_spec_set("foo", "1.7.9"), []),
build_candidates(%w[1.7.9 1.8.0 2.0.0])
)
expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9]
@@ -134,7 +138,7 @@ RSpec.describe Bundler::GemVersionPromoter do
it "when unlocking favor next release, then minor increase over current" do
res = gvp.sort_versions(
- Bundler::Resolver::Package.new("foo", [], build_spec_set("foo", "0.2.0"), []),
+ build_package("foo", [], build_spec_set("foo", "0.2.0"), []),
build_candidates(%w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1])
)
expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0]
diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb
index 3d8014b665..3c6536c4eb 100644
--- a/spec/bundler/bundler/shared_helpers_spec.rb
+++ b/spec/bundler/bundler/shared_helpers_spec.rb
@@ -248,6 +248,8 @@ RSpec.describe Bundler::SharedHelpers do
shared_examples_for "ENV['BUNDLER_SETUP'] gets set correctly" do
it "ensures bundler/setup is set in ENV['BUNDLER_SETUP']" do
+ skip "Does not play well with DidYouMean being a bundled gem instead of a default gem in Ruby 2.6" if RUBY_VERSION < "2.7"
+
subject.set_bundle_environment
expect(ENV["BUNDLER_SETUP"]).to eq("#{source_lib_dir}/bundler/setup")
end
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 38bef77eaf..08ac333664 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -768,133 +768,212 @@ RSpec.describe "bundle lock" do
#{Bundler::VERSION}
L
end
+ end
- it "properly shows resolution errors including OR requirements" do
- build_repo4 do
- build_gem "activeadmin", "2.13.1" do |s|
- s.add_dependency "railties", ">= 6.1", "< 7.1"
- end
- build_gem "actionpack", "6.1.4"
- build_gem "actionpack", "7.0.3.1"
- build_gem "actionpack", "7.0.4"
- build_gem "railties", "6.1.4" do |s|
- s.add_dependency "actionpack", "6.1.4"
- end
- build_gem "rails", "7.0.3.1" do |s|
- s.add_dependency "railties", "7.0.3.1"
- end
- build_gem "rails", "7.0.4" do |s|
- s.add_dependency "railties", "7.0.4"
- end
+ it "properly shows resolution errors including OR requirements" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "railties", ">= 6.1", "< 7.1"
+ end
+ build_gem "actionpack", "6.1.4"
+ build_gem "actionpack", "7.0.3.1"
+ build_gem "actionpack", "7.0.4"
+ build_gem "railties", "6.1.4" do |s|
+ s.add_dependency "actionpack", "6.1.4"
+ end
+ build_gem "rails", "7.0.3.1" do |s|
+ s.add_dependency "railties", "7.0.3.1"
end
+ build_gem "rails", "7.0.4" do |s|
+ s.add_dependency "railties", "7.0.4"
+ end
+ end
- gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
- gem "rails", ">= 7.0.3.1"
- gem "activeadmin", "2.13.1"
- G
+ gem "rails", ">= 7.0.3.1"
+ gem "activeadmin", "2.13.1"
+ G
- bundle "lock", :raise_on_error => false
+ bundle "lock", :raise_on_error => false
- expect(err).to eq <<~ERR.strip
- Could not find compatible versions
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
- Because rails >= 7.0.4 depends on railties = 7.0.4
- and rails < 7.0.4 depends on railties = 7.0.3.1,
- railties = 7.0.3.1 OR = 7.0.4 is required.
- So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally,
- version solving has failed.
- ERR
- end
+ Because rails >= 7.0.4 depends on railties = 7.0.4
+ and rails < 7.0.4 depends on railties = 7.0.3.1,
+ railties = 7.0.3.1 OR = 7.0.4 is required.
+ So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally,
+ version solving has failed.
+ ERR
+ end
- it "is able to display some explanation on crazy irresolvable cases" do
- build_repo4 do
- build_gem "activeadmin", "2.13.1" do |s|
- s.add_dependency "ransack", "= 3.1.0"
- end
+ it "is able to display some explanation on crazy irresolvable cases" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "ransack", "= 3.1.0"
+ end
- # Activemodel is missing as a dependency in lockfile
- build_gem "ransack", "3.1.0" do |s|
- s.add_dependency "activemodel", ">= 6.0.4"
- s.add_dependency "activesupport", ">= 6.0.4"
- end
+ # Activemodel is missing as a dependency in lockfile
+ build_gem "ransack", "3.1.0" do |s|
+ s.add_dependency "activemodel", ">= 6.0.4"
+ s.add_dependency "activesupport", ">= 6.0.4"
+ end
- %w[6.0.4 7.0.2.3 7.0.3.1 7.0.4].each do |version|
- build_gem "activesupport", version
+ %w[6.0.4 7.0.2.3 7.0.3.1 7.0.4].each do |version|
+ build_gem "activesupport", version
- # Activemodel is only available on 6.0.4
- if version == "6.0.4"
- build_gem "activemodel", version do |s|
- s.add_dependency "activesupport", version
- end
+ # Activemodel is only available on 6.0.4
+ if version == "6.0.4"
+ build_gem "activemodel", version do |s|
+ s.add_dependency "activesupport", version
end
+ end
- build_gem "rails", version do |s|
- # Depednencies of Rails 7.0.2.3 are in reverse order
- if version == "7.0.2.3"
- s.add_dependency "activesupport", version
- s.add_dependency "activemodel", version
- else
- s.add_dependency "activemodel", version
- s.add_dependency "activesupport", version
- end
+ build_gem "rails", version do |s|
+ # Depednencies of Rails 7.0.2.3 are in reverse order
+ if version == "7.0.2.3"
+ s.add_dependency "activesupport", version
+ s.add_dependency "activemodel", version
+ else
+ s.add_dependency "activemodel", version
+ s.add_dependency "activesupport", version
end
end
end
+ end
- gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
- gem "rails", ">= 7.0.2.3"
- gem "activeadmin", "= 2.13.1"
- G
+ gem "rails", ">= 7.0.2.3"
+ gem "activeadmin", "= 2.13.1"
+ G
- lockfile <<~L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- activeadmin (2.13.1)
- ransack (= 3.1.0)
- ransack (3.1.0)
- activemodel (>= 6.0.4)
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ activeadmin (2.13.1)
+ ransack (= 3.1.0)
+ ransack (3.1.0)
+ activemodel (>= 6.0.4)
- PLATFORMS
- #{lockfile_platforms}
+ PLATFORMS
+ #{lockfile_platforms}
- DEPENDENCIES
- activeadmin (= 2.13.1)
- ransack (= 3.1.0)
+ DEPENDENCIES
+ activeadmin (= 2.13.1)
+ ransack (= 3.1.0)
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock", :raise_on_error => false
+
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
+
+ Because every version of activemodel depends on activesupport = 6.0.4
+ and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
+ every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1.
+ And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
+ rails >= 7.0.2.3, < 7.0.3.1 is forbidden.
+ (1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
+ and rails >= 7.0.4 depends on activemodel = 7.0.4,
+ rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4.
+
+ Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
+ and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
+ rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1.
+ And because rails >= 7.0.4 depends on activesupport = 7.0.4
+ and every version of activemodel depends on activesupport = 6.0.4,
+ activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3.
+ And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1),
+ rails >= 7.0.2.3 is forbidden.
+ So, because Gemfile depends on rails >= 7.0.2.3,
+ version solving has failed.
+ ERR
+ end
+
+ it "does not accidentally resolves to prereleases" do
+ build_repo4 do
+ build_gem "autoproj", "2.0.3" do |s|
+ s.add_dependency "autobuild", ">= 1.10.0.a"
+ s.add_dependency "tty-prompt"
+ end
+
+ build_gem "tty-prompt", "0.6.0"
+ build_gem "tty-prompt", "0.7.0"
+ build_gem "autobuild", "1.10.0.b3"
+ build_gem "autobuild", "1.10.1" do |s|
+ s.add_dependency "tty-prompt", "~> 0.6.0"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "autoproj", ">= 2.0.0"
+ G
+
+ bundle "lock"
+ expect(lockfile).to_not include("autobuild (1.10.0.b3)")
+ expect(lockfile).to include("autobuild (1.10.1)")
+ end
+
+ it "deals with platform specific incompatibilities" do
+ build_repo4 do
+ build_gem "activerecord", "6.0.6"
+ build_gem "activerecord-jdbc-adapter", "60.4" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.0.0"
+ end
+ build_gem "activerecord-jdbc-adapter", "61.0" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.1.0"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activerecord", "6.0.6"
+ gem "activerecord-jdbc-adapter", "61.0"
+ G
+
+ simulate_platform "universal-java-19" do
bundle "lock", :raise_on_error => false
+ end
+
+ expect(err).to include("Could not find compatible versions")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ end
+
+ context "when re-resolving to include prereleases" do
+ before do
+ build_repo4 do
+ build_gem "tzinfo-data", "1.2022.7"
+ build_gem "rails", "7.1.0.alpha" do |s|
+ s.add_dependency "activesupport"
+ end
+ build_gem "activesupport", "7.1.0.alpha"
+ end
+ end
+
+ it "does not end up including gems scoped to other platforms in the lockfile" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rails"
+ gem "tzinfo-data", platform: :windows
+ G
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "lock"
+ end
- expect(err).to eq <<~ERR.strip
- Could not find compatible versions
-
- Because every version of activemodel depends on activesupport = 6.0.4
- and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
- every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1.
- And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
- rails >= 7.0.2.3, < 7.0.3.1 is forbidden.
- (1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
- and rails >= 7.0.4 depends on activemodel = 7.0.4,
- rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4.
-
- Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
- and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
- rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1.
- And because rails >= 7.0.4 depends on activesupport = 7.0.4
- and every version of activemodel depends on activesupport = 6.0.4,
- activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3.
- And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1),
- rails >= 7.0.2.3 is forbidden.
- So, because Gemfile depends on rails >= 7.0.2.3,
- version solving has failed.
- ERR
+ expect(lockfile).not_to include("tzinfo-data (1.2022.7)")
end
end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 8f23b509bd..2f82a9f9f3 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -6,10 +6,8 @@ RSpec.describe "bundle install with specific platforms" do
gem "google-protobuf"
G
- context "when on a darwin machine" do
- before { simulate_platform "x86_64-darwin-15" }
-
- it "locks to the specific darwin platform" do
+ it "locks to the specific darwin platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
@@ -19,8 +17,10 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
])
end
+ end
- it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
@@ -53,8 +53,10 @@ RSpec.describe "bundle install with specific platforms" do
# make sure the platform that got actually installed with the old bundler is used
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
end
+ end
- it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
@@ -103,8 +105,10 @@ RSpec.describe "bundle install with specific platforms" do
#{Bundler::VERSION}
L
end
+ end
- it "still installs the generic RUBY variant if necessary even when running on a legacy lockfile locked only to RUBY" do
+ context "when running on a legacy lockfile locked only to RUBY" do
+ around do |example|
build_repo4 do
build_gem "nokogiri", "1.3.10"
build_gem "nokogiri", "1.3.10" do |s|
@@ -140,12 +144,20 @@ RSpec.describe "bundle install with specific platforms" do
2.1.4
L
- simulate_platform "arm64-darwin-22" do
- bundle "update --bundler", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- end
+ simulate_platform "arm64-darwin-22", &example
end
- it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ it "still installs the generic RUBY variant if necessary" do
+ bundle "update --bundler", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end
+
+ it "still installs the generic RUBY variant if necessary, even in frozen mode" do
+ bundle "update --bundler", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "BUNDLE_FROZEN" => "true" }
+ end
+ end
+
+ it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ simulate_platform "x86_64-darwin-15" do
build_repo2 do
build_gem("libv8", "8.4.255.0")
build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" }
@@ -188,8 +200,10 @@ RSpec.describe "bundle install with specific platforms" do
bundle "add mini_racer --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)")
end
+ end
- it "chooses platform specific gems even when resolving upon materialization and the API returns more specific platforms first" do
+ it "chooses platform specific gems even when resolving upon materialization and the API returns more specific platforms first" do
+ simulate_platform "x86_64-darwin-15" do
build_repo4 do
build_gem("grpc", "1.50.0")
build_gem("grpc", "1.50.0") {|s| s.platform = "universal-darwin" }
@@ -220,8 +234,10 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose", :artifice => "compact_index_precompiled_before", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
expect(out).to include("Installing grpc 1.50.0 (universal-darwin)")
end
+ end
- it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "cache --all-platforms"
@@ -230,8 +246,10 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "config set --local cache_all_platforms true"
@@ -241,44 +259,46 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
- git = build_git "pg_array_parser", "1.0"
+ it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
+ git = build_git "pg_array_parser", "1.0"
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
- G
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
+ G
- lockfile <<-L
- GIT
- remote: #{lib_path("pg_array_parser-1.0")}
- revision: #{git.ref_for("main")}
- specs:
- pg_array_parser (1.0-java)
- pg_array_parser (1.0)
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("pg_array_parser-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ pg_array_parser (1.0-java)
+ pg_array_parser (1.0)
- GEM
- specs:
+ GEM
+ specs:
- PLATFORMS
- java
- #{lockfile_platforms}
+ PLATFORMS
+ java
+ #{lockfile_platforms}
- DEPENDENCIES
- pg_array_parser!
+ DEPENDENCIES
+ pg_array_parser!
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- bundle "config set --local cache_all true"
- bundle "cache --all-platforms"
+ bundle "config set --local cache_all true"
+ bundle "cache --all-platforms"
- expect(err).to be_empty
- end
+ expect(err).to be_empty
+ end
- it "uses the platform-specific gem with extra dependencies" do
+ it "uses the platform-specific gem with extra dependencies" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem_with_different_dependencies_per_platform
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -291,13 +311,15 @@ RSpec.describe "bundle install with specific platforms" do
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0",
"facter-2.4.6-universal-darwin"])
end
+ end
- context "when adding a platform via lock --add_platform" do
- before do
- allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- end
+ context "when adding a platform via lock --add_platform" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
- it "adds the foreign platform" do
+ it "adds the foreign platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
bundle "lock --add-platform=#{x64_mingw32}"
@@ -308,8 +330,10 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
])
end
+ end
- it "falls back on plain ruby when that version doesn't have a platform-specific gem" do
+ it "falls back on plain ruby when that version doesn't have a platform-specific gem" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
bundle "lock --add-platform=#{java}"
@@ -664,6 +688,63 @@ RSpec.describe "bundle install with specific platforms" do
L
end
+ it "automatically fixes the lockfile without removing other variants if it's missing platform gems, but they are installed locally" do
+ simulate_platform "x86_64-darwin-21" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-20"
+ end
+
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ # Make sure sorbet-static-0.5.10549-universal-darwin-21 is installed
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "= 0.5.10549"
+ G
+
+ # Make sure the lockfile is missing sorbet-static-0.5.10549-universal-darwin-21
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+ sorbet-static (0.5.10549-universal-darwin-21)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile" do
build_repo4 do
build_gem "nokogiri", "1.13.8"
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index d04da0c334..2f465b7b25 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -323,7 +323,7 @@ RSpec.describe "real world edgecases", :realworld => true do
if Bundler.feature_flag.bundler_3_mode?
# Conflicts on bundler version, so we count attempts differently
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false
- expect(out.split("\n").grep(/backtracking to/).count).to eq(8)
+ expect(out.split("\n").grep(/backtracking to/).count).to eq(16)
else
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
expect(out).to include("Solution found after 7 attempts")
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
index 3ef537be0a..aa8a48fcc7 100644
--- a/spec/bundler/realworld/slow_perf_spec.rb
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -28,6 +28,6 @@ RSpec.describe "bundle install with complex dependencies", :realworld => true do
gem 'rspec-rails'
G
- expect { bundle "lock" }.to take_less_than(18) # seconds
+ expect { bundle "lock" }.to take_less_than(30) # seconds
end
end
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index 8f347dfa68..9567d2a3c3 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -168,6 +168,29 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
+ it "installs subdependencies quietly if necessary when the install option is not set" do
+ build_repo4 do
+ build_gem "rack" do |s|
+ s.add_dependency "rackdep"
+ end
+
+ build_gem "rackdep", "1.0.0"
+ end
+
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ end
+
+ require "rackdep"
+ puts RACKDEP
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+
it "installs quietly from git if necessary when the install option is not set" do
build_git "foo", "1.0.0"
baz_ref = build_git("baz", "2.0.0").ref_for("HEAD")
@@ -207,8 +230,6 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
-<<<<<<< HEAD:spec/bundler/runtime/inline_spec.rb
-=======
it "doesn't reinstall already installed gems" do
system_gems "rack-1.0.0"
@@ -316,7 +337,6 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
->>>>>>> fa6e6ea95c2 (Fix issue with extensions not compiling properly using inline gemfile):bundler/spec/runtime/inline_spec.rb
it "installs inline gems when a Gemfile.lock is present" do
gemfile <<-G
source "https://notaserver.com"
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index 670f3b0230..78372302f1 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -18,22 +18,17 @@ module Spec
@platforms ||= ["ruby"]
default_source = instance_double("Bundler::Source::Rubygems", :specs => @index, :to_s => "locally install gems")
source_requirements = { :default => default_source }
- args[0] ||= Bundler::SpecSet.new([]) # base
- args[0].each {|ls| ls.source = default_source }
- args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter
- args[2] ||= [] # additional_base_requirements
- originally_locked = args[3] || Bundler::SpecSet.new([])
- unlock = args[4] || []
- packages = Hash.new do |h, k|
- h[k] = Bundler::Resolver::Package.new(k, @platforms, originally_locked, unlock)
- end
+ base = args[0] || Bundler::SpecSet.new([])
+ base.each {|ls| ls.source = default_source }
+ gem_version_promoter = args[1] || Bundler::GemVersionPromoter.new
+ originally_locked = args[2] || Bundler::SpecSet.new([])
+ unlock = args[3] || []
@deps.each do |d|
name = d.name
- platforms = d.gem_platforms(@platforms)
source_requirements[name] = d.source = default_source
- packages[name] = Bundler::Resolver::Package.new(name, platforms, originally_locked, unlock, :dependency => d)
end
- Bundler::Resolver.new(source_requirements, *args[0..2]).start(@deps, packages)
+ packages = Bundler::Resolver::Base.new(source_requirements, @deps, base, @platforms, :locked_specs => originally_locked, :unlock => unlock)
+ Bundler::Resolver.new(packages, gem_version_promoter).start
end
def should_not_resolve
@@ -71,7 +66,7 @@ module Spec
s.level = opts.first
s.strict = opts.include?(:strict)
end
- should_resolve_and_include specs, [@base, search, [], @locked, unlock]
+ should_resolve_and_include specs, [@base, search, @locked, unlock]
end
def an_awesome_index