| 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: Gem::Deprecate.skip_during do
76: Gem::Specification.load Gem::Path.new(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 84
84: def initialize specs_or_dirs = []
85: @gems = {}
86: @spec_dirs = nil
87:
88: case specs_or_dirs
89: when Hash then
90: specs_or_dirs.each do |full_name, spec|
91: add_spec spec
92: end
93: when Array, String then
94: self.spec_dirs = Array(specs_or_dirs)
95: refresh!
96: else
97: arg = specs_or_dirs.inspect
98: warn "NOTE: SourceIndex.new(#{arg}) is deprecated; From #{caller.first}."
99: end
100: end
Add a gem specification to the source index.
# File lib/rubygems/source_index.rb, line 186
186: def add_spec(gem_spec, name = gem_spec.full_name)
187: # No idea why, but the Indexer wants to insert them using original_name
188: # instead of full_name. So we make it an optional arg.
189: @gems[name] = gem_spec
190: end
Add gem specifications to the source index.
# File lib/rubygems/source_index.rb, line 195
195: def add_specs(*gem_specs)
196: Gem::Deprecate.skip_during do
197: gem_specs.each do |spec|
198: add_spec spec
199: end
200: end
201: end
Iterate over the specifications in the source index.
# File lib/rubygems/source_index.rb, line 213
213: def each(&block) # :yields: gem.full_name, gem
214: @gems.each(&block)
215: end
Find a gem by an exact match on the short name.
# File lib/rubygems/source_index.rb, line 251
251: def find_name(gem_name, requirement = Gem::Requirement.default)
252: dep = Gem::Dependency.new gem_name, requirement
253:
254: Gem::Deprecate.skip_during do
255: search dep
256: end
257: end
The signature for the given gem specification.
# File lib/rubygems/source_index.rb, line 237
237: def gem_signature(gem_full_name)
238: require 'digest'
239:
240: Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
241: end
The signature for the source index. Changes in the signature indicate a change in the index.
# File lib/rubygems/source_index.rb, line 228
228: def index_signature
229: require 'digest'
230:
231: Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
232: end
Returns an Array specifications for the latest released versions of each gem in this index.
# File lib/rubygems/source_index.rb, line 138
138: def latest_specs(include_prerelease=false)
139: result = Hash.new { |h,k| h[k] = [] }
140: latest = {}
141:
142: sort.each do |_, spec|
143: name = spec.name
144: curr_ver = spec.version
145: prev_ver = latest.key?(name) ? latest[name].version : nil
146:
147: next if !include_prerelease && curr_ver.prerelease?
148: next unless prev_ver.nil? or curr_ver >= prev_ver or
149: latest[name].platform != Gem::Platform::RUBY
150:
151: if prev_ver.nil? or
152: (curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then
153: result[name].clear
154: latest[name] = spec
155: end
156:
157: if spec.platform != Gem::Platform::RUBY then
158: result[name].delete_if do |result_spec|
159: result_spec.platform == spec.platform
160: end
161: end
162:
163: result[name] << spec
164: end
165:
166: result.values.flatten
167: end
Reconstruct the source index from the specifications in spec_dirs.
# File lib/rubygems/source_index.rb, line 117
117: def load_gems_in(*spec_dirs)
118: @gems.clear
119:
120: spec_dirs.reverse_each do |spec_dir|
121: spec_files = Dir[File.join(spec_dir, "*.gemspec")]
122:
123: spec_files.each do |spec_file|
124: gemspec = Gem::Deprecate.skip_during do
125: Gem::Specification.load spec_file
126: end
127: add_spec gemspec if gemspec
128: end
129: end
130:
131: self
132: end
Returns an Array of Gem::Specifications that are not up to date.
# File lib/rubygems/source_index.rb, line 328
328: def outdated
329: outdateds = []
330:
331: latest_specs.each do |local|
332: dependency = Gem::Dependency.new local.name, ">= #{local.version}"
333:
334: fetcher = Gem::SpecFetcher.fetcher
335: remotes = fetcher.find_matching dependency
336: remotes = remotes.map { |(_, version, _), _| version }
337:
338: latest = remotes.sort.last
339:
340: outdateds << local.name if latest and local.version < latest
341: end
342:
343: outdateds
344: end
# File lib/rubygems/source_index.rb, line 106
106: def prerelease_gems
107: @gems.reject { |name, gem| !gem.version.prerelease? }
108: end
An array including only the prerelease gemspecs
# File lib/rubygems/source_index.rb, line 172
172: def prerelease_specs
173: prerelease_gems.values
174: 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 320
320: def refresh!
321: raise 'source index not created from disk' if @spec_dirs.nil?
322: load_gems_in(*@spec_dirs)
323: end
# File lib/rubygems/source_index.rb, line 110
110: def released_gems
111: @gems.reject { |name, gem| gem.version.prerelease? }
112: end
An array including only the released gemspecs
# File lib/rubygems/source_index.rb, line 179
179: def released_specs
180: released_gems.values
181: end
Remove a gem specification named full_name.
# File lib/rubygems/source_index.rb, line 206
206: def remove_spec(full_name)
207: @gems.delete full_name
208: 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 268
268: def search(gem_pattern, platform_or_requirement = false)
269: requirement = nil
270: only_platform = false # FIX: WTF is this?!?
271:
272: # TODO - Remove support and warning for legacy arguments after 2008/11
273: unless Gem::Dependency === gem_pattern
274: warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name"
275: end
276:
277: case gem_pattern
278: when Regexp then
279: requirement = platform_or_requirement || Gem::Requirement.default
280: when Gem::Dependency then
281: only_platform = platform_or_requirement
282: requirement = gem_pattern.requirement
283:
284: gem_pattern = if Regexp === gem_pattern.name then
285: gem_pattern.name
286: elsif gem_pattern.name.empty? then
287: //
288: else
289: /^#{Regexp.escape gem_pattern.name}$/
290: end
291: else
292: requirement = platform_or_requirement || Gem::Requirement.default
293: gem_pattern = /#{gem_pattern}/i
294: end
295:
296: unless Gem::Requirement === requirement then
297: requirement = Gem::Requirement.create requirement
298: end
299:
300: specs = @gems.values.select do |spec|
301: spec.name =~ gem_pattern and
302: requirement.satisfied_by? spec.version
303: end
304:
305: if only_platform then
306: specs = specs.select do |spec|
307: Gem::Platform.match spec.platform
308: end
309: end
310:
311: specs.sort_by { |s| s.sort_obj }
312: end
The gem specification given a full gem spec name.
# File lib/rubygems/source_index.rb, line 220
220: def specification(full_name)
221: @gems[full_name]
222: end