summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Giddins <segiddins@segiddins.me>2016-06-23 19:52:04 -0500
committerSamuel Giddins <segiddins@segiddins.me>2016-06-27 16:27:22 -0500
commit16e535493bcd6e5670b0bff8bcc84b03a01325fa (patch)
treeb4cee1e4f3fb64085c3ffb7d1c530a9b28dcc503
parentca01935f9a7e43ac8726e9244d468e8c516c7cb9 (diff)
downloadbundler-16e535493bcd6e5670b0bff8bcc84b03a01325fa.tar.gz
[Resolver] Pin transitive deps to relevant sources
-rw-r--r--lib/bundler/definition.rb5
-rw-r--r--lib/bundler/resolver.rb39
-rw-r--r--lib/bundler/rubygems_ext.rb2
-rw-r--r--lib/bundler/source_list.rb2
-rw-r--r--spec/install/gemfile/sources_spec.rb11
-rw-r--r--spec/lock/lockfile_spec.rb15
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