SpecFetcher handles metadata updates from remote gem repositories.
Default fetcher instance. Use this instead of ::new to reduce object allocation.
# File rubygems/spec_fetcher.rb, line 41
def self.fetcher
@fetcher ||= new
end
Creates a new SpecFetcher. Ordinarily you want to use the default fetcher from ::fetcher which uses the Gem.sources.
If you need to retrieve specifications from a different
source, you can send it as an argument.
# File rubygems/spec_fetcher.rb, line 56
def initialize sources = nil
@sources = sources || Gem.sources
@update_cache =
begin
File.stat(Gem.user_home).uid == Process.uid
rescue Errno::EACCES, Errno::ENOENT
false
end
@specs = {}
@latest_specs = {}
@prerelease_specs = {}
@caches = {
:latest => @latest_specs,
:prerelease => @prerelease_specs,
:released => @specs,
}
@fetcher = Gem::RemoteFetcher.fetcher
end
Returns a list of gems available for each source in Gem.sources.
type can be one of 3 values: :released => Return the list
of all released specs :complete => Return the list of all specs
:latest => Return the list of only the highest version of each gem
:prerelease => Return the list of all prerelease only specs
# File rubygems/spec_fetcher.rb, line 218
def available_specs(type)
errors = []
list = {}
@sources.each_source do |source|
begin
names = case type
when :latest
tuples_for source, :latest
when :released
tuples_for source, :released
when :complete
names =
tuples_for(source, :prerelease, true) +
tuples_for(source, :released)
names.sort
when :abs_latest
names =
tuples_for(source, :prerelease, true) +
tuples_for(source, :latest)
names.sort
when :prerelease
tuples_for(source, :prerelease)
else
raise Gem::Exception, "Unknown type - :#{type}"
end
rescue Gem::RemoteFetcher::FetchError => e
errors << Gem::SourceFetchProblem.new(source, e)
else
list[source] = names
end
end
[list, errors]
end
Return all gem name tuples who’s names match obj
# File rubygems/spec_fetcher.rb, line 144
def detect(type=:complete)
tuples = []
list, _ = available_specs(type)
list.each do |source, specs|
specs.each do |tup|
if yield(tup)
tuples << [tup, source]
end
end
end
tuples
end
Find and fetch gem name tuples that match dependency.
If matching_platform is false, gems for all platforms are
returned.
# File rubygems/spec_fetcher.rb, line 85
def search_for_dependency(dependency, matching_platform=true)
found = {}
rejected_specs = {}
if dependency.prerelease?
if dependency.specific?
type = :complete
else
type = :abs_latest
end
elsif dependency.latest_version?
type = :latest
else
type = :released
end
list, errors = available_specs(type)
list.each do |source, specs|
if dependency.name.is_a?(String) && specs.respond_to?(:bsearch)
start_index = (0 ... specs.length).bsearch{ |i| specs[i].name >= dependency.name }
end_index = (0 ... specs.length).bsearch{ |i| specs[i].name > dependency.name }
specs = specs[start_index ... end_index] if start_index && end_index
end
found[source] = specs.select do |tup|
if dependency.match?(tup)
if matching_platform and !Gem::Platform.match(tup.platform)
pm = (
rejected_specs[dependency] ||= Gem::PlatformMismatch.new(tup.name, tup.version))
pm.add_platform tup.platform
false
else
true
end
end
end
end
errors += rejected_specs.values
tuples = []
found.each do |source, specs|
specs.each do |s|
tuples << [s, source]
end
end
tuples = tuples.sort_by { |x| x[0] }
return [tuples, errors]
end
Find and fetch specs that match dependency.
If matching_platform is false, gems for all platforms are
returned.
# File rubygems/spec_fetcher.rb, line 165
def spec_for_dependency(dependency, matching_platform=true)
tuples, errors = search_for_dependency(dependency, matching_platform)
specs = []
tuples.each do |tup, source|
begin
spec = source.fetch_spec(tup)
rescue Gem::RemoteFetcher::FetchError => e
errors << Gem::SourceFetchProblem.new(source, e)
else
specs << [spec, source]
end
end
return [specs, errors]
end
Suggests gems based on the supplied gem_name. Returns an array
of alternative gem names.
# File rubygems/spec_fetcher.rb, line 186
def suggest_gems_from_name gem_name
gem_name = gem_name.downcase.tr('_-', '')
max = gem_name.size / 2
names = available_specs(:latest).first.values.flatten(1)
matches = names.map { |n|
next unless n.match_platform?
distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '')
next if distance >= max
return [n.name] if distance == 0
[n.name, distance]
}.compact
matches = matches.uniq.sort_by { |name, dist| dist }
matches.first(5).map { |name, dist| name }
end
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.