Extended maintenance of Ruby versions 1.8.7 and 1.9.2 ended on July 31, 2014. Read more
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.
The singleton Gem::SourceInfoCache. If
all
is true, a full refresh will be performed if the singleton
instance is being initialized.
# File rubygems/source_info_cache.rb, line 38 def self.cache(all = false) return @cache if @cache @cache = new @cache.refresh all if Gem.configuration.update_sources @cache end
# File rubygems/source_info_cache.rb, line 45 def self.cache_data cache.cache_data end
The name of the system cache file.
# File rubygems/source_info_cache.rb, line 52 def self.latest_system_cache_file File.join File.dirname(system_cache_file), "latest_#{File.basename system_cache_file}" end
The name of the latest user cache file.
# File rubygems/source_info_cache.rb, line 60 def self.latest_user_cache_file File.join File.dirname(user_cache_file), "latest_#{File.basename user_cache_file}" end
Reset all singletons, discarding any changes.
# File rubygems/source_info_cache.rb, line 68 def self.reset @cache = nil @system_cache_file = nil @user_cache_file = nil end
Search all source indexes. See #search.
# File rubygems/source_info_cache.rb, line 77 def self.search(*args) cache.search(*args) end
Search all source indexes returning the source_uri. See #search_with_source.
# File rubygems/source_info_cache.rb, line 85 def self.search_with_source(*args) cache.search_with_source(*args) end
The most recent cache data.
# File rubygems/source_info_cache.rb, line 114 def cache_data return @cache_data if @cache_data cache_file # HACK writable check @only_latest = true @cache_data = read_cache_data latest_cache_file @cache_data end
The name of the cache file.
# File rubygems/source_info_cache.rb, line 128 def cache_file return @cache_file if @cache_file @cache_file = (try_file(system_cache_file) or try_file(user_cache_file) or raise "unable to locate a writable cache file") end
Write the cache to a local file (if it is dirty).
# File rubygems/source_info_cache.rb, line 138 def flush write_cache if @dirty @dirty = false end
# File rubygems/source_info_cache.rb, line 143 def latest_cache_data latest_cache_data = {} cache_data.each do |repo, sice| latest = sice.source_index.latest_specs new_si = Gem::SourceIndex.new new_si.add_specs(*latest) latest_sice = Gem::SourceInfoCacheEntry.new new_si, sice.size latest_cache_data[repo] = latest_sice end latest_cache_data end
The name of the latest cache file.
# File rubygems/source_info_cache.rb, line 162 def latest_cache_file File.join File.dirname(cache_file), "latest_#{File.basename cache_file}" end
The name of the latest system cache file.
# File rubygems/source_info_cache.rb, line 169 def latest_system_cache_file self.class.latest_system_cache_file end
The name of the latest user cache file.
# File rubygems/source_info_cache.rb, line 176 def latest_user_cache_file self.class.latest_user_cache_file end
Merges the complete cache file into this Gem::SourceInfoCache.
# File rubygems/source_info_cache.rb, line 183 def read_all_cache_data if @only_latest then @only_latest = false all_data = read_cache_data cache_file cache_data.update all_data do |source_uri, latest_sice, all_sice| all_sice.source_index.gems.update latest_sice.source_index.gems Gem::SourceInfoCacheEntry.new all_sice.source_index, latest_sice.size end begin refresh true rescue Gem::RemoteFetcher::FetchError end end end
Reads cached data from file
.
# File rubygems/source_info_cache.rb, line 204 def read_cache_data(file) # Marshal loads 30-40% faster from a String, and 2MB on 20061116 is small data = open file, 'rb' do |fp| fp.read end cache_data = Marshal.load data cache_data.each do |url, sice| next unless sice.is_a?(Hash) update cache = sice['cache'] size = sice['size'] if cache.is_a?(Gem::SourceIndex) and size.is_a?(Numeric) then new_sice = Gem::SourceInfoCacheEntry.new cache, size cache_data[url] = new_sice else # irreperable, force refetch. reset_cache_for url, cache_data end end cache_data rescue Errno::ENOENT {} rescue => e if Gem.configuration.really_verbose then say "Exception during cache_data handling: #{e.class} - #{e}" say "Cache file was: #{file}" say "\t#{e.backtrace.join "\n\t"}" end {} end
Refreshes each source in the cache from its repository. If
all
is false, only latest gems are updated.
# File rubygems/source_info_cache.rb, line 241 def refresh(all) Gem.sources.each do |source_uri| cache_entry = cache_data[source_uri] if cache_entry.nil? then cache_entry = Gem::SourceInfoCacheEntry.new nil, 0 cache_data[source_uri] = cache_entry end update if cache_entry.refresh source_uri, all end flush end
# File rubygems/source_info_cache.rb, line 265 def reset_cache_data @cache_data = nil @only_latest = true end
Force cache file to be reset, useful for integration testing of rubygems
# File rubygems/source_info_cache.rb, line 273 def reset_cache_file @cache_file = nil end
# File rubygems/source_info_cache.rb, line 255 def reset_cache_for(url, cache_data) say "Reseting cache for #{url}" if Gem.configuration.really_verbose sice = Gem::SourceInfoCacheEntry.new Gem::SourceIndex.new, 0 sice.refresh url, false # HACK may be unnecessary, see ::cache and #refresh cache_data[url] = sice cache_data 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.
# File rubygems/source_info_cache.rb, line 282 def search(pattern, platform_only = false, all = false) read_all_cache_data if all cache_data.map do |source_uri, sic_entry| next unless Gem.sources.include? source_uri # TODO - Remove this gunk after 2008/11 unless pattern.kind_of? Gem::Dependency then pattern = Gem::Dependency.new pattern, Gem::Requirement.default end sic_entry.source_index.search pattern, platform_only end.flatten.compact 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.
# File rubygems/source_info_cache.rb, line 301 def search_with_source(pattern, only_platform = false, all = false) read_all_cache_data if all results = [] cache_data.map do |source_uri, sic_entry| next unless Gem.sources.include? source_uri # TODO - Remove this gunk after 2008/11 unless pattern.kind_of?(Gem::Dependency) pattern = Gem::Dependency.new(pattern, Gem::Requirement.default) end sic_entry.source_index.search(pattern, only_platform).each do |spec| results << [spec, source_uri] end end results 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.
# File rubygems/source_info_cache.rb, line 328 def set_cache_data(hash) @cache_data = hash update end
The name of the system cache file.
# File rubygems/source_info_cache.rb, line 336 def system_cache_file self.class.system_cache_file end
Determine if path
is a candidate for a cache file. Returns
path
if it is, nil if not.
# File rubygems/source_info_cache.rb, line 344 def try_file(path) return path if File.writable? path return nil if File.exist? path dir = File.dirname path unless File.exist? dir then begin FileUtils.mkdir_p dir rescue RuntimeError, SystemCallError return nil end end return path if File.writable? dir nil end
Mark the cache as updated (i.e. dirty).
# File rubygems/source_info_cache.rb, line 366 def update @dirty = true end
The name of the user cache file.
# File rubygems/source_info_cache.rb, line 373 def user_cache_file self.class.user_cache_file end
Write data to the proper cache files.
# File rubygems/source_info_cache.rb, line 380 def write_cache if not File.exist?(cache_file) or not @only_latest then open cache_file, 'wb' do |io| io.write Marshal.dump(cache_data) end end open latest_cache_file, 'wb' do |io| io.write Marshal.dump(latest_cache_data) end end