Class: RuboCop::ResultCache
- Inherits:
-
Object
- Object
- RuboCop::ResultCache
- Defined in:
- lib/rubocop/result_cache.rb
Overview
Provides functionality for caching rubocop runs.
Constant Summary collapse
- NON_CHANGING =
[:color, :format, :formatters, :out, :debug, :fail_level, :cache, :fail_fast, :stdin].freeze
Class Attribute Summary collapse
-
.inhibit_cleanup ⇒ Object
Returns the value of attribute inhibit_cleanup.
-
.source_checksum ⇒ Object
Returns the value of attribute source_checksum.
Class Method Summary collapse
- .allow_symlinks_in_cache_location?(config_store) ⇒ Boolean
- .cache_root(config_store) ⇒ Object
-
.cleanup(config_store, verbose, cache_root = nil) ⇒ Object
Remove old files so that the cache doesn’t grow too big.
Instance Method Summary collapse
-
#initialize(file, options, config_store, cache_root = nil) ⇒ ResultCache
constructor
A new instance of ResultCache.
- #load ⇒ Object
- #save(offenses) ⇒ Object
- #valid? ⇒ Boolean
Constructor Details
#initialize(file, options, config_store, cache_root = nil) ⇒ ResultCache
Returns a new instance of ResultCache.
71 72 73 74 75 76 77 78 79 |
# File 'lib/rubocop/result_cache.rb', line 71 def initialize(file, , config_store, cache_root = nil) cache_root ||= ResultCache.cache_root(config_store) @allow_symlinks_in_cache_location = ResultCache.allow_symlinks_in_cache_location?(config_store) @path = File.join(cache_root, rubocop_checksum, (), file_checksum(file, config_store)) @cached_data = CachedData.new(file) end |
Class Attribute Details
.inhibit_cleanup ⇒ Object
Returns the value of attribute inhibit_cleanup.
136 137 138 |
# File 'lib/rubocop/result_cache.rb', line 136 def inhibit_cleanup @inhibit_cleanup end |
.source_checksum ⇒ Object
Returns the value of attribute source_checksum.
136 137 138 |
# File 'lib/rubocop/result_cache.rb', line 136 def source_checksum @source_checksum end |
Class Method Details
.allow_symlinks_in_cache_location?(config_store) ⇒ Boolean
67 68 69 |
# File 'lib/rubocop/result_cache.rb', line 67 def self.allow_symlinks_in_cache_location?(config_store) config_store.for('.').for_all_cops['AllowSymlinksInCacheRootDirectory'] end |
.cache_root(config_store) ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/rubocop/result_cache.rb', line 57 def self.cache_root(config_store) root = config_store.for('.').for_all_cops['CacheRootDirectory'] if root == '/tmp' tmpdir = File.realpath(Dir.tmpdir) # Include user ID in the path to make sure the user has write access. root = File.join(tmpdir, Process.uid.to_s) end File.join(root, 'rubocop_cache') end |
.cleanup(config_store, verbose, cache_root = nil) ⇒ Object
Remove old files so that the cache doesn’t grow too big. When the threshold MaxFilesInCache has been exceeded, the oldest 50% of all the files in the cache are removed. The reason for removing so much is that cleaning should be done relatively seldom, since there is a slight risk that some other RuboCop process was just about to read the file, when there’s parallel execution and the cache is shared.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/rubocop/result_cache.rb', line 21 def self.cleanup(config_store, verbose, cache_root = nil) return if inhibit_cleanup # OPTIMIZE: For faster testing cache_root ||= cache_root(config_store) return unless File.exist?(cache_root) files, dirs = Find.find(cache_root).partition { |path| File.file?(path) } if files.length > config_store.for('.').for_all_cops['MaxFilesInCache'] && files.length > 1 # Add 1 to half the number of files, so that we remove the file if # there's only 1 left. remove_count = 1 + files.length / 2 if verbose puts "Removing the #{remove_count} oldest files from #{cache_root}" end sorted = files.sort_by { |path| File.mtime(path) } remove_files(sorted, dirs, remove_count, verbose) end end |
Instance Method Details
#load ⇒ Object
85 86 87 |
# File 'lib/rubocop/result_cache.rb', line 85 def load @cached_data.from_json(IO.binread(@path)) end |
#save(offenses) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rubocop/result_cache.rb', line 89 def save(offenses) dir = File.dirname(@path) FileUtils.mkdir_p(dir) preliminary_path = "#{@path}_#{rand(1_000_000_000)}" # RuboCop must be in control of where its cached data is stored. A # symbolic link anywhere in the cache directory tree can be an # indication that a symlink attack is being waged. return if symlink_protection_triggered?(dir) File.open(preliminary_path, 'wb') do |f| f.write(@cached_data.to_json(offenses)) end # The preliminary path is used so that if there are multiple RuboCop # processes trying to save data for the same inspected file # simultaneously, the only problem we run in to is a competition who gets # to write to the final file. The contents are the same, so no corruption # of data should occur. FileUtils.mv(preliminary_path, @path) end |
#valid? ⇒ Boolean
81 82 83 |
# File 'lib/rubocop/result_cache.rb', line 81 def valid? File.exist?(@path) end |