Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more
The SourceIndex object indexes all the gems available from a particular source (e.g. a list of gem directories, or a remote source). A SourceIndex maps a gem full name to a gem specification.
The class used to be named Cache, but that became confusing when cached source fetchers where introduced. The constant Gem::Cache is an alias for this class to allow old YAMLized source index objects to load properly.
Creates a new SourceIndex from the ruby format gem specifications in
spec_dirs.
# File rubygems/source_index.rb, line 66
def self.from_gems_in(*spec_dirs)
new spec_dirs
end
Factory method to construct a source index instance for a given path.
If supplied, ::from_installed_gems
will act just like from_gems_in. This argument is deprecated
and is provided just for backwards compatibility, and should not generally
be used.
SourceIndex instance
# File rubygems/source_index.rb, line 45
def self.from_installed_gems(*deprecated)
if deprecated.empty?
from_gems_in(*installed_spec_directories)
else
warn "NOTE: from_installed_gems(arg) is deprecated. From #{caller.first}"
from_gems_in(*deprecated) # HACK warn
end
end
Returns a list of directories from Gem.path that contain specifications.
# File rubygems/source_index.rb, line 57
def self.installed_spec_directories
# TODO: move to Gem::Utils
Gem.path.collect { |dir| File.join(dir, "specifications") }
end
Loads a ruby-format specification from file_name and returns
the loaded spec.
# File rubygems/source_index.rb, line 74
def self.load_specification(file_name)
Gem::Deprecate.skip_during do
Gem::Specification.load Gem::Path.new(file_name)
end
end
Constructs a source index instance from the provided specifications, which is a Hash of gem full names and Gem::Specifications.
# File rubygems/source_index.rb, line 84
def initialize specs_or_dirs = []
@gems = {}
@spec_dirs = nil
case specs_or_dirs
when Hash then
specs_or_dirs.each do |full_name, spec|
add_spec spec
end
when Array, String then
self.spec_dirs = Array(specs_or_dirs)
refresh!
else
arg = specs_or_dirs.inspect
warn "NOTE: SourceIndex.new(#{arg}) is deprecated; From #{caller.first}."
end
end
Add a gem specification to the source index.
# File rubygems/source_index.rb, line 186
def add_spec(gem_spec, name = gem_spec.full_name)
# No idea why, but the Indexer wants to insert them using original_name
# instead of full_name. So we make it an optional arg.
@gems[name] = gem_spec
end
Add gem specifications to the source index.
# File rubygems/source_index.rb, line 195
def add_specs(*gem_specs)
Gem::Deprecate.skip_during do
gem_specs.each do |spec|
add_spec spec
end
end
end
# File rubygems/source_index.rb, line 350
def dump
Marshal.dump(self)
end
Iterate over the specifications in the source index.
# File rubygems/source_index.rb, line 213
def each(&block) # :yields: gem.full_name, gem
@gems.each(&block)
end
Find a gem by an exact match on the short name.
# File rubygems/source_index.rb, line 251
def find_name(gem_name, requirement = Gem::Requirement.default)
dep = Gem::Dependency.new gem_name, requirement
Gem::Deprecate.skip_during do
search dep
end
end
The signature for the given gem specification.
# File rubygems/source_index.rb, line 237
def gem_signature(gem_full_name)
require 'digest'
Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
end
The signature for the source index. Changes in the signature indicate a change in the index.
# File rubygems/source_index.rb, line 228
def index_signature
require 'digest'
Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
end
Returns an Array specifications for the latest released versions of each gem in this index.
# File rubygems/source_index.rb, line 138
def latest_specs(include_prerelease=false)
result = Hash.new { |h,k| h[k] = [] }
latest = {}
sort.each do |_, spec|
name = spec.name
curr_ver = spec.version
prev_ver = latest.key?(name) ? latest[name].version : nil
next if !include_prerelease && curr_ver.prerelease?
next unless prev_ver.nil? or curr_ver >= prev_ver or
latest[name].platform != Gem::Platform::RUBY
if prev_ver.nil? or
(curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then
result[name].clear
latest[name] = spec
end
if spec.platform != Gem::Platform::RUBY then
result[name].delete_if do |result_spec|
result_spec.platform == spec.platform
end
end
result[name] << spec
end
result.values.flatten
end
Reconstruct the source index from the specifications in
spec_dirs.
# File rubygems/source_index.rb, line 117
def load_gems_in(*spec_dirs)
@gems.clear
spec_dirs.reverse_each do |spec_dir|
spec_files = Dir[File.join(spec_dir, "*.gemspec")]
spec_files.each do |spec_file|
gemspec = Gem::Deprecate.skip_during do
Gem::Specification.load spec_file
end
add_spec gemspec if gemspec
end
end
self
end
Returns an Array of Gem::Specifications that are not up to date.
# File rubygems/source_index.rb, line 328
def outdated
outdateds = []
latest_specs.each do |local|
dependency = Gem::Dependency.new local.name, ">= #{local.version}"
fetcher = Gem::SpecFetcher.fetcher
remotes = fetcher.find_matching dependency
remotes = remotes.map { |(_, version, _), _| version }
latest = remotes.sort.last
outdateds << local.name if latest and local.version < latest
end
outdateds
end
# File rubygems/source_index.rb, line 106
def prerelease_gems
@gems.reject { |name, gem| !gem.version.prerelease? }
end
An array including only the prerelease gemspecs
# File rubygems/source_index.rb, line 172
def prerelease_specs
prerelease_gems.values
end
Replaces the gems in the source index from specifications in the directories this source index was created from. Raises an exception if this source index wasn’t created from a directory (via ::from_gems_in or ::from_installed_gems, or having #spec_dirs set).
# File rubygems/source_index.rb, line 320
def refresh!
raise 'source index not created from disk' if @spec_dirs.nil?
load_gems_in(*@spec_dirs)
end
# File rubygems/source_index.rb, line 110
def released_gems
@gems.reject { |name, gem| gem.version.prerelease? }
end
An array including only the released gemspecs
# File rubygems/source_index.rb, line 179
def released_specs
released_gems.values
end
Remove a gem specification named full_name.
# File rubygems/source_index.rb, line 206
def remove_spec(full_name)
@gems.delete full_name
end
Search for a gem by Gem::Dependency
gem_pattern. If only_platform is true, only gems
matching Gem::Platform.local
will be returned. An Array of matching Gem::Specification objects is returned.
For backwards compatibility, a String or Regexp pattern may be passed as
gem_pattern, and a Gem::Requirement for
platform_only. This behavior is deprecated and will be
removed.
# File rubygems/source_index.rb, line 268
def search(gem_pattern, platform_or_requirement = false)
requirement = nil
only_platform = false # FIX: WTF is this?!?
# TODO - Remove support and warning for legacy arguments after 2008/11
unless Gem::Dependency === gem_pattern
warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name"
end
case gem_pattern
when Regexp then
requirement = platform_or_requirement || Gem::Requirement.default
when Gem::Dependency then
only_platform = platform_or_requirement
requirement = gem_pattern.requirement
gem_pattern = if Regexp === gem_pattern.name then
gem_pattern.name
elsif gem_pattern.name.empty? then
//
else
/^#{Regexp.escape gem_pattern.name}$/
end
else
requirement = platform_or_requirement || Gem::Requirement.default
gem_pattern = /#{gem_pattern}/i
end
unless Gem::Requirement === requirement then
requirement = Gem::Requirement.create requirement
end
specs = @gems.values.select do |spec|
spec.name =~ gem_pattern and
requirement.satisfied_by? spec.version
end
if only_platform then
specs = specs.select do |spec|
Gem::Platform.match spec.platform
end
end
specs.sort_by { |s| s.sort_obj }
end
# File rubygems/source_index.rb, line 243
def size
@gems.size
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.