diff options
Diffstat (limited to 'lib/bundler/resolver.rb')
-rw-r--r-- | lib/bundler/resolver.rb | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index 0c11c83b72..585b8667ad 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -17,14 +17,15 @@ 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, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) + def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil) base = SpecSet.new(base) unless base.is_a?(SpecSet) - resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) + resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) result = resolver.start(requirements) SpecSet.new(result) end - def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) + def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms) + @index = index @source_requirements = source_requirements @base = base @resolver = Molinillo::Resolver.new(self, self) @@ -39,7 +40,7 @@ module Bundler @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY] @gem_version_promoter = gem_version_promoter @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major? - @no_aggregate_global_source = @source_requirements[:global].nil? + @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource? @variant_specific_names = [] @generic_names = ["Ruby\0", "RubyGems\0"] @@ -124,7 +125,8 @@ module Bundler dependency = dependency_proxy.dep name = dependency.name search_result = @search_for[dependency_proxy] ||= begin - results = results_for(dependency, @base[name]) + index = index_for(dependency) + results = index.search(dependency, @base[name]) if vertex = @base_dg.vertex_named(name) locked_requirement = vertex.payload.requirement @@ -193,26 +195,23 @@ module Bundler search_result end - def index_for(dependency, base) + def index_for(dependency) source = @source_requirements[dependency.name] if source source.specs - elsif @no_aggregate_global_source - dependency.all_sources.find(-> { Index.new }) do |s| - idx = s.specs - results = idx.search(dependency, base) - next if results.empty? || results == base - return idx + elsif @lockfile_uses_separate_rubygems_sources + Index.build do |idx| + if 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 else - @source_requirements[:global] + @index end end - def results_for(dependency, base) - index_for(dependency, base).search(dependency, base) - end - def name_for(dependency) dependency.name end @@ -239,13 +238,11 @@ module Bundler def relevant_sources_for_vertex(vertex) if vertex.root? - [@source_requirements[vertex.name]].compact - elsif @no_aggregate_global_source + [@source_requirements[vertex.name]] + elsif @lockfile_uses_separate_rubygems_sources vertex.recursive_predecessors.map do |v| @source_requirements[v.name] - end.compact << @source_requirements[:default] - else - [] + end << @source_requirements[:default] end end @@ -286,7 +283,7 @@ module Bundler if (base = @base[dependency.name]) && !base.empty? dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1 else - all = index_for(dependency, base).search(dependency.name).size + all = index_for(dependency).search(dependency.name).size if all <= 1 all - 1_000_000 @@ -329,7 +326,7 @@ module Bundler "The source does not contain any versions of '#{name}'" end else - message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \ + message = "Could not find gem '#{requirement}' in any of the gem sources " \ "listed in your Gemfile#{cache_message}." end raise GemNotFound, message @@ -414,8 +411,14 @@ module Bundler relevant_sources = if conflict.requirement.source [conflict.requirement.source] - else + elsif conflict.requirement.all_sources conflict.requirement.all_sources + elsif @lockfile_uses_separate_rubygems_sources + # every conflict should have an explicit group of sources when we + # enforce strict pinning + raise "no source set for #{conflict}" + else + [] end.compact.map(&:to_s).uniq.sort metadata_requirement = name.end_with?("\0") @@ -452,8 +455,7 @@ module Bundler def validate_resolved_specs!(resolved_specs) resolved_specs.each do |v| name = v.name - sources = relevant_sources_for_vertex(v) - next unless sources.any? + next unless sources = relevant_sources_for_vertex(v) sources.compact! if default_index = sources.index(@source_requirements[:default]) sources.delete_at(default_index) @@ -462,12 +464,14 @@ module Bundler sources.uniq! next if sources.size <= 1 + multisource_disabled = Bundler.feature_flag.disable_multisource? + msg = ["The gem '#{name}' was found in multiple relevant sources."] msg.concat sources.map {|s| " * #{s}" }.sort - msg << "You #{@no_aggregate_global_source ? :must : :should} add this gem to the source block for the source you wish it to be installed from." + msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from." msg = msg.join("\n") - raise SecurityError, msg if @no_aggregate_global_source + raise SecurityError, msg if multisource_disabled Bundler.ui.warn "Warning: #{msg}" end end |