Class Gem::SourceInfoCache
In: lib/rubygems/source_info_cache.rb
Parent: Object

SourceInfoCache stores a copy of the gem index for each gem source.

There are two possible cache locations, the system cache and the user cache:

  • The system cache is preferred if it is writable or can be created.
  • The user cache is used otherwise

Once a cache is selected, it will be used for all operations. SourceInfoCache will not switch between cache files dynamically.

Cache data is a Hash mapping a source URI to a SourceInfoCacheEntry.

Methods

Included Modules

Gem::UserInteraction

Public Class methods

The singleton Gem::SourceInfoCache. If all is true, a full refresh will be performed if the singleton instance is being initialized.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 38
38:   def self.cache(all = false)
39:     return @cache if @cache
40:     @cache = new
41:     @cache.refresh all if Gem.configuration.update_sources
42:     @cache
43:   end

[Source]

    # File lib/rubygems/source_info_cache.rb, line 45
45:   def self.cache_data
46:     cache.cache_data
47:   end

The name of the system cache file.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 52
52:   def self.latest_system_cache_file
53:     File.join File.dirname(system_cache_file),
54:               "latest_#{File.basename system_cache_file}"
55:   end

The name of the latest user cache file.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 60
60:   def self.latest_user_cache_file
61:     File.join File.dirname(user_cache_file),
62:               "latest_#{File.basename user_cache_file}"
63:   end

Reset all singletons, discarding any changes.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 68
68:   def self.reset
69:     @cache = nil
70:     @system_cache_file = nil
71:     @user_cache_file = nil
72:   end

Search all source indexes. See Gem::SourceInfoCache#search.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 77
77:   def self.search(*args)
78:     cache.search(*args)
79:   end

Search all source indexes returning the source_uri. See Gem::SourceInfoCache#search_with_source.

[Source]

    # File lib/rubygems/source_info_cache.rb, line 85
85:   def self.search_with_source(*args)
86:     cache.search_with_source(*args)
87:   end

The name of the system cache file. (class method)

[Source]

    # File lib/rubygems/source_info_cache.rb, line 92
92:   def self.system_cache_file
93:     @system_cache_file ||= Gem.default_system_source_cache_dir
94:   end

The name of the user cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 99
 99:   def self.user_cache_file
100:     @user_cache_file ||=
101:       ENV['GEMCACHE'] || Gem.default_user_source_cache_dir
102:   end

Public Instance methods

The most recent cache data.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 114
114:   def cache_data
115:     return @cache_data if @cache_data
116:     cache_file # HACK writable check
117: 
118:     @only_latest = true
119: 
120:     @cache_data = read_cache_data latest_cache_file
121: 
122:     @cache_data
123:   end

The name of the cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 128
128:   def cache_file
129:     return @cache_file if @cache_file
130:     @cache_file = (try_file(system_cache_file) or
131:       try_file(user_cache_file) or
132:       raise "unable to locate a writable cache file")
133:   end

Write the cache to a local file (if it is dirty).

[Source]

     # File lib/rubygems/source_info_cache.rb, line 138
138:   def flush
139:     write_cache if @dirty
140:     @dirty = false
141:   end

[Source]

     # File lib/rubygems/source_info_cache.rb, line 143
143:   def latest_cache_data
144:     latest_cache_data = {}
145: 
146:     cache_data.each do |repo, sice|
147:       latest = sice.source_index.latest_specs
148: 
149:       new_si = Gem::SourceIndex.new
150:       new_si.add_specs(*latest)
151: 
152:       latest_sice = Gem::SourceInfoCacheEntry.new new_si, sice.size
153:       latest_cache_data[repo] = latest_sice
154:     end
155: 
156:     latest_cache_data
157:   end

The name of the latest cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 162
162:   def latest_cache_file
163:     File.join File.dirname(cache_file), "latest_#{File.basename cache_file}"
164:   end

The name of the latest system cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 169
169:   def latest_system_cache_file
170:     self.class.latest_system_cache_file
171:   end

The name of the latest user cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 176
176:   def latest_user_cache_file
177:     self.class.latest_user_cache_file
178:   end

Merges the complete cache file into this Gem::SourceInfoCache.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 183
183:   def read_all_cache_data
184:     if @only_latest then
185:       @only_latest = false
186:       all_data = read_cache_data cache_file
187: 
188:       cache_data.update all_data do |source_uri, latest_sice, all_sice|
189:         all_sice.source_index.gems.update latest_sice.source_index.gems
190: 
191:         Gem::SourceInfoCacheEntry.new all_sice.source_index, latest_sice.size
192:       end
193: 
194:       begin
195:         refresh true
196:       rescue Gem::RemoteFetcher::FetchError
197:       end
198:     end
199:   end

