diff options
author | chrismo <chrismo@clabs.org> | 2016-06-21 11:58:42 -0500 |
---|---|---|
committer | chrismo <chrismo@clabs.org> | 2016-07-08 19:35:57 -0500 |
commit | 3630f18c8119d5b8534b72f9e6b32db6a7a5b533 (patch) | |
tree | 882af80a441b655883c1100bea4579551973609d | |
parent | bdc1df50535b15a9a263410dbe4789571a115ff5 (diff) | |
download | bundler-3630f18c8119d5b8534b72f9e6b32db6a7a5b533.tar.gz |
Port GemVersionPromoter specs from bundler-patch
-rw-r--r-- | lib/bundler/gem_version_promoter.rb | 4 | ||||
-rw-r--r-- | spec/bundler/gem_version_promoter_spec.rb | 155 |
2 files changed, 158 insertions, 1 deletions
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb index f89e8ca8a7..3bacd6002d 100644 --- a/lib/bundler/gem_version_promoter.rb +++ b/lib/bundler/gem_version_promoter.rb @@ -26,7 +26,8 @@ module Bundler end def sort_versions(dep, dep_specs) - before_result = "before sort_versions: #{debug_format_result(dep, dep_specs).inspect}" + # MODO Revisit env name - also see below + before_result = "before sort_versions: #{debug_format_result(dep, dep_specs).inspect}" if ENV["DEBUG_PATCH_RESOLVER"] result = @sort_versions[dep] ||= begin gem_name = dep.name @@ -46,6 +47,7 @@ module Bundler end end end + # MODO: flush out this problem by freezing it? result.dup # not ideal, but elsewhere in bundler the resulting array is occasionally emptied, corrupting the cache. end diff --git a/spec/bundler/gem_version_promoter_spec.rb b/spec/bundler/gem_version_promoter_spec.rb index e69de29bb2..c34de89bf3 100644 --- a/spec/bundler/gem_version_promoter_spec.rb +++ b/spec/bundler/gem_version_promoter_spec.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true +require "spec_helper" + +describe Bundler::GemVersionPromoter do + context "conservative resolver" do + def versions(result) + result.flatten.map(&:version).map(&:to_s) + end + + def make_instance(*args) + @gvp = Bundler::GemVersionPromoter.new(*args).tap do |gvp| + gvp.class.class_eval { public :filter_dep_specs, :sort_dep_specs } + end + end + + def unlocking(options = {}) + make_instance(Bundler::SpecSet.new([]), ["foo"]).tap do |p| + p.level = options[:level] if options[:level] + p.strict = options[:strict] if options[:strict] + p.minimal = options[:minimal] if options[:minimal] + end + end + + def keep_locked(options = {}) + make_instance(Bundler::SpecSet.new([]), ["bar"]).tap do |p| + p.level = options[:level] if options[:level] + p.strict = options[:strict] if options[:strict] + p.minimal = options[:minimal] if options[:minimal] + end + end + + def build_spec_group(name, version) + build_spec(name, version).map {|s| Array(s) } + end + + # Rightmost (highest array index) in result is most preferred. + # Leftmost (lowest array index) in result is least preferred. + # `build_spec_group` has all version of gem in index. + # `build_spec` is the version currently in the .lock file. + # + # In default (not strict) mode, all versions in the index will + # be returned, allowing Bundler the best chance to resolve all + # dependencies, but sometimes resulting in upgrades that some + # would not consider conservative. + context "filter specs (strict) (minor not allowed)" do + it "when keeping build_spec, keep current, next release" do + keep_locked(:level => :patch) + res = @gvp.filter_dep_specs( + build_spec_group("foo", %w(1.7.8 1.7.9 1.8.0)), + build_spec("foo", "1.7.8").first) + expect(versions(res)).to eq %w(1.7.9 1.7.8) + end + + it "when unlocking prefer next release first" do + unlocking + res = @gvp.filter_dep_specs( + build_spec_group("foo", %w(1.7.8 1.7.9 1.8.0)), + build_spec("foo", "1.7.8").first) + expect(versions(res)).to eq %w(1.7.8 1.7.9) + end + + it "when unlocking keep current when already at latest release" do + unlocking + res = @gvp.filter_dep_specs( + build_spec_group("foo", %w(1.7.9 1.8.0 2.0.0)), + build_spec("foo", "1.7.9").first) + expect(versions(res)).to eq %w(1.7.9) + end + end + + context "filter specs (strict) (minor preferred)" do + it "should have specs" + end + + context "sort specs (not strict) (minor not allowed)" do + it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do + keep_locked + res = @gvp.sort_dep_specs( + build_spec_group("foo", %w(1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1)), + build_spec("foo", "1.7.7").first) + expect(versions(res)).to eq %w(2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7) + end + + it "when unlocking favor next release, then current over minor increase" do + unlocking + res = @gvp.sort_dep_specs( + build_spec_group("foo", %w(1.7.7 1.7.8 1.7.9 1.8.0)), + build_spec("foo", "1.7.8").first) + expect(versions(res)).to eq %w(1.8.0 1.7.8 1.7.9) + end + + it "when unlocking do proper integer comparison, not string" do + unlocking + res = @gvp.sort_dep_specs( + build_spec_group("foo", %w(1.7.7 1.7.8 1.7.9 1.7.15 1.8.0)), + build_spec("foo", "1.7.8").first) + expect(versions(res)).to eq %w(1.8.0 1.7.8 1.7.9 1.7.15) + end + + it "leave current when unlocking but already at latest release" do + unlocking + res = @gvp.sort_dep_specs( + build_spec_group("foo", %w(1.7.9 1.8.0 2.0.0)), + build_spec("foo", "1.7.9").first) + expect(versions(res)).to eq %w(2.0.0 1.8.0 1.7.9) + end + + it "when prefer_minimal, and not updating this gem, order is strictly oldest to newest" do + keep_locked(:minimal => true) + versions = %w(1.7.5 1.7.8 1.7.9 1.8.0 2.0.0 2.1.0 3.0.0 3.0.1 3.1.0) + res = @gvp.sort_dep_specs( + build_spec_group("foo", versions), + build_spec("foo", "1.7.5").first) + expect(versions(res)).to eq versions.reverse + end + + it "when prefer_minimal, and updating this gem, order is oldest to newest except current" do + unlocking(:minimal => true) + versions = %w(1.7.5 1.7.8 1.7.9 1.8.0 2.0.0 2.1.0 3.0.0 3.0.1 3.1.0) + res = @gvp.sort_dep_specs( + build_spec_group("foo", versions), + build_spec("foo", "1.7.5").first) + expect(versions(res)).to eq %w(3.1.0 3.0.1 3.0.0 2.1.0 2.0.0 1.8.0 1.7.5 1.7.9 1.7.8) + end + end + + context "sort specs (not strict) (minor allowed)" do + it "when unlocking favor next release, then minor increase over current" do + unlocking(:level => :minor) + res = @gvp.sort_dep_specs( + build_spec_group("foo", %w(0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1)), + build_spec("foo", "0.2.0").first) + 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) + end + + it "new version specified" + + it "new version specified, prefer_minimal" + end + + context "caching search results" do + it "should dup the output to protect the cache" do + # Bundler will (somewhere) do this on occasion during a large resolution. + # Let's protect against it. + gvp = Bundler::GemVersionPromoter.new + + dep = Bundler::DepProxy.new(Gem::Dependency.new("foo", ">= 0"), "ruby") + sg = build_spec_group("foo", %w(2.4.0)) + res = gvp.sort_versions(dep, sg) + res.clear + expect(gvp.sort_versions(dep, sg)).to_not eq [] + end + end + end +end |