Class | Gem::SourceIndex |
In: |
lib/rubygems/source_index.rb
|
Parent: | Object |
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.
NOTE: | 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. |
spec_dirs | [RW] | Directories to use to refresh this SourceIndex when calling refresh! |
Creates a new SourceIndex from the ruby format gem specifications in spec_dirs.
# File lib/rubygems/source_index.rb, line 66 66: def self.from_gems_in(*spec_dirs) 67: new spec_dirs 68: end
Factory method to construct a source index instance for a given path.
deprecated: | 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. |
return: | SourceIndex instance |
# File lib/rubygems/source_index.rb, line 45 45: def self.from_installed_gems(*deprecated) 46: if deprecated.empty? 47: from_gems_in(*installed_spec_directories) 48: else 49: warn "NOTE: from_installed_gems(arg) is deprecated. From #{caller.first}" 50: from_gems_in(*deprecated) # HACK warn 51: end 52: end
Loads a ruby-format specification from file_name and returns the loaded spec.
# File lib/rubygems/source_index.rb, line 74 74: def self.load_specification(file_name) 75: Deprecate.skip_during do 76: Gem::Specification.load file_name 77: end 78: end
Constructs a source index instance from the provided specifications, which is a Hash of gem full names and Gem::Specifications.
# File lib/rubygems/source_index.rb, line 87 87: def initialize specs_or_dirs = [] 88: @gems = {} 89: @spec_dirs = nil 90: 91: case specs_or_dirs 92: when Hash then 93: warn "NOTE: SourceIndex.new(hash) is deprecated; From #{caller.first}." 94: specs_or_dirs.each{ |full_name, spec| add_spec spec } 95: when Array, String then 96: self.spec_dirs = Array(specs_or_dirs) 97: refresh! 98: else 99: arg = specs_or_dirs.inspect 100: warn "NOTE: SourceIndex.new(#{arg}) is deprecated; From #{caller.first}." 101: end 102: end
Add a gem specification to the source index.
# File lib/rubygems/source_index.rb, line 190 190: def add_spec(gem_spec, name = gem_spec.full_name) 191: # No idea why, but the Indexer wants to insert them using original_name 192: # instead of full_name. So we make it an optional arg. 193: @gems[name] = gem_spec 194: end
Add gem specifications to the source index.
# File lib/rubygems/source_index.rb, line 199 199: def add_specs(*gem_specs) 200: gem_specs.each do |spec| 201: add_spec spec 202: end 203: end
Iterate over the specifications in the source index.
# File lib/rubygems/source_index.rb, line 215 215: def each(&block) # :yields: gem.full_name, gem 216: @gems.each(&block) 217: end
Find a gem by an exact match on the short name.
# File lib/rubygems/source_index.rb, line 253 253: def find_name(gem_name, requirement = Gem::Requirement.default) 254: dep = Gem::Dependency.new gem_name, requirement 255: search dep 256: end
The signature for the given gem specification.
# File lib/rubygems/source_index.rb, line 239 239: def gem_signature(gem_full_name) 240: require 'digest' 241: 242: Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s 243: end
The signature for the source index. Changes in the signature indicate a change in the index.
# File lib/rubygems/source_index.rb, line 230 230: def index_signature 231: require 'digest' 232: 233: Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s 234: end
Returns an Array specifications for the latest released versions of each gem in this index.
# File lib/rubygems/source_index.rb, line 140 140: def latest_specs(include_prerelease=false) 141: result = Hash.new { |h,k| h[k] = [] } 142: latest = {} 143: 144: sort.each do |_, spec| 145: name = spec.name 146: curr_ver = spec.version 147: prev_ver = latest.key?(name) ? latest[name].version : nil 148: 149: next if !include_prerelease && curr_ver.prerelease? 150: next unless prev_ver.nil? or curr_ver >= prev_ver or 151: latest[name].platform != Gem::Platform::RUBY 152: 153: if prev_ver.nil? or 154: (curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then 155: result[name].clear 156: latest[name] = spec 157: end 158: 159: if spec.platform != Gem::Platform::RUBY then 160: result[name].delete_if do |result_spec| 161: result_spec.platform == spec.platform 162: end 163: end 164: 165: result[name] << spec 166: end 167: 168: # TODO: why is this a hash while @gems is an array? Seems like 169: # structural similarity would be good. 170: result.values.flatten 171: end
Reconstruct the source index from the specifications in spec_dirs.
# File lib/rubygems/source_index.rb, line 119 119: def load_gems_in(*spec_dirs) 120: @gems.clear 121: 122: spec_dirs.reverse_each do |spec_dir| 123: spec_files = Dir.glob File.join(spec_dir, '*.gemspec') 124: 125: spec_files.each do |spec_file| 126: gemspec = Deprecate.skip_during do 127: Gem::Specification.load spec_file 128: end 129: add_spec gemspec if gemspec 130: end 131: end 132: 133: self 134: end
Returns an Array of Gem::Specifications that are not up to date.
# File lib/rubygems/source_index.rb, line 327 327: def outdated 328: outdateds = [] 329: 330: latest_specs.each do |local| 331: dependency = Gem::Dependency.new local.name, ">= #{local.version}" 332: 333: fetcher = Gem::SpecFetcher.fetcher 334: remotes = fetcher.find_matching dependency 335: remotes = remotes.map { |(_, version, _), _| version } 336: 337: latest = remotes.sort.last 338: 339: outdateds << local.name if latest and local.version < latest 340: end 341: 342: outdateds 343: end
# File lib/rubygems/source_index.rb, line 108 108: def prerelease_gems 109: @gems.reject{ |name, gem| !gem.version.prerelease? } 110: end
An array including only the prerelease gemspecs
# File lib/rubygems/source_index.rb, line 176 176: def prerelease_specs 177: prerelease_gems.values 178: 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 lib/rubygems/source_index.rb, line 319 319: def refresh! 320: raise 'source index not created from disk' if @spec_dirs.nil? 321: load_gems_in(*@spec_dirs) 322: end
# File lib/rubygems/source_index.rb, line 112 112: def released_gems 113: @gems.reject{ |name, gem| gem.version.prerelease? } 114: end
An array including only the released gemspecs
# File lib/rubygems/source_index.rb, line 183 183: def released_specs 184: released_gems.values 185: end
Remove a gem specification named full_name.
# File lib/rubygems/source_index.rb, line 208 208: def remove_spec(full_name) 209: @gems.delete full_name 210: 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 lib/rubygems/source_index.rb, line 267 267: def search(gem_pattern, platform_only = false) 268: requirement = nil 269: only_platform = false 270: 271: # TODO - Remove support and warning for legacy arguments after 2008/11 272: unless Gem::Dependency === gem_pattern 273: warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name" 274: end 275: 276: case gem_pattern 277: when Regexp then 278: requirement = platform_only || Gem::Requirement.default 279: when Gem::Dependency then 280: only_platform = platform_only 281: requirement = gem_pattern.requirement 282: 283: gem_pattern = if Regexp === gem_pattern.name then 284: gem_pattern.name 285: elsif gem_pattern.name.empty? then 286: // 287: else 288: /^#{Regexp.escape gem_pattern.name}$/ 289: end 290: else 291: requirement = platform_only || Gem::Requirement.default 292: gem_pattern = /#{gem_pattern}/i 293: end 294: 295: unless Gem::Requirement === requirement then 296: requirement = Gem::Requirement.create requirement 297: end 298: 299: specs = @gems.values.select do |spec| 300: spec.name =~ gem_pattern and 301: requirement.satisfied_by? spec.version 302: end 303: 304: if only_platform then 305: specs = specs.select do |spec| 306: Gem::Platform.match spec.platform 307: end 308: end 309: 310: specs.sort_by { |s| s.sort_obj } 311: end
The gem specification given a full gem spec name.
# File lib/rubygems/source_index.rb, line 222 222: def specification(full_name) 223: @gems[full_name] 224: end