summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Giddins <segiddins@segiddins.me>2017-04-08 17:28:58 -0500
committerSamuel Giddins <segiddins@segiddins.me>2017-04-13 20:40:29 -0500
commitb05df750e92a2c12b0d47c0b9bff619bb024a0d5 (patch)
tree68715031276773dd0545d79610361ea56b7585a9
parentfe617daaaad4d4d3a48bcce90e39caff9145cfbb (diff)
downloadbundler-b05df750e92a2c12b0d47c0b9bff619bb024a0d5.tar.gz
Avoid deadlocking when installing with a lockfile missing dependencies
-rw-r--r--.rubocop_todo.yml21
-rw-r--r--lib/bundler/endpoint_specification.rb12
-rw-r--r--lib/bundler/lazy_specification.rb2
-rw-r--r--lib/bundler/remote_specification.rb8
-rw-r--r--lib/bundler/shared_helpers.rb15
-rw-r--r--spec/lock/lockfile_spec.rb23
6 files changed, 53 insertions, 28 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index d03086eab2..7d16768980 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2017-03-30 23:48:11 +0900 using RuboCop version 0.48.0.
+# on 2017-04-08 17:26:10 -0500 using RuboCop version 0.48.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -72,12 +72,12 @@ Lint/UselessAssignment:
- 'lib/bundler/index.rb'
- 'lib/bundler/installer.rb'
-# Offense count: 444
+# Offense count: 451
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
- Max: 980
+ Max: 988
-# Offense count: 1991
+# Offense count: 2035
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
@@ -141,7 +141,7 @@ Style/CaseEquality:
- 'lib/bundler/match_platform.rb'
- 'lib/bundler/rubygems_ext.rb'
-# Offense count: 24
+# Offense count: 25
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
@@ -163,11 +163,11 @@ Style/ConditionalAssignment:
- 'lib/bundler/source/git.rb'
- 'lib/bundler/source/rubygems.rb'
-# Offense count: 154
+# Offense count: 158
Style/Documentation:
Enabled: false
-# Offense count: 300
+# Offense count: 304
# Cop supports --auto-correct.
Style/EmptyLineAfterMagicComment:
Enabled: false
@@ -205,7 +205,7 @@ Style/GlobalVars:
- 'lib/bundler/cli.rb'
- 'spec/spec_helper.rb'
-# Offense count: 18
+# Offense count: 17
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Exclude:
@@ -217,7 +217,6 @@ Style/GuardClause:
- 'lib/bundler/definition.rb'
- 'lib/bundler/dsl.rb'
- 'lib/bundler/installer.rb'
- - 'lib/bundler/lockfile_parser.rb'
- 'lib/bundler/runtime.rb'
- 'lib/bundler/source/path/installer.rb'
- 'lib/bundler/source_list.rb'
@@ -241,14 +240,14 @@ Style/IfUnlessModifierOfIfUnless:
Style/IndentArray:
EnforcedStyle: consistent
-# Offense count: 33
+# Offense count: 34
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
Style/IndentHeredoc:
Enabled: false
-# Offense count: 8
+# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: InverseMethods, InverseBlocks.
Style/InverseMethods:
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 5e14f03265..1fb5b29732 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -5,8 +5,8 @@ module Bundler
ILLFORMED_MESSAGE = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'.freeze
include MatchPlatform
- attr_reader :name, :version, :platform, :dependencies, :required_rubygems_version, :required_ruby_version, :checksum
- attr_accessor :source, :remote
+ attr_reader :name, :version, :platform, :required_rubygems_version, :required_ruby_version, :checksum
+ attr_accessor :source, :remote, :dependencies
def initialize(name, version, platform, dependencies, metadata = nil)
@name = name
@@ -91,13 +91,7 @@ module Bundler
end
def __swap__(spec)
- without_type = proc {|d| Gem::Dependency.new(d.name, d.requirements_list.sort) }
- if (extra_deps = spec.runtime_dependencies.map(&without_type).-(dependencies.map(&without_type))) && extra_deps.any?
- Bundler.ui.debug "#{full_name} from #{remote} has corrupted API dependencies (API returned #{dependencies}, real spec has (#{spec.runtime_dependencies}))"
- raise APIResponseMismatchError,
- "Downloading #{full_name} revealed dependencies not in the API (#{extra_deps.map(&:to_s).join(", ")})." \
- "\nInstalling with `--full-index` should fix the problem."
- end
+ SharedHelpers.ensure_same_dependencies(spec, dependencies, spec.dependencies)
@remote_specification = spec
end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 46f50844e1..9a8268a2d5 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -79,7 +79,7 @@ module Bundler
"To use the platform-specific version of the gem, run `bundle config specific_platform true` and install again."
search = source.specs.search(self).last
end
- search.dependencies = dependencies if search.is_a?(RemoteSpecification)
+ search.dependencies = dependencies if search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)
search
end
end
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index 82b5cb8c6f..cd076939c4 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -51,13 +51,7 @@ module Bundler
# once the remote gem is downloaded, the backend specification will
# be swapped out.
def __swap__(spec)
- without_type = proc {|d| Gem::Dependency.new(d.name, d.requirements_list) }
- if (extra_deps = spec.runtime_dependencies.map(&without_type).-(dependencies.map(&without_type))) && extra_deps.any?
- Bundler.ui.debug "#{full_name} from #{remote} has corrupted API dependencies (API returned #{dependencies}, real spec has (#{spec.runtime_dependencies}))"
- raise APIResponseMismatchError,
- "Downloading #{full_name} revealed dependencies not in the API (#{extra_deps.map(&without_type).map(&:to_s).join(", ")})." \
- "\nInstalling with `--full-index` should fix the problem."
- end
+ SharedHelpers.ensure_same_dependencies(spec, dependencies, spec.dependencies)
@_remote_specification = spec
end
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 086624b383..cb8e142769 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -152,6 +152,21 @@ module Bundler
end
end
+ def ensure_same_dependencies(spec, old, new)
+ new = new.reject {|d| d.type == :development }
+ old = old.reject {|d| d.type == :development }
+
+ without_type = proc {|d| Gem::Dependency.new(d.name, d.requirements_list.sort) }
+ new.map!(&without_type)
+ old.map!(&without_type)
+
+ extra_deps = new - old
+ return if extra_deps.empty?
+ raise APIResponseMismatchError,
+ "Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.map(&:to_s).join(", ")})." \
+ "\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem."
+ end
+
private
def find_gemfile
diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb
index 7d768e337c..86a23dbe3d 100644
--- a/spec/lock/lockfile_spec.rb
+++ b/spec/lock/lockfile_spec.rb
@@ -1258,6 +1258,29 @@ RSpec.describe "the lockfile format" do
L
end
+ it "raises a helpful error message when the lockfile is missing deps" do
+ lockfile <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack_middleware (1.0)
+
+ PLATFORMS
+ #{local}
+
+ DEPENDENCIES
+ rack_middleware
+ L
+
+ install_gemfile <<-G
+ source "file:#{gem_repo1}"
+ gem "rack_middleware"
+ G
+
+ expect(out).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (rack (= 0.9.1)).").
+ and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
+ end
+
describe "a line ending" do
def set_lockfile_mtime_to_known_value
time = Time.local(2000, 1, 1, 0, 0, 0)