diff options
author | chrismo <chrismo@clabs.org> | 2016-06-21 17:25:22 -0500 |
---|---|---|
committer | chrismo <chrismo@clabs.org> | 2016-07-08 19:35:57 -0500 |
commit | 3d3aeda062896d71396e9529decc60acf15f108b (patch) | |
tree | f069c7ac9c4903b5bea9dfad6a0de61e9bcf6641 | |
parent | 3630f18c8119d5b8534b72f9e6b32db6a7a5b533 (diff) | |
download | bundler-3d3aeda062896d71396e9529decc60acf15f108b.tar.gz |
Clarified changing dependency specs.
A couple of confusing cases that should be clearer now and the
differences called out. Details in the spec code and comments.
Plus some MODO additions and other pending spec additions.
-rw-r--r-- | lib/bundler/cli.rb | 4 | ||||
-rw-r--r-- | lib/bundler/resolver.rb | 1 | ||||
-rw-r--r-- | spec/commands/update_spec.rb | 9 | ||||
-rw-r--r-- | spec/resolver/basic_spec.rb | 50 | ||||
-rw-r--r-- | spec/support/indexes.rb | 4 |
5 files changed, 48 insertions, 20 deletions
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 3c1521bed1..0d3c3d53e4 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -208,12 +208,16 @@ module Bundler "Update ruby specified in Gemfile.lock" method_option "bundler", :type => :string, :lazy_default => "> 0.a", :banner => "Update the locked version of bundler" + + # MODO: hide these from help to release undocumented? method_option "patch", :type => :boolean, :banner => "Prefer updating only to next patch version" 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)" + method_option "strict", :type => :boolean, :banner => + "Do not allow any gem to be updated past latest --patch/--minor/--major" def update(*gems) require "bundler/cli/update" Update.new(options, gems).run diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index e687b86216..77a17aeed3 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -270,6 +270,7 @@ module Bundler end platform_results = search.select {|sg| sg.for?(platform, @ruby_version) }.each {|sg| sg.activate_platform!(platform) } return platform_results if @gem_version_promoter.level == :major # default behavior + # MODO: put this inside the cache @gem_version_promoter.sort_versions(dependency, platform_results) end diff --git a/spec/commands/update_spec.rb b/spec/commands/update_spec.rb index 4e6e6df20b..cd23c4891d 100644 --- a/spec/commands/update_spec.rb +++ b/spec/commands/update_spec.rb @@ -426,6 +426,7 @@ describe "bundle update --ruby" do end end +# these specs are slow and focus on integration and therefore are not exhaustive. unit specs elsewhere handle that. describe "bundle update conservative" do context "patch preferred" do it "single gem without dependencies name specified" do @@ -443,7 +444,6 @@ describe "bundle update conservative" do gem 'foo' G - # bundle "update --patch foo", {:env => {'DEBUG_PATCH_RESOLVER' => true}} bundle "update --patch foo" should_be_installed "foo 1.0.1" @@ -464,14 +464,16 @@ describe "bundle update conservative" do gem 'foo' G - # bundle "update --patch foo", {:env => {'DEBUG_PATCH_RESOLVER' => true}} bundle "update --patch" should_be_installed "foo 1.0.1" end + + it "warns on minor or major increment elsewhere" end context "minor preferred" do + it "warns on major increment elsewhere" end context "strict" do @@ -481,5 +483,8 @@ describe "bundle update conservative" do end context "dry run" do + it "should show what would happen" + + it "should replace/be the same as what outdated shows" end end diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb index 41b9f8c84b..d65bab49ac 100644 --- a/spec/resolver/basic_spec.rb +++ b/spec/resolver/basic_spec.rb @@ -117,69 +117,87 @@ describe "Resolving" do end dep "foo" + # base represents declared dependencies in the Gemfile that are still satisfied by the lockfile + @base = Bundler::SpecSet.new([]) + + # locked represents versions in lockfile @locked = locked(%w(foo 1.4.3), %w(bar 2.0.3)) end it "resolves all gems to latest patch" do # strict is not set, so bar goes up a minor version due to dependency from foo 1.4.5 - should_consv_resolve_and_include :patch, [], %w(foo-1.4.5 bar-2.1.1) + should_conservative_resolve_and_include :patch, [], %w(foo-1.4.5 bar-2.1.1) end it "resolves all gems to latest patch strict" do # strict is set, so foo can only go up to 1.4.4 to avoid bar going up a minor version, and bar can go up to 2.0.5 - should_consv_resolve_and_include [:patch, :strict], [], %w(foo-1.4.4 bar-2.0.5) + should_conservative_resolve_and_include [:patch, :strict], [], %w(foo-1.4.4 bar-2.0.5) end it "resolves all gems to latest patch minimal" do + # MODO: remove minimal # minimal is set, so foo goes up the next available to 1.4.4 and bar goes up to next available 2.0.4 - should_consv_resolve_and_include [:patch, :minimal], [], %w(foo-1.4.4 bar-2.0.4) + should_conservative_resolve_and_include [:patch, :minimal], [], %w(foo-1.4.4 bar-2.0.4) end it "resolves foo only to latest patch - same dependency case" do @locked = locked(%w(foo 1.3.7), %w(bar 2.0.3)) # bar is locked, and the lock holds here because the dependency on bar doesn't change on the matching foo version. - should_consv_resolve_and_include :patch, ["foo"], %w(foo-1.3.8 bar-2.0.3) + should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.3.8 bar-2.0.3) + end + + it "resolves foo only to latest patch - changing dependency not declared case" do + # foo is the only gem being requested for update, therefore bar is locked, but bar is NOT + # declared as a dependency in the Gemfile. In this case, locks don't apply to _changing_ + # dependencies and since the dependency of the selected foo gem changes, the latest matching + # dependency of "bar", "~> 2.1" -- bar-2.1.1 -- is selected. This is not a bug and follows + # the long-standing documented Conservative Updating behavior of bundle install. + # http://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING + should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.4.5 bar-2.1.1) end - it "resolves foo only to latest patch - changing dependency case" do - # bar is locked, but locks don't apply to _changing_ dependencies and since the dependency of the - # selected foo gem changes, the latest matching of bar-2.1.1 - # (this could be considered a bug, but possibly hard to solve for) - should_consv_resolve_and_include :patch, ["foo"], %w(foo-1.4.5 bar-2.1.1) + it "resolves foo only to latest patch - changing dependency declared case" do + # bar is locked AND a declared dependency in the Gemfile, so it will not move, and therefore + # foo can only move up to 1.4.4. + @base << build_spec("bar", "2.0.3").first + should_conservative_resolve_and_include :patch, ["foo"], %w(foo-1.4.4 bar-2.0.3) end it "resolves foo only to latest patch strict" do # adding strict helps solve the possibly unexpected behavior of bar changing in the prior test case, # because no versions will be returned for bar ~> 2.1, so the engine falls back to ~> 2.0 (turn on # debugging to see this happen). - should_consv_resolve_and_include [:patch, :strict], ["foo"], %w(foo-1.4.4 bar-2.0.3) + should_conservative_resolve_and_include [:patch, :strict], ["foo"], %w(foo-1.4.4 bar-2.0.3) end it "resolves bar only to latest patch" do # bar is locked, so foo can only go up to 1.4.4 - should_consv_resolve_and_include :patch, ["bar"], %w(foo-1.4.3 bar-2.0.5) + should_conservative_resolve_and_include :patch, ["bar"], %w(foo-1.4.3 bar-2.0.5) end it "resolves all gems to latest minor" do # strict is not set, so bar goes up a major version due to dependency from foo 1.4.5 - should_consv_resolve_and_include :minor, [], %w(foo-1.5.1 bar-3.0.0) + should_conservative_resolve_and_include :minor, [], %w(foo-1.5.1 bar-3.0.0) end it "resolves all gems to latest minor strict" do # strict is set, so foo can only go up to 1.5.0 to avoid bar going up a major version - should_consv_resolve_and_include [:minor, :strict], [], %w(foo-1.5.0 bar-2.1.1) + should_conservative_resolve_and_include [:minor, :strict], [], %w(foo-1.5.0 bar-2.1.1) end it "resolves all gems to latest minor minimal" do + # MODO: remove minimal # minimal is set, and it takes precedence over minor. not sure what is the PoLS in this case. Not sure # if minimal is a great option in the first place. It exists to help a case where there are many, many # versions and I'd rather go from 1.0.2 to 1.0.3 instead of 1.0.45. But, we could consider killing the # minimal option altogether. If that's what you need, use the Gemfile dependency. - should_consv_resolve_and_include [:minor, :minimal], [], %w(foo-1.4.4 bar-2.0.4) + should_conservative_resolve_and_include [:minor, :minimal], [], %w(foo-1.4.4 bar-2.0.4) end - it "will not revert to a previous version" - it "has taken care of all MODOs" + it "could revert to a previous version" + + it "will not revert to a previous version in strict mode" + it "bring over all sort/filter specs from bundler-patch" end end diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb index 7de62eefeb..59ee91ca52 100644 --- a/spec/support/indexes.rb +++ b/spec/support/indexes.rb @@ -55,7 +55,7 @@ module Spec end) end - def should_consv_resolve_and_include(opts, unlock, specs) + def should_conservative_resolve_and_include(opts, unlock, specs) # empty unlock means unlock all opts = Array(opts) search = Bundler::GemVersionPromoter.new(@locked, unlock).tap do |s| @@ -63,7 +63,7 @@ module Spec s.strict = opts.include?(:strict) s.minimal = opts.include?(:minimal) end - should_resolve_and_include specs, [{}, [], nil, search] + should_resolve_and_include specs, [{}, @base, nil, search] end def an_awesome_index |