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
- .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.
63 64 65 66 67 68 69 |
# File 'lib/rubocop/result_cache.rb', line 63 def initialize(file, , config_store, cache_root = nil) cache_root ||= ResultCache.cache_root(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.
122 123 124 |
# File 'lib/rubocop/result_cache.rb', line 122 def inhibit_cleanup @inhibit_cleanup end |
.source_checksum ⇒ Object
Returns the value of attribute source_checksum.
122 123 124 |
# File 'lib/rubocop/result_cache.rb', line 122 def source_checksum @source_checksum end |
Class Method Details
.cache_root(config_store) ⇒ Object
53 54 55 56 57 58 59 60 61 |
# File 'lib/rubocop/result_cache.rb', line 53 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
75 76 77 |
# File 'lib/rubocop/result_cache.rb', line 75 def load @cached_data.from_json(IO.binread(@path)) end |
#save(offenses) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/rubocop/result_cache.rb', line 79 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 is an indication # that a symlink attack is being waged. return if any_symlink?(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
71 72 73 |
# File 'lib/rubocop/result_cache.rb', line 71 def valid? File.exist?(@path) end |