123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Server::Cache Private

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: lib/rubocop/server/cache.rb

Overview

Caches the states of server process.

Constant Summary

Class Attribute Summary

Class Method Summary

Class Attribute Details

.cache_root_path (rw)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 28

attr_accessor :cache_root_path

.pid_running?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 136

def pid_running?
  Process.kill(0, pid_path.read.to_i) == 1
rescue Errno::ESRCH, Errno::ENOENT, Errno::EACCES, Errno::EROFS, Errno::ENAMETOOLONG
  false
end

Class Method Details

.acquire_lock

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 142

def acquire_lock
  lock_file = File.open(lock_path, File::CREAT)
  # flock returns 0 if successful, and false if not.
  flock_result = lock_file.flock(File::LOCK_EX | File::LOCK_NB)
  yield flock_result != false
ensure
  lock_file.flock(File::LOCK_UN)
  lock_file.close
end

.cache_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 69

def cache_path
  cache_root_dir = if cache_root_path
                     File.join(cache_root_path, 'rubocop_cache')
                   else
                     cache_root_dir_from_config
                   end

  File.expand_path(File.join(cache_root_dir, 'server'))
end

.cache_root_dir_from_config

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 80

def cache_root_dir_from_config
  CacheConfig.root_dir do
    # `RuboCop::ConfigStore` has heavy dependencies, this is a lightweight implementation
    # so that only the necessary `CacheRootDirectory` can be obtained.
    config_path = ConfigFinder.find_config_path(Dir.pwd)
    file_contents = File.read(config_path)

    # Returns early if `CacheRootDirectory` is not used before requiring `erb` or `yaml`.
    next unless file_contents.include?('CacheRootDirectory')

    require 'erb'
    yaml_code = ERB.new(file_contents).result

    require 'yaml'
    config_yaml = YAML.safe_load(
      yaml_code, permitted_classes: [Regexp, Symbol], aliases: true
    )

    # For compatibility with Ruby 3.0 or lower.
    if Gem::Version.new(Psych::VERSION) < Gem::Version.new('4.0.0')
      config_yaml == false ? nil : config_yaml
    end

    config_yaml&.dig('AllCops', 'CacheRootDirectory')
  end
end

.dir

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 63

def dir
  Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
    d.mkpath unless d.exist?
  end
end

.inherit_from_data(yaml)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 172

def inherit_from_data(yaml)
  return '' unless (inherit_from_paths = yaml['inherit_from'])

  Array(inherit_from_paths).map do |path|
    next if PathUtil.remote_file?(path)

    path = Pathname(path)

    path.exist? ? path.read : ''
  end.join
end

.lock_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 120

def lock_path
  dir.join('lock')
end

.pid_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 116

def pid_path
  dir.join('pid')
end

.port_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 108

def port_path
  dir.join('port')
end

.project_dir

Searches for Gemfile or gems.rb in the current dir or any parent dirs

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 31

def project_dir
  current_dir = Dir.pwd
  while current_dir != '/'
    return current_dir if GEMFILE_NAMES.any? do |gemfile|
      File.exist?(File.join(current_dir, gemfile))
    end

    current_dir = File.expand_path('..', current_dir)
  end
  # If we can't find a Gemfile, just use the current directory
  Dir.pwd
end

.project_dir_cache_key

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 44

def project_dir_cache_key
  @project_dir_cache_key ||= project_dir[1..].tr('/', '+')
end

.require_data(yaml)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 184

def require_data(yaml)
  return '' unless (require_paths = yaml['require'])

  Array(require_paths).map do |path|
    # NOTE: This targets only relative or absolute path specifications.
    # For example, specifications like `require: rubocop-performance`,
    # which can be loaded from `$LOAD_PATH`, are ignored.
    next unless path.start_with?('.', '/')

    # NOTE: `.so` files are not typically specified, so only `.rb` files are targeted.
    path = "#{path}.rb" unless path.end_with?('.rb')
    path = Pathname(path)

    path.exist? ? path.read : ''
  end.join
end

.restart_key

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 49

def restart_key
  lockfile_path = LOCKFILE_NAMES.map do |lockfile_name|
    Pathname(project_dir).join(lockfile_name)
  end.find(&:exist?)
  version_data = lockfile_path&.read || RuboCop::Version::STRING
  config_data = Pathname(ConfigFinder.find_config_path(Dir.pwd)).read
  yaml = YAML.safe_load(config_data, permitted_classes: [Regexp, Symbol], aliases: true)
  inherit_from_data = inherit_from_data(yaml)
  require_data = require_data(yaml)

  Digest::SHA1.hexdigest(version_data + config_data + inherit_from_data + require_data)
end

.status_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 124

def status_path
  dir.join('status')
end

.stderr_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 132

def stderr_path
  dir.join('stderr')
end

.token_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 112

def token_path
  dir.join('token')
end

.version_path

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 128

def version_path
  dir.join('version')
end

.write_pid_file

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 157

def write_pid_file
  pid_path.write(Process.pid)
  yield
ensure
  dir.rmtree
end

.write_port_and_token_files(port:, token:)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 152

def write_port_and_token_files(port:, token:)
  port_path.write(port)
  token_path.write(token)
end

.write_status_file(status)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 164

def write_status_file(status)
  status_path.write(status)
end

.write_version_file(version)

[ GitHub ]

  
# File 'lib/rubocop/server/cache.rb', line 168

def write_version_file(version)
  version_path.write(version)
end