diff options
author | The Bundler Bot <bot@bundler.io> | 2018-09-13 04:30:32 +0000 |
---|---|---|
committer | The Bundler Bot <bot@bundler.io> | 2018-09-13 04:30:32 +0000 |
commit | 87f49b2dc000b38776e6a73924e63ec090d53062 (patch) | |
tree | 4f7e9d3ae6ceca613baf38c87ae8ea47357115c9 | |
parent | 368d7594adbdf83032719011d7608545faf2d942 (diff) | |
parent | 7aa2639f79f019e0cff55bd27140360fe34c0eb7 (diff) | |
download | bundler-87f49b2dc000b38776e6a73924e63ec090d53062.tar.gz |
Auto merge of #6695 - bundler:segiddins/6684-gvp-prefer-non-pres, r=colby-swandale
[GemVersionPromoter] Prefer non-pre-release versions
### What was the end-user problem that led to this PR?
The problem was `bundle update --patch` could cause a prerelease to be resolved, when it shouldn't have been.
Closes #6684.
### What was your diagnosis of the problem?
My diagnosis was the resolver moved pre's to be first when no pre requirement was specified, but then the GVP did its own sorting.
### What is your fix for the problem, implemented in this PR?
My fix was to re-implement that "pre's go first unless they were explicitly requested" logic in the GVP.
### Why did you choose this fix out of the possible options?
I chose this fix because it allows the GVP to properly sort versions, making it entirely correct without dependence upon the resolver.
-rw-r--r-- | lib/bundler/gem_version_promoter.rb | 12 | ||||
-rw-r--r-- | lib/bundler/resolver.rb | 11 | ||||
-rw-r--r-- | spec/resolver/basic_spec.rb | 12 | ||||
-rw-r--r-- | spec/support/indexes.rb | 1 |
4 files changed, 31 insertions, 5 deletions
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb index 8d412c2cc0..ed950ad28b 100644 --- a/lib/bundler/gem_version_promoter.rb +++ b/lib/bundler/gem_version_promoter.rb @@ -24,6 +24,8 @@ module Bundler # existing in the referenced source. attr_accessor :strict + attr_accessor :prerelease_specified + # Given a list of locked_specs and a list of gems to unlock creates a # GemVersionPromoter instance. # @@ -39,6 +41,7 @@ module Bundler @locked_specs = locked_specs @unlock_gems = unlock_gems @sort_versions = {} + @prerelease_specified = {} end # @param value [Symbol] One of three Symbols: :major, :minor or :patch. @@ -123,6 +126,15 @@ module Bundler result = spec_groups.sort do |a, b| @a_ver = a.version @b_ver = b.version + + unless @prerelease_specified[@gem_name] + a_pre = @a_ver.prerelease? + b_pre = @b_ver.prerelease? + + next -1 if a_pre && !b_pre + next 1 if b_pre && !a_pre + end + if major? @a_ver <=> @b_ver elsif either_version_older_than_locked diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index a6c26ffc6b..fac28ced90 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -43,7 +43,7 @@ module Bundler end def start(requirements) - @prerelease_specified = {} + @gem_version_promoter.prerelease_specified = @prerelease_specified = {} requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? } verify_gemfile_dependencies_are_found!(requirements) @@ -108,16 +108,17 @@ module Bundler index = index_for(dependency) results = index.search(dependency, @base[dependency.name]) - unless @prerelease_specified[dependency.name] + if vertex = @base_dg.vertex_named(dependency.name) + locked_requirement = vertex.payload.requirement + end + + if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?) # Move prereleases to the beginning of the list, so they're considered # last during resolution. pre, results = results.partition {|spec| spec.version.prerelease? } results = pre + results end - if vertex = @base_dg.vertex_named(dependency.name) - locked_requirement = vertex.payload.requirement - end spec_groups = if results.any? nested = [] results.each do |spec| diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb index a2d5e13377..9f92303447 100644 --- a/spec/resolver/basic_spec.rb +++ b/spec/resolver/basic_spec.rb @@ -87,6 +87,18 @@ RSpec.describe "Resolving" do should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta rack-1.1 rack-mount-0.6] end + it "prefers non-pre-releases when doing conservative updates" do + @index = build_index do + gem "mail", "2.7.0" + gem "mail", "2.7.1.rc1" + gem "RubyGems\0", Gem::VERSION + end + dep "mail" + @locked = locked ["mail", "2.7.0"] + @base = locked + should_conservative_resolve_and_include [:patch], [], ["mail-2.7.0"] + end + it "raises an exception if a child dependency is not resolved" do @index = a_unresovable_child_index dep "chef_app_error" diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb index 5f6c515735..b76f493d01 100644 --- a/spec/support/indexes.rb +++ b/spec/support/indexes.rb @@ -66,6 +66,7 @@ module Spec search = Bundler::GemVersionPromoter.new(@locked, unlock).tap do |s| s.level = opts.first s.strict = opts.include?(:strict) + s.prerelease_specified = Hash[@deps.map {|d| [d.name, d.requirement.prerelease?] }] end should_resolve_and_include specs, [@base, search] end |