Reads cached data from file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 204
204:   def read_cache_data(file)
205:     # Marshal loads 30-40% faster from a String, and 2MB on 20061116 is small
206:     data = open file, 'rb' do |fp| fp.read end
207:     cache_data = Marshal.load data
208: 
209:     cache_data.each do |url, sice|
210:       next unless sice.is_a?(Hash)
211:       update
212: 
213:       cache = sice['cache']
214:       size  = sice['size']
215: 
216:       if cache.is_a?(Gem::SourceIndex) and size.is_a?(Numeric) then
217:         new_sice = Gem::SourceInfoCacheEntry.new cache, size
218:         cache_data[url] = new_sice
219:       else # irreperable, force refetch.
220:         reset_cache_for url, cache_data
221:       end
222:     end
223: 
224:     cache_data
225:   rescue Errno::ENOENT
226:     {}
227:   rescue => e
228:     if Gem.configuration.really_verbose then
229:       say "Exception during cache_data handling: #{e.class} - #{e}"
230:       say "Cache file was: #{file}"
231:       say "\t#{e.backtrace.join "\n\t"}"
232:     end
233: 
234:     {}
235:   end

Refreshes each source in the cache from its repository. If all is false, only latest gems are updated.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 241
241:   def refresh(all)
242:     Gem.sources.each do |source_uri|
243:       cache_entry = cache_data[source_uri]
244:       if cache_entry.nil? then
245:         cache_entry = Gem::SourceInfoCacheEntry.new nil, 0
246:         cache_data[source_uri] = cache_entry
247:       end
248: 
249:       update if cache_entry.refresh source_uri, all
250:     end
251: 
252:     flush
253:   end

[Source]

     # File lib/rubygems/source_info_cache.rb, line 265
265:   def reset_cache_data
266:     @cache_data = nil
267:     @only_latest = true
268:   end

Force cache file to be reset, useful for integration testing of rubygems

[Source]

     # File lib/rubygems/source_info_cache.rb, line 273
273:   def reset_cache_file
274:     @cache_file = nil
275:   end

[Source]

     # File lib/rubygems/source_info_cache.rb, line 255
255:   def reset_cache_for(url, cache_data)
256:     say "Reseting cache for #{url}" if Gem.configuration.really_verbose
257: 
258:     sice = Gem::SourceInfoCacheEntry.new Gem::SourceIndex.new, 0
259:     sice.refresh url, false # HACK may be unnecessary, see ::cache and #refresh
260: 
261:     cache_data[url] = sice
262:     cache_data
263:   end

Searches all source indexes. See Gem::SourceIndex#search for details on pattern and platform_only. If all is set to true, the full index will be loaded before searching.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 282
282:   def search(pattern, platform_only = false, all = false)
283:     read_all_cache_data if all
284: 
285:     cache_data.map do |source_uri, sic_entry|
286:       next unless Gem.sources.include? source_uri
287:       sic_entry.source_index.search pattern, platform_only
288:     end.flatten.compact
289:   end

Searches all source indexes for pattern. If only_platform is true, only gems matching Gem.platforms will be selected. Returns an Array of pairs containing the Gem::Specification found and the source_uri it was found at.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 295
295:   def search_with_source(pattern, only_platform = false, all = false)
296:     read_all_cache_data if all
297: 
298:     results = []
299: 
300:     cache_data.map do |source_uri, sic_entry|
301:       next unless Gem.sources.include? source_uri
302: 
303:       sic_entry.source_index.search(pattern, only_platform).each do |spec|
304:         results << [spec, source_uri]
305:       end
306:     end
307: 
308:     results
309:   end

Set the source info cache data directly. This is mainly used for unit testing when we don‘t want to read a file system to grab the cached source index information. The hash should map a source URL into a SourceInfoCacheEntry.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 317
317:   def set_cache_data(hash)
318:     @cache_data = hash
319:     update
320:   end

The name of the system cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 325
325:   def system_cache_file
326:     self.class.system_cache_file
327:   end

Determine if path is a candidate for a cache file. Returns path if it is, nil if not.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 333
333:   def try_file(path)
334:     return path if File.writable? path
335:     return nil if File.exist? path
336: 
337:     dir = File.dirname path
338: 
339:     unless File.exist? dir then
340:       begin
341:         FileUtils.mkdir_p dir
342:       rescue RuntimeError, SystemCallError
343:         return nil
344:       end
345:     end
346: 
347:     return path if File.writable? dir
348: 
349:     nil
350:   end

Mark the cache as updated (i.e. dirty).

[Source]

     # File lib/rubygems/source_info_cache.rb, line 355
355:   def update
356:     @dirty = true
357:   end

The name of the user cache file.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 362
362:   def user_cache_file
363:     self.class.user_cache_file
364:   end

Write data to the proper cache files.

[Source]

     # File lib/rubygems/source_info_cache.rb, line 369
369:   def write_cache
370:     if not File.exist?(cache_file) or not @only_latest then
371:       open cache_file, 'wb' do |io|
372:         io.write Marshal.dump(cache_data)
373:       end
374:     end
375: 
376:     open latest_cache_file, 'wb' do |io|
377:       io.write Marshal.dump(latest_cache_data)
378:     end
379:   end

[Validate]