summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchrismo <chrismo@clabs.org>2016-06-21 17:25:22 -0500
committerchrismo <chrismo@clabs.org>2016-07-08 19:35:57 -0500
commit3d3aeda062896d71396e9529decc60acf15f108b (patch)
treef069c7ac9c4903b5bea9dfad6a0de61e9bcf6641
parent3630f18c8119d5b8534b72f9e6b32db6a7a5b533 (diff)
downloadbundler-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.rb4
-rw-r--r--lib/bundler/resolver.rb1
-rw-r--r--spec/commands/update_spec.rb9
-rw-r--r--spec/resolver/basic_spec.rb50
-rw-r--r--spec/support/indexes.rb4
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