| 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