diff options
author | André Arko <andre@arko.net> | 2013-07-29 10:35:25 -0700 |
---|---|---|
committer | André Arko <andre@arko.net> | 2013-07-29 10:35:25 -0700 |
commit | 6608516a379d6cd4bd2b35c8b913b6c284197e00 (patch) | |
tree | 1379403af7549ef9e9b7495b8115604153cb9c88 | |
parent | 899a250984b4d248955a56948bd6e05423248df3 (diff) | |
parent | 5024238df342b791d3c19b1448c7a797615cc938 (diff) | |
download | bundler-6608516a379d6cd4bd2b35c8b913b6c284197e00.tar.gz |
Merge pull request #2564 from bundler/detect-cyclic-dependency
Raise user friendly errors in case of Cyclic Dependency
-rw-r--r-- | lib/bundler.rb | 31 | ||||
-rw-r--r-- | lib/bundler/spec_set.rb | 17 | ||||
-rw-r--r-- | spec/resolver/basic_spec.rb | 11 | ||||
-rw-r--r-- | spec/support/indexes.rb | 18 |
4 files changed, 61 insertions, 16 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index 5ab56154ae..cfc645b75e 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -50,21 +50,22 @@ module Bundler end end - class GemfileNotFound < BundlerError; status_code(10) ; end - class GemNotFound < BundlerError; status_code(7) ; end - class GemfileError < BundlerError; status_code(4) ; end - class InstallError < BundlerError; status_code(5) ; end - class InstallHookError < BundlerError; status_code(6) ; end - class PathError < BundlerError; status_code(13) ; end - class GitError < BundlerError; status_code(11) ; end - class DeprecatedError < BundlerError; status_code(12) ; end - class GemspecError < BundlerError; status_code(14) ; end - class InvalidOption < BundlerError; status_code(15) ; end - class ProductionError < BundlerError; status_code(16) ; end - class HTTPError < BundlerError; status_code(17) ; end - class RubyVersionMismatch < BundlerError; status_code(18) ; end - class SecurityError < BundlerError; status_code(19) ; end - class LockfileError < BundlerError; status_code(20) ; end + class GemfileNotFound < BundlerError; status_code(10) ; end + class GemNotFound < BundlerError; status_code(7) ; end + class GemfileError < BundlerError; status_code(4) ; end + class InstallError < BundlerError; status_code(5) ; end + class InstallHookError < BundlerError; status_code(6) ; end + class PathError < BundlerError; status_code(13) ; end + class GitError < BundlerError; status_code(11) ; end + class DeprecatedError < BundlerError; status_code(12) ; end + class GemspecError < BundlerError; status_code(14) ; end + class InvalidOption < BundlerError; status_code(15) ; end + class ProductionError < BundlerError; status_code(16) ; end + class HTTPError < BundlerError; status_code(17) ; end + class RubyVersionMismatch < BundlerError; status_code(18) ; end + class SecurityError < BundlerError; status_code(19) ; end + class LockfileError < BundlerError; status_code(20) ; end + class CyclicDependencyError < BundlerError; status_code(21) ; end # Internal errors, should be rescued class VersionConflict < BundlerError diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 2cdffdc83f..1746f6d0df 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -109,7 +109,22 @@ module Bundler def sorted rake = @specs.find { |s| s.name == 'rake' } - @sorted ||= ([rake] + tsort).compact.uniq + begin + @sorted ||= ([rake] + tsort).compact.uniq + rescue TSort::Cyclic => error + cgems = extract_circular_gems(error) + raise CyclicDependencyError, "Your Gemfile requires gems that depend" \ + " depend on each other, creating an infinite loop. Please remove" \ + " either gem '#{cgems[1]}' or gem '#{cgems[0]}' and try again." + end + end + + def extract_circular_gems(error) + if Bundler.current_ruby.mri? && Bundler.current_ruby.on_19? + error.message.scan(/(\w+) \([^)]/).flatten + else + error.message.scan(/@name="(.*?)"/).flatten + end end def lookup diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb index d675f4435f..22dc2f0fbe 100644 --- a/spec/resolver/basic_spec.rb +++ b/spec/resolver/basic_spec.rb @@ -23,4 +23,15 @@ describe "Resolving" do dep "my_app" should_resolve_as %w(activemodel-3.2.11 builder-3.0.4 grape-0.2.6 my_app-1.0.0) end + + it "should throw error in case of circular dependencies" do + @index = a_circular_index + dep "circular_app" + + got = resolve + expect { + got = got.map { |s| s.full_name }.sort + }.to raise_error(Bundler::CyclicDependencyError, /please remove either gem 'foo' or gem 'bar'/i) + end + end diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb index 2ca67a637a..418f7f32db 100644 --- a/spec/support/indexes.rb +++ b/spec/support/indexes.rb @@ -130,5 +130,23 @@ module Spec end end end + + def a_circular_index + build_index do + gem "rack", "1.0.1" + gem("foo", '0.2.6') do + dep "bar", ">= 0" + end + + gem("bar", "1.0.0") do + dep "foo", ">= 0" + end + + gem("circular_app", '1.0.0') do + dep "foo", ">= 0" + dep "bar", ">= 0" + end + end + end end end |