diff options
author | The Bundler Bot <bot@bundler.io> | 2017-06-23 00:26:33 +0000 |
---|---|---|
committer | The Bundler Bot <bot@bundler.io> | 2017-06-23 00:26:33 +0000 |
commit | 7a76c3555af9fb7f56327397ae2876bd684a95f0 (patch) | |
tree | d57e02cb9357a2e6e9e63fac8f131cfac5109941 | |
parent | 67ff76af19e6d033d26e63ff2f064754316fee38 (diff) | |
parent | c35495cd1738b9c867cde5198319deacb52df555 (diff) | |
download | bundler-7a76c3555af9fb7f56327397ae2876bd684a95f0.tar.gz |
Auto merge of #5788 - bundler:seg-allow-bundler-dep-conflicts, r=indirect
[2.0] Allow conflicts between bundler dependencies and the current bundler version
### What was the end-user problem that led to this PR?
The problem will occur once 2.0 is released -- there are many gems that declare a `s.dependency "bundler", "~> 1.x"` dependency on bundler. This would essentially make them inoperable with Bundler 2. We want to make adopting 2.0 as pain-free as possible, so hard conflicts are a no-go.
### Was was your diagnosis of the problem?
My diagnosis was that we need a way to allow conflicts on the bundler dependency once 2.0 comes out, so people can use 2.0.
### What is your fix for the problem, implemented in this PR?
My fix introduces a feature flag for allowing these conflicts (enabled on 2.0), which when enabled will ignore bundler dependencies during resolution, and warn in the installer when a conflict would've occurred.
### Why did you choose this fix out of the possible options?
I chose this fix because it has the minimal performance penalty with the feature flag enabled. This is mostly a port of https://github.com/bundler/bundler/pull/3871 to master.
-rw-r--r-- | lib/bundler/definition.rb | 5 | ||||
-rw-r--r-- | lib/bundler/feature_flag.rb | 1 | ||||
-rw-r--r-- | lib/bundler/installer.rb | 17 | ||||
-rw-r--r-- | lib/bundler/resolver.rb | 14 | ||||
-rw-r--r-- | lib/bundler/settings.rb | 1 | ||||
-rw-r--r-- | lib/bundler/shared_helpers.rb | 11 | ||||
-rw-r--r-- | man/bundle-config.ronn | 3 | ||||
-rw-r--r-- | spec/install/bundler_spec.rb | 22 |
8 files changed, 64 insertions, 10 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 0e39cf710c..7157c46b98 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -567,10 +567,7 @@ module Bundler end def pretty_dep(dep, source = false) - msg = String.new(dep.name) - msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default - msg << " from the `#{dep.source}` source" if source && dep.source - msg + SharedHelpers.pretty_dependency(dep, source) end # Check if the specs of the given source changed diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb index b07ea49679..0a3b010d1a 100644 --- a/lib/bundler/feature_flag.rb +++ b/lib/bundler/feature_flag.rb @@ -14,6 +14,7 @@ module Bundler (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } } + settings_flag(:allow_bundler_dependency_conflicts) { bundler_2_mode? } settings_flag(:allow_offline_install) { bundler_2_mode? } settings_flag(:error_on_stderr) { bundler_2_mode? } settings_flag(:init_gems_rb) { bundler_2_mode? } diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 7c13c0c8a9..c47012973b 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -80,6 +80,7 @@ module Bundler resolve_if_needed(options) ensure_specs_are_compatible! + warn_on_incompatible_bundler_deps install(options) lock unless Bundler.settings[:frozen] @@ -202,6 +203,22 @@ module Bundler end end + def warn_on_incompatible_bundler_deps + bundler_version = Gem::Version.create(Bundler::VERSION) + @definition.specs.each do |spec| + spec.dependencies.each do |dep| + next if dep.type == :development + next unless dep.name == "bundler".freeze + next if dep.requirement.satisfied_by?(bundler_version) + + Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \ + " #{SharedHelpers.pretty_dependency(dep)}" \ + ", which is unsatisfied by the current bundler version #{VERSION}" \ + ", so the dependency is being ignored" + end + end + end + def can_install_in_parallel? if Bundler.rubygems.provides?(">= 2.1.0") true diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index db2ae496a4..93c9d669c4 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -5,11 +5,7 @@ module Bundler class Molinillo::VersionConflict def printable_dep(dep) - if dep.is_a?(Bundler::Dependency) - DepProxy.new(dep, dep.platforms.join(", ")).to_s.strip - else - dep.to_s - end + SharedHelpers.pretty_dependency(dep) end def message @@ -79,6 +75,7 @@ module Bundler include GemHelpers attr_reader :activated + attr_accessor :ignores_bundler_dependencies def initialize(a) super @@ -88,6 +85,7 @@ module Bundler @specs = Hash.new do |specs, platform| specs[platform] = select_best_platform_match(self, platform) end + @ignores_bundler_dependencies = true end def initialize_copy(o) @@ -151,6 +149,7 @@ module Bundler if spec = @specs[platform] spec.dependencies.each do |dep| next if dep.type == :development + next if @ignores_bundler_dependencies && dep.name == "bundler".freeze dependencies[platform] << DepProxy.new(dep, platform) end end @@ -206,6 +205,7 @@ module Bundler additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) } @platforms = platforms @gem_version_promoter = gem_version_promoter + @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts? end def start(requirements) @@ -281,7 +281,9 @@ module Bundler end nested.reduce([]) do |groups, (version, specs)| next groups if locked_requirement && !locked_requirement.satisfied_by?(version) - groups << SpecGroup.new(specs) + spec_group = SpecGroup.new(specs) + spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts + groups << spec_group end else [] diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index e0eb660a8a..77f01774a2 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -7,6 +7,7 @@ module Bundler autoload :Mirrors, "bundler/mirror" BOOL_KEYS = %w[ + allow_bundler_dependency_conflicts allow_offline_install auto_install cache_all diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 39f0423f7f..07880387f0 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -176,6 +176,17 @@ module Bundler "\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem." end + def pretty_dependency(dep, print_source = false) + msg = String.new(dep.name) + msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default + if dep.is_a?(Bundler::Dependency) + platform_string = dep.platforms.join(", ") + msg << " " << platform_string if !platform_string.empty? && platform_string != Gem::Platform::RUBY + end + msg << " from the `#{dep.source}` source" if print_source && dep.source + msg + end + private def find_gemfile(order_matters = false) diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn index c8a1391d3e..9fc62edae3 100644 --- a/man/bundle-config.ronn +++ b/man/bundle-config.ronn @@ -234,6 +234,9 @@ learn more about their operation in [bundle install(1)][bundle-install]. * `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`) Require passing `--all` to `bundle update` when everything should be updated, and disallow passing no options to `bundle update`. +* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`): + Allow resolving to specifications that have dependencies on `bundler` that + are incompatible with the running Bundler version. In general, you should set these settings per-application by using the applicable flag to the [bundle install(1)][bundle-install] or [bundle package(1)][bundle-package] command. diff --git a/spec/install/bundler_spec.rb b/spec/install/bundler_spec.rb index 5035937ea1..ca17d19abd 100644 --- a/spec/install/bundler_spec.rb +++ b/spec/install/bundler_spec.rb @@ -142,5 +142,27 @@ RSpec.describe "bundle install" do bundle "check" expect(out).to include("The Gemfile's dependencies are satisfied") end + + context "with allow_bundler_dependency_conflicts set" do + before { bundle! "config allow_bundler_dependency_conflicts true" } + + it "are forced to the current bundler version with warnings when no compatible version is found" do + build_repo4 do + build_gem "requires_nonexistant_bundler" do |s| + s.add_runtime_dependency "bundler", "99.99.99.99" + end + end + + install_gemfile! <<-G + source "file://#{gem_repo4}" + gem "requires_nonexistant_bundler" + G + + expect(out).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \ + "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored" + + expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0" + end + end end end |