forked from rubocop/rubocop
/
cache.rb
141 lines (116 loc) · 3.65 KB
/
cache.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# frozen_string_literal: true
require 'pathname'
require_relative '../cache_config'
require_relative '../config_finder'
#
# This code is based on https://github.com/fohte/rubocop-daemon.
#
# Copyright (c) 2018 Hayato Kawai
#
# The MIT License (MIT)
#
# https://github.com/fohte/rubocop-daemon/blob/master/LICENSE.txt
#
module RuboCop
module Server
# Caches the states of server process.
# @api private
class Cache
GEMFILE_NAMES = %w[Gemfile gems.rb].freeze
class << self
attr_accessor :cache_root_path
# Searches for Gemfile or gems.rb in the current dir or any parent dirs
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
def project_dir_cache_key
@project_dir_cache_key ||= project_dir[1..].tr('/', '+')
end
def dir
Pathname.new(File.join(cache_path, project_dir_cache_key)).tap do |d|
d.mkpath unless d.exist?
end
end
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
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.
require 'yaml'
config_path = ConfigFinder.find_config_path(Dir.pwd)
# Ruby 3.1+
config_yaml = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('4.0.0')
YAML.safe_load_file(config_path, permitted_classes: [Regexp, Symbol])
else
YAML.load_file(config_path)
end
config_yaml.dig('AllCops', 'CacheRootDirectory')
end
end
def port_path
dir.join('port')
end
def token_path
dir.join('token')
end
def pid_path
dir.join('pid')
end
def lock_path
dir.join('lock')
end
def status_path
dir.join('status')
end
def version_path
dir.join('version')
end
def pid_running?
Process.kill(0, pid_path.read.to_i) == 1
rescue Errno::ESRCH
false
end
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
def write_port_and_token_files(port:, token:)
port_path.write(port)
token_path.write(token)
end
def write_pid_file
pid_path.write(Process.pid)
yield
ensure
dir.rmtree
end
def write_status_file(status)
status_path.write(status)
end
def write_version_file(version)
version_path.write(version)
end
end
end
end
end