summaryrefslogtreecommitdiff
path: root/lib/bundler/resolver.rb
diff options
context:
space:
mode:
authorDiego Steiner <diego.steiner@renuo.ch>2016-09-27 14:07:35 +0200
committerDiego Steiner <diego.steiner@renuo.ch>2016-09-27 14:07:35 +0200
commitf809209b0c13a48a6da75692483bb51cf3ac0342 (patch)
tree37ca2dd297079ef5b91faefc423cd1b997d3991f /lib/bundler/resolver.rb
parent14c1a12b711878c7d7d7f360cb70c9398496b018 (diff)
parent121ada2a1842ebe9989f35567e2dd829ec06b7a1 (diff)
downloadbundler-f809209b0c13a48a6da75692483bb51cf3ac0342.tar.gz
Merge remote-tracking branch 'origin/master' into 4854-gemnotfound-error
Diffstat (limited to 'lib/bundler/resolver.rb')
-rw-r--r--lib/bundler/resolver.rb102
1 files changed, 54 insertions, 48 deletions
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 81537baf24..e636e1f815 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -66,48 +66,39 @@ module Bundler
end
end
- ALL = Bundler::Dependency::PLATFORM_MAP.values.uniq.freeze
-
class SpecGroup < Array
include GemHelpers
- attr_reader :activated, :required_by
+ attr_reader :activated
def initialize(a)
super
- @required_by = []
- @activated = []
+ @required_by = []
+ @activated_platforms = []
@dependencies = nil
- @specs = {}
-
- ALL.each do |p|
- @specs[p] = reverse.find {|s| s.match_platform(p) }
+ @specs = Hash.new do |specs, platform|
+ specs[platform] = select_best_platform_match(self, platform)
end
end
def initialize_copy(o)
super
- @required_by = o.required_by.dup
- @activated = o.activated.dup
+ @activated_platforms = o.activated.dup
end
def to_specs
- specs = {}
-
- @activated.each do |p|
+ @activated_platforms.map do |p|
next unless s = @specs[p]
- platform = generic(Gem::Platform.new(s.platform))
- next if specs[platform]
-
- lazy_spec = LazySpecification.new(name, version, platform, source)
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
lazy_spec.dependencies.replace s.dependencies
- specs[platform] = lazy_spec
- end
- specs.values
+ lazy_spec
+ end.compact
end
def activate_platform!(platform)
- @activated << platform if !@activated.include?(platform) && for?(platform, nil)
+ return unless for?(platform)
+ return if @activated_platforms.include?(platform)
+ @activated_platforms << platform
end
def name
@@ -122,17 +113,9 @@ module Bundler
@source ||= first.source
end
- def for?(platform, ruby_version)
+ def for?(platform)
spec = @specs[platform]
- return false unless spec
-
- return true if ruby_version.nil?
- # Only allow endpoint specifications since they won't hit the network to
- # fetch the full gemspec when calling required_ruby_version
- return true if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
- return true if spec.required_ruby_version.nil?
-
- spec.required_ruby_version.satisfied_by?(ruby_version.to_gem_version_with_patchlevel)
+ !spec.nil?
end
def to_s
@@ -140,7 +123,11 @@ module Bundler
end
def dependencies_for_activated_platforms
- @activated.map {|p| __dependencies[p] }.flatten
+ dependencies = @activated_platforms.map {|p| __dependencies[p] }
+ metadata_dependencies = @activated_platforms.map do |platform|
+ metadata_dependencies(@specs[platform], platform)
+ end
+ dependencies.concat(metadata_dependencies).flatten
end
def platforms_for_dependency_named(dependency)
@@ -150,18 +137,31 @@ module Bundler
private
def __dependencies
- @dependencies ||= begin
- dependencies = {}
- ALL.each do |p|
- next unless spec = @specs[p]
- dependencies[p] = []
+ @dependencies = Hash.new do |dependencies, platform|
+ dependencies[platform] = []
+ if spec = @specs[platform]
spec.dependencies.each do |dep|
next if dep.type == :development
- dependencies[p] << DepProxy.new(dep, p)
+ dependencies[platform] << DepProxy.new(dep, platform)
end
end
- dependencies
+ dependencies[platform]
+ end
+ end
+
+ def metadata_dependencies(spec, platform)
+ return [] unless spec
+ # Only allow endpoint specifications since they won't hit the network to
+ # fetch the full gemspec when calling required_ruby_version
+ return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
+ dependencies = []
+ if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
+ dependencies << DepProxy.new(Gem::Dependency.new("ruby\0", spec.required_ruby_version), platform)
end
+ if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
+ dependencies << DepProxy.new(Gem::Dependency.new("rubygems\0", spec.required_rubygems_version), platform)
+ end
+ dependencies
end
end
@@ -175,29 +175,34 @@ module Bundler
# ==== Returns
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
# collection of gemspecs is returned. Otherwise, nil is returned.
- def self.resolve(requirements, index, source_requirements = {}, base = [], ruby_version = nil, gem_version_promoter = GemVersionPromoter.new)
+ def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [])
base = SpecSet.new(base) unless base.is_a?(SpecSet)
- resolver = new(index, source_requirements, base, ruby_version, gem_version_promoter)
+ resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements)
result = resolver.start(requirements)
SpecSet.new(result)
end
- def initialize(index, source_requirements, base, ruby_version, gem_version_promoter)
+ def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements)
@index = index
@source_requirements = source_requirements
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
- @base.each {|ls| @base_dg.add_vertex(ls.name, Dependency.new(ls.name, ls.version), true) }
- @ruby_version = ruby_version
+ @base.each do |ls|
+ dep = Dependency.new(ls.name, ls.version)
+ @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
+ end
+ additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
@gem_version_promoter = gem_version_promoter
end
def start(requirements)
verify_gemfile_dependencies_are_found!(requirements)
dg = @resolver.resolve(requirements, @base_dg)
- dg.map(&:payload).map(&:to_specs).flatten
+ dg.map(&:payload).
+ reject {|sg| sg.name.end_with?("\0") }.
+ map(&:to_specs).flatten
rescue Molinillo::VersionConflict => e
raise VersionConflict.new(e.conflicts.keys.uniq, e.message)
rescue Molinillo::CircularDependencyError => e
@@ -278,7 +283,7 @@ module Bundler
@gem_version_promoter.sort_versions(dependency, spec_groups)
end
end
- search.select {|sg| sg.for?(platform, @ruby_version) }.each {|sg| sg.activate_platform!(platform) }
+ search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) }
end
def index_for(dependency)
@@ -302,7 +307,8 @@ module Bundler
end
def requirement_satisfied_by?(requirement, activated, spec)
- requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
+ return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
+ spec.activate_platform!(requirement.__platform) || spec.for?(requirement.__platform)
end
def sort_dependencies(dependencies, activated, conflicts)