diff options
author | Samuel Giddins <segiddins@segiddins.me> | 2016-06-23 19:52:04 -0500 |
---|---|---|
committer | Samuel Giddins <segiddins@segiddins.me> | 2016-06-27 16:27:22 -0500 |
commit | 16e535493bcd6e5670b0bff8bcc84b03a01325fa (patch) | |
tree | b4cee1e4f3fb64085c3ffb7d1c530a9b28dcc503 | |
parent | ca01935f9a7e43ac8726e9244d468e8c516c7cb9 (diff) | |
download | bundler-16e535493bcd6e5670b0bff8bcc84b03a01325fa.tar.gz |
[Resolver] Pin transitive deps to relevant sources
-rw-r--r-- | lib/bundler/definition.rb | 5 | ||||
-rw-r--r-- | lib/bundler/resolver.rb | 39 | ||||
-rw-r--r-- | lib/bundler/rubygems_ext.rb | 2 | ||||
-rw-r--r-- | lib/bundler/source_list.rb | 2 | ||||
-rw-r--r-- | spec/install/gemfile/sources_spec.rb | 11 | ||||
-rw-r--r-- | spec/lock/lockfile_spec.rb | 15 |
6 files changed, 57 insertions, 17 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index cd3e25862d..654bb9a630 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -668,9 +668,10 @@ module Bundler # Record the specs available in each gem's source, so that those # specs will be available later when the resolver knows where to # look for that gemspec (or its dependencies) - source_requirements = {} + default = sources.rubygems_sources.last + source_requirements = { :default => default } dependencies.each do |dep| - next unless source = dep.source || sources.rubygems_global + next unless source = dep.source || default source_requirements[dep.name] = source end source_requirements diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index 0afd4b6944..33613c8d8f 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -54,11 +54,18 @@ module Bundler o << %(the gems in your #{SharedHelpers.gemfile_name}, which may resolve the conflict.\n) elsif !conflict.existing o << "\n" + relevant_sources = if conflict.requirement.source + [conflict.requirement.source] + elsif conflict.requirement.all_sources + conflict.requirement.all_sources + else + raise "no source set for #{conflict}" + end.compact.uniq if conflict.requirement_trees.first.size > 1 o << "Could not find gem '#{conflict.requirement}', which is required by " - o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the sources." + o << "gem '#{conflict.requirement_trees.first[-2]}', in any of the relevant sources:\n #{relevant_sources * "\n "}" else - o << "Could not find gem '#{conflict.requirement}' in any of the sources\n" + o << "Could not find gem '#{conflict.requirement}' in any of the relevant sources:\n #{relevant_sources * "\n "}" end end o @@ -259,8 +266,17 @@ module Bundler platform = dependency.__platform dependency = dependency.dep unless dependency.is_a? Gem::Dependency search = @search_for[dependency] ||= begin - source = @source_requirements[dependency.name] - index = (source && source.specs) || @index + index = Index.build do |idx| + if source = @source_requirements[dependency.name] + idx.add_source source.specs + elsif dependency.all_sources + dependency.all_sources.each {|s| idx.add_source(s.specs) if s } + else + idx.add_source @source_requirements[:default].specs + end + end + # source = @source_requirements[dependency.name] + # index = (source && source.specs) || @index results = index.search(dependency, @base[dependency.name]) if vertex = @base_dg.vertex_named(dependency.name) locked_requirement = vertex.payload.requirement @@ -304,8 +320,23 @@ module Bundler requirement.matches_spec?(spec) end + def relevant_sources_for_vertex(vertex) + if vertex.root? + [@source_requirements[vertex.name]] + else + vertex.recursive_predecessors.map do |v| + @source_requirements[v.name] + end << @source_requirements[:default] + end + end + + # def valid_source_for_spec?(spec, vertex) + # relevant_sources_for_vertex(vertex).include?(spec.source) + # end + def sort_dependencies(dependencies, activated, conflicts) dependencies.sort_by do |dependency| + dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name)) name = name_for(dependency) [ activated.vertex_named(name).payload ? 0 : 1, diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 2f36c29cd9..94f502ad51 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -112,7 +112,7 @@ module Gem end class Dependency - attr_accessor :source, :groups + attr_accessor :source, :groups, :all_sources alias_method :eql?, :== diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index a74ac61373..8a069d560f 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -34,7 +34,7 @@ module Bundler end def rubygems_sources - @rubygems_sources + [@rubygems_global || @rubygems_local].compact + @rubygems_sources + [@rubygems_global || @rubygems_local] end def rubygems_remotes diff --git a/spec/install/gemfile/sources_spec.rb b/spec/install/gemfile/sources_spec.rb index efe3c9a0b7..3daeb49f96 100644 --- a/spec/install/gemfile/sources_spec.rb +++ b/spec/install/gemfile/sources_spec.rb @@ -259,6 +259,7 @@ describe "bundle install with gems on multiple sources" do it "installs all gems without warning" do bundle :install expect(out).not_to include("Warning") + expect(err).not_to include("Warning") should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") end end @@ -273,8 +274,11 @@ describe "bundle install with gems on multiple sources" do end it "does not find the dependency" do - bundle :install - expect(out).to include("Could not find gem 'rack (>= 0) ruby'") + bundle :install, :expect_err => true + expect(err).to include strip_whitespace(<<-E).strip + Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources: + rubygems repository file:#{gem_repo2}/ or installed locally + E end end @@ -292,8 +296,9 @@ describe "bundle install with gems on multiple sources" do end it "installs the dependency from the top-level source without warning" do - bundle :install + bundle :install, :expect_err => true expect(out).not_to include("Warning") + expect(err).not_to include("Warning") should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0") end end diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb index 427e8fcbb5..478a1c2ff0 100644 --- a/spec/lock/lockfile_spec.rb +++ b/spec/lock/lockfile_spec.rb @@ -788,8 +788,9 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G - path "foo" - gem "foo" + path "foo" do + gem "foo" + end G lockfile_should_be <<-G @@ -813,8 +814,9 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app(File.join("..", "foo")) install_gemfile <<-G - path "../foo" - gem "foo" + path "../foo" do + gem "foo" + end G lockfile_should_be <<-G @@ -838,8 +840,9 @@ describe "the lockfile format" do build_lib "foo", :path => bundled_app("foo") install_gemfile <<-G - path File.expand_path("../foo", __FILE__) - gem "foo" + path File.expand_path("../foo", __FILE__) do + gem "foo" + end G lockfile_should_be <<-G |