mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00

When printing sources inside these error messages, it's useful to only
consider the current state of the source. For example, when requiring
`bundler/setup`, the source shouldn't be configured to be able to hit
the network, so the error message should only mention "locally installed
gems" to make that more clear.
30eb14f853
68 lines
2.1 KiB
Ruby
68 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Bundler
|
|
class Source
|
|
class RubygemsAggregate
|
|
attr_reader :source_map, :sources
|
|
|
|
def initialize(sources, source_map)
|
|
@sources = sources
|
|
@source_map = source_map
|
|
|
|
@index = build_index
|
|
end
|
|
|
|
def specs
|
|
@index
|
|
end
|
|
|
|
def to_err
|
|
to_s
|
|
end
|
|
|
|
def to_s
|
|
"any of the sources"
|
|
end
|
|
|
|
private
|
|
|
|
def build_index
|
|
Index.build do |idx|
|
|
dependency_names = source_map.pinned_spec_names
|
|
|
|
sources.all_sources.each do |source|
|
|
source.dependency_names = dependency_names - source_map.pinned_spec_names(source)
|
|
idx.add_source source.specs
|
|
dependency_names.concat(source.unmet_deps).uniq!
|
|
end
|
|
|
|
double_check_for_index(idx, dependency_names)
|
|
end
|
|
end
|
|
|
|
# Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
|
|
# sources A and B. At this point, the API request will have found all the versions of Bar in source A,
|
|
# but will not have found any versions of Bar from source B, which is a problem if the requested version
|
|
# of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
|
|
# each spec we found, we add all possible versions from all sources to the index.
|
|
def double_check_for_index(idx, dependency_names)
|
|
pinned_names = source_map.pinned_spec_names
|
|
|
|
names = :names # do this so we only have to traverse to get dependency_names from the index once
|
|
unmet_dependency_names = lambda do
|
|
return names unless names == :names
|
|
new_names = sources.all_sources.map(&:dependency_names_to_double_check)
|
|
return names = nil if new_names.compact!
|
|
names = new_names.flatten(1).concat(dependency_names)
|
|
names.uniq!
|
|
names -= pinned_names
|
|
names
|
|
end
|
|
|
|
sources.all_sources.each do |source|
|
|
source.double_check_for(unmet_dependency_names)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|