Class: RuboCop::ResultCache Private
- Inherits:
-
Object
- Object
- RuboCop::ResultCache
- Defined in:
- lib/rubocop/result_cache.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Provides functionality for caching RuboCop runs.
Constant Summary collapse
- NON_CHANGING =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
%i[color format formatters out debug display_time fail_level fix_layout autocorrect safe_autocorrect autocorrect_all cache fail_fast stdin parallel].freeze
- DL_EXTENSIONS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
::RbConfig::CONFIG .values_at('DLEXT', 'DLEXT2') .reject { |ext| !ext || ext.empty? } .map { |ext| ".#{ext}" } .freeze
Class Attribute Summary collapse
- .inhibit_cleanup ⇒ Object private
- .rubocop_required_features ⇒ Object private
Instance Attribute Summary collapse
- #path ⇒ Object readonly private
Class Method Summary collapse
- .allow_symlinks_in_cache_location?(config_store) ⇒ Boolean private
- .cache_root(config_store, cache_root_override = nil) ⇒ Object private
-
.cleanup(config_store, verbose, cache_root_override = nil) ⇒ Object
private
Remove old files so that the cache doesn’t grow too big.
-
.relevant_options_digest(options) ⇒ Object
private
Return a hash of the options given at invocation, minus the ones that have no effect on which offenses and disabled line ranges are found, and thus don’t affect caching.
- .reset_config_cache ⇒ Object private
-
.source_checksum ⇒ Object
private
The checksum of the RuboCop program running the inspection.
Instance Method Summary collapse
- #debug? ⇒ Boolean private
-
#initialize(file, team, options, config_store, cache_root_override = nil) ⇒ ResultCache
constructor
private
A new instance of ResultCache.
- #load ⇒ Object private
- #save(offenses) ⇒ Object private
- #valid? ⇒ Boolean private
Constructor Details
#initialize(file, team, options, config_store, cache_root_override = nil) ⇒ ResultCache
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of ResultCache.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/rubocop/result_cache.rb', line 108 def initialize(file, team, , config_store, cache_root_override = nil) cache_root_override ||= [:cache_root] if [:cache_root] rubocop_cache_dir = ResultCache.cache_root(config_store, cache_root_override) @allow_symlinks_in_cache_location = ResultCache.allow_symlinks_in_cache_location?(config_store) @path = File.join(rubocop_cache_dir, self.class.source_checksum, context_checksum(team, ), file_checksum(file, config_store)) @cached_data = CachedData.new(file) @debug = [:debug] end |
Class Attribute Details
.inhibit_cleanup ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
191 192 193 |
# File 'lib/rubocop/result_cache.rb', line 191 def inhibit_cleanup @inhibit_cleanup end |
.rubocop_required_features ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
45 46 47 |
# File 'lib/rubocop/result_cache.rb', line 45 def rubocop_required_features @rubocop_required_features end |
Instance Attribute Details
#path ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
106 107 108 |
# File 'lib/rubocop/result_cache.rb', line 106 def path @path end |
Class Method Details
.allow_symlinks_in_cache_location?(config_store) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
98 99 100 |
# File 'lib/rubocop/result_cache.rb', line 98 def self.allow_symlinks_in_cache_location?(config_store) config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory'] end |
.cache_root(config_store, cache_root_override = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
88 89 90 91 92 93 94 95 96 |
# File 'lib/rubocop/result_cache.rb', line 88 def self.cache_root(config_store, cache_root_override = nil) return @cache_root if @cache_root && !cache_root_override result = CacheConfig.root_dir do cache_root_override || config_store.for_pwd.for_all_cops['CacheRootDirectory'] end @cache_root = result unless cache_root_override result end |
.cleanup(config_store, verbose, cache_root_override = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
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 removing 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.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rubocop/result_cache.rb', line 28 def self.cleanup(config_store, verbose, cache_root_override = nil) return if inhibit_cleanup # OPTIMIZE: For faster testing return unless config_store.for_pwd.for_all_cops['MaxFilesInCache'] rubocop_cache_dir = cache_root(config_store, cache_root_override) return unless File.exist?(rubocop_cache_dir) # We know the cache entries are 3 level deep, so globing # for `*/*/*` only returns files. files = Dir[File.join(rubocop_cache_dir, '*/*/*')] return unless requires_file_removal?(files.length, config_store) remove_oldest_files(files, rubocop_cache_dir, verbose) end |
.relevant_options_digest(options) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a hash of the options given at invocation, minus the ones that have no effect on which offenses and disabled line ranges are found, and thus don’t affect caching.
211 212 213 214 215 216 217 |
# File 'lib/rubocop/result_cache.rb', line 211 def () @relevant_options_digest ||= {} @relevant_options_digest[] ||= begin = .reject { |key, _| NON_CHANGING.include?(key) } .to_s.gsub(/[^a-z]+/i, '_') end end |
.reset_config_cache ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
102 103 104 |
# File 'lib/rubocop/result_cache.rb', line 102 def self.reset_config_cache @cache_root = nil end |
.source_checksum ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The checksum of the RuboCop program running the inspection.
194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/rubocop/result_cache.rb', line 194 def source_checksum @source_checksum ||= begin digest = Digest::SHA1.new rubocop_extra_features .select { |path| File.file?(path) } .sort! .each do |path| digest << digest(path) end digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING digest.hexdigest end end |
Instance Method Details
#debug? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
121 122 123 |
# File 'lib/rubocop/result_cache.rb', line 121 def debug? @debug end |
#load ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
129 130 131 132 |
# File 'lib/rubocop/result_cache.rb', line 129 def load puts "Loading cache from #{@path}" if debug? @cached_data.from_json(File.read(@path, encoding: Encoding::UTF_8)) end |
#save(offenses) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/rubocop/result_cache.rb', line 134 def save(offenses) dir = File.dirname(@path) begin FileUtils.mkdir_p(dir) rescue Errno::EACCES, Errno::EROFS => e warn "Couldn't create cache directory. Continuing without cache.\n #{e.}" return end 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, 'w', encoding: Encoding::UTF_8) 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
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
125 126 127 |
# File 'lib/rubocop/result_cache.rb', line 125 def valid? File.exist?(@path) end |