summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBundlerbot <bot@bundler.io>2019-05-03 08:48:33 +0000
committerBundlerbot <bot@bundler.io>2019-05-03 08:48:33 +0000
commit9cc693b61cf13acb7a610692fd41d26a2caa768c (patch)
treec1a9bf9e3f71c5467028625bdf7a0ad2cc929338
parent8d2c4e8e6b51fbb4b3367b1eb2ee779579f21966 (diff)
parentf143b3744afd2293d340ea8c90601d3dc48e0b54 (diff)
downloadbundler-9cc693b61cf13acb7a610692fd41d26a2caa768c.tar.gz
Merge #7149
7149: Fix bundle update crash r=deivid-rodriguez a=deivid-rodriguez ### What was the end-user problem that led to this PR? The problem was that I introduced a regression with https://github.com/bundler/bundler/pull/6329. When running `bundle update <gem>`, where `<gem>` is included in the Gemfile, but it's for another platform from the current one, `bundle` would crash with the following error: ``` NoMethodError: undefined method `source' for nil:NilClass /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli/update.rb:86:in `block in run' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli/update.rb:78:in `each' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli/update.rb:78:in `run' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli.rb:280:in `block in update' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/settings.rb:129:in `temporary' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli.rb:279:in `update' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli.rb:26:in `dispatch' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/cli.rb:17:in `start' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/exe/bundle:21:in `block in <top (required)>' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors' /home/deivid/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bundler-2.1.0.pre.1/exe/bundle:13:in `<top (required)>' /home/deivid/.rbenv/versions/2.6.3/bin/bundle:23:in `load' /home/deivid/.rbenv/versions/2.6.3/bin/bundle:23:in `<main>' ``` ### What was your diagnosis of the problem? My diagnosis was that we can't always rely on the spec being updated not being `nil` in the definition. It can be `nil` for gems in excluded groups, or for gems included only for platforms different from the current one. ### What is your fix for the problem, implemented in this PR? My fix is to handle this case and show a proper error. ### Why did you choose this fix out of the possible options? I chose this fix because it's user friendly. Co-authored-by: David Rodríguez <deivid.rodriguez@riseup.net>
-rw-r--r--lib/bundler/cli/update.rb29
-rw-r--r--spec/commands/update_spec.rb35
2 files changed, 54 insertions, 10 deletions
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index 60ea1c2a80..afd386bd54 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -60,8 +60,8 @@ module Bundler
Bundler.definition.validate_runtime!
if locked_gems = Bundler.definition.locked_gems
- previous_locked_specs = locked_gems.specs.reduce({}) do |h, s|
- h[s.name] = { :version => s.version, :source => s.source.to_s }
+ previous_locked_info = locked_gems.specs.reduce({}) do |h, s|
+ h[s.name] = { :spec => s, :version => s.version, :source => s.source.to_s }
h
end
end
@@ -76,17 +76,26 @@ module Bundler
if locked_gems
gems.each do |name|
- locked_spec = previous_locked_specs[name]
- next unless locked_spec
- locked_source = locked_spec[:source]
- locked_version = locked_spec[:version]
+ locked_info = previous_locked_info[name]
+ next unless locked_info
+
+ locked_spec = locked_info[:spec]
new_spec = Bundler.definition.specs[name].first
+ unless new_spec
+ if Bundler.rubygems.platforms.none? {|p| locked_spec.match_platform(p) }
+ Bundler.ui.warn "Bundler attempted to update #{name} but it was not considered because it is for a different platform from the current one"
+ end
+
+ next
+ end
+
+ locked_source = locked_info[:source]
new_source = new_spec.source.to_s
- new_version = new_spec.version
next if locked_source != new_source
- if !new_version
- Bundler.ui.warn "Bundler attempted to update #{name} but it was removed from the bundle"
- elsif new_version < locked_version
+
+ new_version = new_spec.version
+ locked_version = locked_info[:version]
+ if new_version < locked_version
Bundler.ui.warn "Note: #{name} version regressed from #{locked_version} to #{new_version}"
elsif new_version == locked_version
Bundler.ui.warn "Bundler attempted to update #{name} but its version stayed the same"
diff --git a/spec/commands/update_spec.rb b/spec/commands/update_spec.rb
index 735d8cd8de..61a5a1d1f1 100644
--- a/spec/commands/update_spec.rb
+++ b/spec/commands/update_spec.rb
@@ -563,6 +563,41 @@ RSpec.describe "bundle update in more complicated situations" do
expect(the_bundle).to include_gem "a 1.1"
end
end
+
+ context "when the dependency is for a different platform" do
+ before do
+ build_repo4 do
+ build_gem("a", "0.9") {|s| s.platform = "java" }
+ build_gem("a", "1.1") {|s| s.platform = "java" }
+ end
+
+ gemfile <<-G
+ source "file://#{gem_repo4}"
+ gem "a", platform: :jruby
+ G
+
+ lockfile <<-L
+ GEM
+ remote: file://#{gem_repo4}
+ specs:
+ a (0.9-java)
+
+ PLATFORMS
+ java
+
+ DEPENDENCIES
+ a
+ L
+
+ simulate_platform linux
+ end
+
+ it "is not updated because it is not actually included in the bundle" do
+ bundle! "update a"
+ expect(last_command.stdboth).to include "Bundler attempted to update a but it was not considered because it is for a different platform from the current one"
+ expect(the_bundle).to_not include_gem "a"
+ end
+ end
end
RSpec.describe "bundle update without a Gemfile.lock" do