pindo 5.2.4 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pindo/base/aeshelper.rb +23 -2
- data/lib/pindo/base/pindocontext.rb +476 -0
- data/lib/pindo/client/pgyer_feishu_oauth_cli.rb +343 -80
- data/lib/pindo/client/pgyerclient.rb +30 -20
- data/lib/pindo/command/android/autobuild.rb +58 -22
- data/lib/pindo/command/android/build.rb +27 -16
- data/lib/pindo/command/android/debug.rb +25 -15
- data/lib/pindo/command/dev/debug.rb +2 -51
- data/lib/pindo/command/dev/feishu.rb +19 -2
- data/lib/pindo/command/ios/adhoc.rb +2 -1
- data/lib/pindo/command/ios/autobuild.rb +39 -9
- data/lib/pindo/command/ios/build.rb +7 -0
- data/lib/pindo/command/ios/debug.rb +2 -132
- data/lib/pindo/command/lib/lint.rb +24 -1
- data/lib/pindo/command/setup.rb +24 -4
- data/lib/pindo/command/unity/apk.rb +20 -0
- data/lib/pindo/command/unity/ipa.rb +27 -3
- data/lib/pindo/command/unity/web.rb +15 -10
- data/lib/pindo/command/web/autobuild.rb +5 -0
- data/lib/pindo/command.rb +58 -1
- data/lib/pindo/module/android/android_build_config_helper.rb +427 -0
- data/lib/pindo/module/android/apk_helper.rb +23 -25
- data/lib/pindo/module/android/base_helper.rb +572 -0
- data/lib/pindo/module/android/build_helper.rb +8 -318
- data/lib/pindo/module/android/gp_compliance_helper.rb +668 -0
- data/lib/pindo/module/android/gradle_helper.rb +746 -3
- data/lib/pindo/module/appselect.rb +18 -5
- data/lib/pindo/module/build/buildhelper.rb +120 -29
- data/lib/pindo/module/build/unityhelper.rb +674 -18
- data/lib/pindo/module/build/versionhelper.rb +146 -0
- data/lib/pindo/module/cert/certhelper.rb +33 -2
- data/lib/pindo/module/cert/xcodecerthelper.rb +3 -1
- data/lib/pindo/module/pgyer/pgyerhelper.rb +114 -31
- data/lib/pindo/module/xcode/xcodebuildconfig.rb +232 -0
- data/lib/pindo/module/xcode/xcodebuildhelper.rb +0 -1
- data/lib/pindo/version.rb +356 -86
- data/lib/pindo.rb +72 -3
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56fcfdba92a710c2c7ab85226d30f305cbb1fca5d3fccb57d5c62e6593c8afbb
|
4
|
+
data.tar.gz: a2d7a5c80ca642869ce4f79ef9dca35383b7426c5cf15077937137db899b4eab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54cef915058ddb2d765e136181c13b1e1e6e1376316e8b443a19e54bf03da4afb7763564348c7fe04099cb87476e3547664016dd479936423243360036a9fbe4
|
7
|
+
data.tar.gz: 86a5729f1929db20b938254ae541c1310fce8dba85d7d0088966f197aad668723c11270775bbdcd8651ca86609d357e69fac7dfd8e6d1459133d58fe9357bccd
|
data/lib/pindo/base/aeshelper.rb
CHANGED
@@ -8,7 +8,7 @@ module Pindo
|
|
8
8
|
module AESHelper
|
9
9
|
|
10
10
|
|
11
|
-
def self.fetch_password(keychain_name:nil)
|
11
|
+
def self.fetch_password(keychain_name:nil, test_file:nil)
|
12
12
|
# password = ENV["MATCH_PASSWORD"]
|
13
13
|
|
14
14
|
server_name = ["match", keychain_name].join("_")
|
@@ -18,9 +18,30 @@ module Pindo
|
|
18
18
|
password = item.password if item
|
19
19
|
|
20
20
|
unless password
|
21
|
+
puts "\e[33m[DEBUG] Keychain中未找到密码,需要用户输入: #{server_name}\e[0m" if ENV['PINDO_DEBUG']
|
21
22
|
password = FastlaneCore::Helper.ask_password(message: "请输入证书仓库的加密密码: ", confirm: true)
|
22
|
-
|
23
|
+
# 尝试添加密码到Keychain,如果已存在则先删除再添加
|
24
|
+
begin
|
25
|
+
# 先检查是否已存在,如果存在则删除
|
26
|
+
existing_item = Security::InternetPassword.find(server: server_name)
|
27
|
+
if existing_item
|
28
|
+
# 重定向stderr到/dev/null来隐藏Keychain的详细输出
|
29
|
+
system("security delete-internet-password -s '#{server_name}' 2>/dev/null")
|
30
|
+
puts "\e[33m[DEBUG] 删除Keychain中的旧密码项: #{server_name}\e[0m" if ENV['PINDO_DEBUG']
|
31
|
+
end
|
32
|
+
|
33
|
+
# 添加新密码,重定向stderr到/dev/null来隐藏Keychain的详细输出
|
34
|
+
system("security add-internet-password -s '#{server_name}' -w '#{password}' 2>/dev/null")
|
35
|
+
puts "\e[32m[DEBUG] 密码已保存到Keychain: #{server_name}\e[0m" if ENV['PINDO_DEBUG']
|
36
|
+
rescue => e
|
37
|
+
# 忽略Keychain错误,继续使用密码
|
38
|
+
# 错误信息可能包含 "already exists" 等,但不影响功能
|
39
|
+
puts "\e[31m[DEBUG] Keychain操作错误: #{e.message}\e[0m" if ENV['PINDO_DEBUG']
|
40
|
+
end
|
41
|
+
else
|
42
|
+
puts "\e[32m[DEBUG] 从Keychain获取密码成功: #{server_name}\e[0m" if ENV['PINDO_DEBUG']
|
23
43
|
end
|
44
|
+
|
24
45
|
return password
|
25
46
|
end
|
26
47
|
|
@@ -0,0 +1,476 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'digest'
|
3
|
+
require 'json'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Pindo
|
7
|
+
class PindoContext
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_reader :current_command, :current_directory
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@current_command = nil # 根命令(第一个设置的命令)
|
14
|
+
@current_directory = nil # 项目路径
|
15
|
+
@memory_selections = {} # 三级结构的内存缓存
|
16
|
+
@file_cache_loaded = false # 标记文件缓存是否已加载
|
17
|
+
@cache_enabled = false # 默认禁用缓存
|
18
|
+
@command_group = nil # 命令组名称
|
19
|
+
ensure_cache_dir
|
20
|
+
end
|
21
|
+
|
22
|
+
# 设置当前上下文
|
23
|
+
def set_context(command, directory = nil, options = {})
|
24
|
+
# 如果已有命令在执行,这是嵌套调用,不需要做任何事
|
25
|
+
unless @current_command.nil?
|
26
|
+
puts "[PindoContext] 嵌套调用 #{command},使用已有上下文 (根命令: #{@current_command},命令组: #{@command_group})"
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
# 第一次设置,是顶层命令
|
31
|
+
@current_command = command # 保持原始命令名称
|
32
|
+
@current_directory = directory || Dir.pwd # 固定项目目录
|
33
|
+
|
34
|
+
# 从选项中获取缓存配置
|
35
|
+
@cache_enabled = options[:cache_enabled] || false
|
36
|
+
# 使用 get_command_group 来确定缓存组
|
37
|
+
@command_group = get_command_group(command)
|
38
|
+
|
39
|
+
puts "\n[PindoContext] ========== 设置顶层命令上下文 =========="
|
40
|
+
puts "[PindoContext] 命令: #{command}"
|
41
|
+
puts "[PindoContext] 目录: #{@current_directory}"
|
42
|
+
puts "[PindoContext] 缓存启用: #{@cache_enabled}"
|
43
|
+
puts "[PindoContext] 命令组: #{@command_group}"
|
44
|
+
puts "[PindoContext] options: #{options.inspect}"
|
45
|
+
|
46
|
+
# 仅在启用缓存时加载文件缓存
|
47
|
+
if @cache_enabled && !@file_cache_loaded
|
48
|
+
puts "[PindoContext] 准备加载文件缓存..."
|
49
|
+
load_file_cache_with_confirmation
|
50
|
+
@file_cache_loaded = true
|
51
|
+
else
|
52
|
+
if !@cache_enabled
|
53
|
+
puts "[PindoContext] 缓存未启用,跳过文件缓存加载"
|
54
|
+
elsif @file_cache_loaded
|
55
|
+
puts "[PindoContext] 文件缓存已加载,跳过重复加载"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
puts "[PindoContext] ======================================\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
# 重置上下文(顶层命令结束时调用)
|
62
|
+
def reset_context
|
63
|
+
# 仅在启用缓存时保存文件缓存
|
64
|
+
save_file_cache if @cache_enabled && @current_command
|
65
|
+
|
66
|
+
@current_command = nil
|
67
|
+
@current_directory = nil
|
68
|
+
@file_cache_loaded = false
|
69
|
+
@cache_enabled = false
|
70
|
+
@command_group = nil
|
71
|
+
# 暂不清理内存缓存,让同一进程内可以复用
|
72
|
+
end
|
73
|
+
|
74
|
+
# 设置用户选择(三级结构:项目路径 -> 根命令 -> 键值)
|
75
|
+
def set_selection(key, value)
|
76
|
+
# 构建三级键 - 使用统一的项目路径获取方法
|
77
|
+
project_path = get_project_path
|
78
|
+
root_command = @command_group || @current_command
|
79
|
+
|
80
|
+
# 如果没有有效的项目路径或命令,不保存
|
81
|
+
unless project_path && root_command
|
82
|
+
puts "[PindoContext] 警告: 无法保存选择,缺少项目路径或命令上下文"
|
83
|
+
return
|
84
|
+
end
|
85
|
+
|
86
|
+
# 初始化三级结构(总是保存到内存,不管是否启用缓存)
|
87
|
+
@memory_selections[project_path] ||= {}
|
88
|
+
@memory_selections[project_path][root_command] ||= {}
|
89
|
+
@memory_selections[project_path][root_command][key] = value
|
90
|
+
|
91
|
+
# 更新该命令组的最后修改时间
|
92
|
+
@memory_selections[project_path][root_command]['__last_modified__'] = Time.now.to_i
|
93
|
+
|
94
|
+
puts "[PindoContext] 保存到内存: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}"
|
95
|
+
|
96
|
+
# 仅在启用缓存时保存到文件
|
97
|
+
if @cache_enabled
|
98
|
+
save_file_cache
|
99
|
+
puts "[PindoContext] 已保存到文件缓存"
|
100
|
+
else
|
101
|
+
puts "[PindoContext] 缓存未启用,仅保存到内存"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# 获取用户选择(三级结构访问)
|
106
|
+
def get_selection(key)
|
107
|
+
# 使用统一的项目路径获取方法
|
108
|
+
project_path = get_project_path
|
109
|
+
root_command = @command_group || @current_command
|
110
|
+
|
111
|
+
return nil unless project_path && root_command
|
112
|
+
|
113
|
+
# 从三级结构中获取值(总是从内存获取,不管是否启用缓存)
|
114
|
+
value = @memory_selections.dig(project_path, root_command, key)
|
115
|
+
|
116
|
+
if value
|
117
|
+
puts "[PindoContext] 从内存获取: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}"
|
118
|
+
else
|
119
|
+
puts "[PindoContext] 内存中未找到: [#{project_path}][#{root_command}][#{key}]" if ENV['PINDO_DEBUG']
|
120
|
+
end
|
121
|
+
|
122
|
+
value
|
123
|
+
end
|
124
|
+
|
125
|
+
# 检查是否有缓存的选择
|
126
|
+
def has_selection?(key)
|
127
|
+
# 总是检查内存中是否有值,不管是否启用缓存
|
128
|
+
!get_selection(key).nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
# 启用/禁用缓存
|
132
|
+
def enable_cache(enabled = true)
|
133
|
+
@cache_enabled = enabled
|
134
|
+
if enabled && !@file_cache_loaded && @current_command
|
135
|
+
load_file_cache_with_confirmation
|
136
|
+
@file_cache_loaded = true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# 检查缓存是否启用
|
141
|
+
def cache_enabled?
|
142
|
+
@cache_enabled
|
143
|
+
end
|
144
|
+
|
145
|
+
# 是否是嵌套调用
|
146
|
+
def nested_call?
|
147
|
+
!@current_command.nil?
|
148
|
+
end
|
149
|
+
|
150
|
+
# 是否是顶层命令(非嵌套)
|
151
|
+
def top_level_command?
|
152
|
+
@current_command.nil?
|
153
|
+
end
|
154
|
+
|
155
|
+
# 获取当前根命令
|
156
|
+
def root_command
|
157
|
+
@command_group || @current_command
|
158
|
+
end
|
159
|
+
|
160
|
+
# 获取当前项目路径(统一的获取方法,确保一致性)
|
161
|
+
def project_path
|
162
|
+
get_project_path
|
163
|
+
end
|
164
|
+
|
165
|
+
# 内部使用的项目路径获取方法
|
166
|
+
# 优先使用已设置的目录,如果没有则尝试获取Git仓库根目录
|
167
|
+
def get_project_path
|
168
|
+
# 如果已经设置了目录,直接返回
|
169
|
+
return @current_directory if @current_directory
|
170
|
+
|
171
|
+
# 尝试获取Git仓库根目录
|
172
|
+
begin
|
173
|
+
git_root = `git rev-parse --show-toplevel 2>/dev/null`.strip
|
174
|
+
return git_root if $?.success? && !git_root.empty?
|
175
|
+
rescue
|
176
|
+
# git命令失败
|
177
|
+
end
|
178
|
+
|
179
|
+
# 最后的后备:使用当前目录
|
180
|
+
Dir.pwd
|
181
|
+
end
|
182
|
+
|
183
|
+
# 清除当前上下文的缓存
|
184
|
+
def clear_current_cache
|
185
|
+
return unless @cache_enabled
|
186
|
+
|
187
|
+
proj_path = get_project_path
|
188
|
+
cmd = root_command
|
189
|
+
return unless proj_path && cmd
|
190
|
+
|
191
|
+
if @memory_selections[proj_path] && @memory_selections[proj_path][cmd]
|
192
|
+
@memory_selections[proj_path].delete(cmd)
|
193
|
+
@memory_selections.delete(proj_path) if @memory_selections[proj_path].empty?
|
194
|
+
save_file_cache
|
195
|
+
puts "[PindoContext] 清除缓存: [#{proj_path}][#{cmd}]" if ENV['PINDO_DEBUG']
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# 选择键定义
|
200
|
+
module SelectionKey
|
201
|
+
TAG_DECISION = :tag_decision # 打Tag决定
|
202
|
+
PROJECT_NAME = :project_name # 项目名称
|
203
|
+
BUNDLE_ID = :bundle_id # Bundle ID
|
204
|
+
CERT_TYPE = :cert_type # 证书类型
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
# 确保缓存目录存在
|
210
|
+
def ensure_cache_dir
|
211
|
+
cache_dir = File.expand_path('~/.pindo/cache')
|
212
|
+
FileUtils.mkdir_p(cache_dir) unless File.exist?(cache_dir)
|
213
|
+
end
|
214
|
+
|
215
|
+
# 获取缓存文件路径
|
216
|
+
def cache_file_path
|
217
|
+
cache_dir = File.expand_path('~/.pindo/cache')
|
218
|
+
File.join(cache_dir, 'context_selections.json')
|
219
|
+
end
|
220
|
+
|
221
|
+
# 加载文件缓存并确认(三级结构)
|
222
|
+
def load_file_cache_with_confirmation
|
223
|
+
file_path = cache_file_path
|
224
|
+
|
225
|
+
puts "[PindoContext] 检查文件缓存: #{file_path}"
|
226
|
+
|
227
|
+
unless File.exist?(file_path)
|
228
|
+
puts "[PindoContext] 文件缓存不存在,跳过加载"
|
229
|
+
return
|
230
|
+
end
|
231
|
+
|
232
|
+
begin
|
233
|
+
file_content = File.read(file_path)
|
234
|
+
file_cache = JSON.parse(file_content)
|
235
|
+
|
236
|
+
# 清理过期缓存(超过7天)
|
237
|
+
file_cache = clean_expired_cache(file_cache)
|
238
|
+
|
239
|
+
# 获取当前项目和命令的缓存
|
240
|
+
project_path = get_project_path
|
241
|
+
root_command = @command_group || @current_command
|
242
|
+
|
243
|
+
puts "[PindoContext] 查找缓存: [#{project_path}][#{root_command}]"
|
244
|
+
|
245
|
+
# 检查三级结构中是否有当前上下文的缓存
|
246
|
+
cached_selections = file_cache.dig(project_path, root_command)
|
247
|
+
|
248
|
+
if cached_selections && !cached_selections.empty?
|
249
|
+
# 根据命令组显示更友好的描述
|
250
|
+
group_desc = case root_command
|
251
|
+
when 'ios:autobuild'
|
252
|
+
'iOS 构建'
|
253
|
+
when 'and:autobuild', 'android:autobuild'
|
254
|
+
'Android 构建'
|
255
|
+
when 'web:autobuild'
|
256
|
+
'Web 构建'
|
257
|
+
else
|
258
|
+
@current_command # 其他命令显示原始命令名
|
259
|
+
end
|
260
|
+
|
261
|
+
puts "\n检测到之前的选择 (#{group_desc}):"
|
262
|
+
puts "────────────────────────────────────────"
|
263
|
+
|
264
|
+
cached_selections.each do |key, value|
|
265
|
+
# 跳过内部字段
|
266
|
+
next if key.to_s.start_with?('__')
|
267
|
+
|
268
|
+
case key.to_s
|
269
|
+
when 'bundle_id'
|
270
|
+
puts " Bundle ID: #{value}"
|
271
|
+
when 'project_name', 'app_key' # 兼容旧的 app_key
|
272
|
+
puts " 项目名称: #{value}"
|
273
|
+
when 'tag_decision'
|
274
|
+
if value.is_a?(Hash)
|
275
|
+
action_desc = value['description'] || value['action']
|
276
|
+
puts " Tag决定: #{action_desc}"
|
277
|
+
end
|
278
|
+
when 'cert_type'
|
279
|
+
puts " 证书类型: #{value}"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
puts "────────────────────────────────────────"
|
283
|
+
|
284
|
+
# 询问用户是否使用缓存
|
285
|
+
require 'highline/import'
|
286
|
+
cli = HighLine.new
|
287
|
+
confirm = cli.agree("\n是否使用以上缓存的选择? (y/n) ")
|
288
|
+
|
289
|
+
if confirm
|
290
|
+
puts "使用缓存的选择\n"
|
291
|
+
# 恢复三级结构的文件缓存到内存缓存
|
292
|
+
file_cache.each do |proj_path, commands|
|
293
|
+
@memory_selections[proj_path] ||= {}
|
294
|
+
commands.each do |cmd, selections|
|
295
|
+
@memory_selections[proj_path][cmd] ||= {}
|
296
|
+
selections.each do |key, value|
|
297
|
+
symbol_key = key.to_sym
|
298
|
+
@memory_selections[proj_path][cmd][symbol_key] = value
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
else
|
303
|
+
puts "清除缓存,重新选择\n"
|
304
|
+
# 清除当前上下文的文件缓存(三级结构)
|
305
|
+
if file_cache[project_path] && file_cache[project_path][root_command]
|
306
|
+
file_cache[project_path].delete(root_command)
|
307
|
+
# 如果项目路径下没有任何命令缓存了,删除项目路径键
|
308
|
+
file_cache.delete(project_path) if file_cache[project_path].empty?
|
309
|
+
end
|
310
|
+
File.write(file_path, JSON.pretty_generate(file_cache))
|
311
|
+
# 不加载任何缓存到内存
|
312
|
+
end
|
313
|
+
else
|
314
|
+
# 加载整个文件缓存到内存(不需要确认)
|
315
|
+
file_cache.each do |proj_path, commands|
|
316
|
+
@memory_selections[proj_path] ||= {}
|
317
|
+
commands.each do |cmd, selections|
|
318
|
+
# 跳过当前上下文(已经是空的)
|
319
|
+
next if proj_path == project_path && cmd == root_command
|
320
|
+
|
321
|
+
@memory_selections[proj_path][cmd] ||= {}
|
322
|
+
selections.each do |key, value|
|
323
|
+
symbol_key = key.to_sym
|
324
|
+
@memory_selections[proj_path][cmd][symbol_key] = value
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
puts "[PindoContext] 处理文件缓存: #{file_path}" if ENV['PINDO_DEBUG']
|
331
|
+
rescue => e
|
332
|
+
puts "[PindoContext] 加载缓存失败: #{e.message}" if ENV['PINDO_DEBUG']
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# 保存文件缓存(三级结构)
|
337
|
+
def save_file_cache
|
338
|
+
file_path = cache_file_path
|
339
|
+
|
340
|
+
begin
|
341
|
+
# 转换内存缓存为可序列化的格式(保持三级结构)
|
342
|
+
file_cache = {}
|
343
|
+
@memory_selections.each do |project_path, commands|
|
344
|
+
file_cache[project_path] ||= {}
|
345
|
+
commands.each do |command, selections|
|
346
|
+
file_cache[project_path][command] ||= {}
|
347
|
+
selections.each do |key, value|
|
348
|
+
# 将符号键转换为字符串
|
349
|
+
string_key = key.to_s
|
350
|
+
file_cache[project_path][command][string_key] = value
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# 写入文件
|
356
|
+
File.write(file_path, JSON.pretty_generate(file_cache))
|
357
|
+
|
358
|
+
puts "[PindoContext] 保存文件缓存: #{file_path}" if ENV['PINDO_DEBUG']
|
359
|
+
rescue => e
|
360
|
+
puts "[PindoContext] 保存缓存失败: #{e.message}" if ENV['PINDO_DEBUG']
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# 获取命令组名称(统一管理命令缓存组)
|
365
|
+
def get_command_group(command)
|
366
|
+
# 根据需求文档定义命令组,相关命令共享同一缓存
|
367
|
+
case command
|
368
|
+
# iOS 构建相关命令组
|
369
|
+
when 'unity:ipa'
|
370
|
+
'ios:autobuild'
|
371
|
+
|
372
|
+
# Android 构建相关命令组
|
373
|
+
when 'unity:apk'
|
374
|
+
'and:autobuild'
|
375
|
+
|
376
|
+
# Web 构建相关命令组
|
377
|
+
when 'unity:web'
|
378
|
+
'web:autobuild'
|
379
|
+
|
380
|
+
else
|
381
|
+
command # 其他命令使用独立缓存(命令名本身作为组)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# 清理过期缓存(超过7天的缓存)
|
386
|
+
def clean_expired_cache(cache_data)
|
387
|
+
return {} unless cache_data.is_a?(Hash)
|
388
|
+
|
389
|
+
current_time = Time.now.to_i
|
390
|
+
seven_days_in_seconds = 7 * 24 * 60 * 60
|
391
|
+
cleaned_cache = {}
|
392
|
+
expired_commands = []
|
393
|
+
expired_projects = []
|
394
|
+
|
395
|
+
cache_data.each do |project_path, commands|
|
396
|
+
# 初始化项目路径
|
397
|
+
cleaned_commands = {}
|
398
|
+
|
399
|
+
commands.each do |command, selections|
|
400
|
+
# 获取最后修改时间
|
401
|
+
last_modified = selections['__last_modified__']
|
402
|
+
|
403
|
+
# 如果没有时间戳,视为过期
|
404
|
+
if last_modified.nil?
|
405
|
+
expired_commands << "[#{project_path}][#{command}] (无时间戳)"
|
406
|
+
puts "[PindoContext] 清理无时间戳缓存: [#{project_path}][#{command}]" if ENV['PINDO_DEBUG']
|
407
|
+
next
|
408
|
+
end
|
409
|
+
|
410
|
+
# 检查是否过期(超过7天)
|
411
|
+
if (current_time - last_modified.to_i) > seven_days_in_seconds
|
412
|
+
days_old = (current_time - last_modified.to_i) / (24 * 60 * 60)
|
413
|
+
expired_commands << "[#{project_path}][#{command}] (#{days_old}天前)"
|
414
|
+
puts "[PindoContext] 清理过期缓存 (#{days_old}天前): [#{project_path}][#{command}]" if ENV['PINDO_DEBUG']
|
415
|
+
next
|
416
|
+
end
|
417
|
+
|
418
|
+
# 保留未过期的缓存
|
419
|
+
cleaned_commands[command] = selections
|
420
|
+
end
|
421
|
+
|
422
|
+
# 如果该项目路径下还有有效的命令缓存,保留它
|
423
|
+
if cleaned_commands.any?
|
424
|
+
cleaned_cache[project_path] = cleaned_commands
|
425
|
+
else
|
426
|
+
# 整个项目路径下的所有命令都过期了,删除整个项目路径
|
427
|
+
expired_projects << project_path
|
428
|
+
puts "[PindoContext] 删除空项目路径: #{project_path}" if ENV['PINDO_DEBUG']
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
# 输出清理总结
|
433
|
+
if expired_commands.any? || expired_projects.any?
|
434
|
+
puts "[PindoContext] 缓存清理完成:"
|
435
|
+
if expired_commands.any?
|
436
|
+
puts " - 清理了 #{expired_commands.size} 个过期命令缓存"
|
437
|
+
expired_commands.each { |cmd| puts " • #{cmd}" } if ENV['PINDO_DEBUG']
|
438
|
+
end
|
439
|
+
if expired_projects.any?
|
440
|
+
puts " - 删除了 #{expired_projects.size} 个空项目路径"
|
441
|
+
expired_projects.each { |proj| puts " • #{proj}" } if ENV['PINDO_DEBUG']
|
442
|
+
end
|
443
|
+
|
444
|
+
# 立即保存清理后的缓存到文件
|
445
|
+
File.write(cache_file_path, JSON.pretty_generate(cleaned_cache))
|
446
|
+
end
|
447
|
+
|
448
|
+
cleaned_cache
|
449
|
+
end
|
450
|
+
|
451
|
+
|
452
|
+
public
|
453
|
+
|
454
|
+
# 调试信息
|
455
|
+
def debug_info
|
456
|
+
puts "\n=== PindoContext Debug Info ==="
|
457
|
+
puts "当前命令: #{@current_command || '无'}"
|
458
|
+
puts "命令组: #{@command_group || '无'}"
|
459
|
+
puts "设置的目录: #{@current_directory || '未设置'}"
|
460
|
+
puts "实际项目路径: #{get_project_path}"
|
461
|
+
puts "缓存启用: #{@cache_enabled}"
|
462
|
+
|
463
|
+
proj_path = get_project_path
|
464
|
+
root_cmd = @command_group || @current_command
|
465
|
+
|
466
|
+
if root_cmd && @memory_selections.dig(proj_path, root_cmd)
|
467
|
+
puts "当前缓存的选择:"
|
468
|
+
@memory_selections[proj_path][root_cmd].each do |k, v|
|
469
|
+
next if k.to_s.start_with?('__') # 跳过内部字段
|
470
|
+
puts " #{k}: #{v.inspect}"
|
471
|
+
end
|
472
|
+
end
|
473
|
+
puts "================================\n"
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|