pindo 5.3.7 → 5.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3dda2ad2ab5ff48d50a3ff942ac1407f1a641fe132698af831e86153695ab822
4
- data.tar.gz: '08347a7f63339395c8572cfed87bc6ab3aac40289dece2ff52ba5486a180c879'
3
+ metadata.gz: 11f6f7b05adc236bf8e379152b9e2d6dbd1bb62da99067637915d3f17768fe77
4
+ data.tar.gz: 7dd2e73b4bb8edb542d3f274eecf64d3c76b8877ac76aa31ca0e574e7606e3bd
5
5
  SHA512:
6
- metadata.gz: a9535a1eb328a8f8b38eebaccff014192b485d818c9fbe5a1b1053e720b8505f1b3a2568105fa4d4ee8206690e11bf6867222e3f74bbb89a45dde7d5d30ab7ba
7
- data.tar.gz: ddc013f1c82a0b7e6705612eaf9e5c23006fab8ccb12c937facf9e6769b1de6d77529df0b0ff52fc4cd6b1beb3ebd0011591fc81af81b61757cc18c891719a2f
6
+ metadata.gz: 4396cfc57f38554634ca62437021ef29c193a347ffbe460a09cf1bfb9f8ac8e0d1e6e584628c044be1935d41be4e5b131c6d9036f3527d9031ab821e79e713e4
7
+ data.tar.gz: 135931aae0cdc3c823e59764611f6e64d30d7e58775c1975776073a551b7e849b937859ba9283f45ca3e40dc37035f23594732fd51fb4b943cb1a2c9bd928783
@@ -10,75 +10,124 @@ module Pindo
10
10
  attr_reader :current_command, :current_directory
11
11
 
12
12
  def initialize
13
- @current_command = nil
14
- @current_directory = nil
15
- @is_nested_call = false
16
- @memory_selections = {} # 内存缓存
17
- @file_cache_loaded = false # 标记文件缓存是否已加载
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
+ @verbose = false # 是否输出详细日志
18
20
  ensure_cache_dir
19
21
  end
20
22
 
23
+ # 判断是否处于 verbose 模式
24
+ def verbose?
25
+ @verbose || ENV['PINDO_VERBOSE'] == '1' || ENV['PINDO_DEBUG'] == '1'
26
+ end
27
+
21
28
  # 设置当前上下文
22
- def set_context(command, directory = nil)
23
- # 判断是否是嵌套调用
24
- if @current_command.nil?
25
- # 第一次设置,是顶层命令
26
- @is_nested_call = false
27
- @current_command = normalize_command(command)
28
- @current_directory = directory || Dir.pwd
29
-
30
- # 顶层命令时加载文件缓存并确认
31
- if !@file_cache_loaded
32
- load_file_cache_with_confirmation
33
- @file_cache_loaded = true
34
- end
29
+ def set_context(command, directory = nil, options = {})
30
+ # 如果已有命令在执行,这是嵌套调用,不需要做任何事
31
+ unless @current_command.nil?
32
+ puts "[PindoContext] 嵌套调用 #{command},使用已有上下文 (根命令: #{@current_command},命令组: #{@command_group})" if verbose?
33
+ return
34
+ end
35
+
36
+ # 第一次设置,是顶层命令
37
+ @current_command = command # 保持原始命令名称
38
+ @current_directory = directory || Dir.pwd # 固定项目目录
39
+
40
+ # 从选项中获取缓存配置
41
+ @cache_enabled = options[:cache_enabled] || false
42
+ @verbose = options[:verbose] || false
43
+ # 使用 get_command_group 来确定缓存组
44
+ @command_group = get_command_group(command)
45
+
46
+ if verbose?
47
+ puts "\n[PindoContext] ========== 设置顶层命令上下文 =========="
48
+ puts "[PindoContext] 命令: #{command}"
49
+ puts "[PindoContext] 目录: #{@current_directory}"
50
+ puts "[PindoContext] 缓存启用: #{@cache_enabled}"
51
+ puts "[PindoContext] 命令组: #{@command_group}"
52
+ puts "[PindoContext] options: #{options.inspect}"
53
+ end
35
54
 
36
- puts "[PindoContext] 顶层命令: #{command}" if ENV['PINDO_DEBUG']
55
+ # 仅在启用缓存时加载文件缓存
56
+ if @cache_enabled && !@file_cache_loaded
57
+ puts "[PindoContext] 准备加载文件缓存..." if verbose?
58
+ load_file_cache_with_confirmation
59
+ @file_cache_loaded = true
37
60
  else
38
- # 已有命令在执行,是嵌套调用
39
- @is_nested_call = true
40
- # 保持原有的命令组不变,确保缓存共享
41
- puts "[PindoContext] 嵌套调用: #{command} (使用 #{@current_command} 的缓存)" if ENV['PINDO_DEBUG']
61
+ if verbose?
62
+ if !@cache_enabled
63
+ puts "[PindoContext] 缓存未启用,跳过文件缓存加载"
64
+ elsif @file_cache_loaded
65
+ puts "[PindoContext] 文件缓存已加载,跳过重复加载"
66
+ end
67
+ end
42
68
  end
69
+ puts "[PindoContext] ======================================\n" if verbose?
43
70
  end
44
71
 
45
72
  # 重置上下文(顶层命令结束时调用)
46
73
  def reset_context
47
- # 保存文件缓存
48
- save_file_cache if @current_command && !@is_nested_call
74
+ # 仅在启用缓存时保存文件缓存
75
+ save_file_cache if @cache_enabled && @current_command
49
76
 
50
77
  @current_command = nil
51
78
  @current_directory = nil
52
- @is_nested_call = false
53
79
  @file_cache_loaded = false
80
+ @cache_enabled = false
81
+ @command_group = nil
54
82
  # 暂不清理内存缓存,让同一进程内可以复用
55
83
  end
56
84
 
57
- # 设置用户选择
85
+ # 设置用户选择(三级结构:项目路径 -> 根命令 -> 键值)
58
86
  def set_selection(key, value)
59
- context_key = get_context_key
60
- return unless context_key
87
+ # 构建三级键 - 使用统一的项目路径获取方法
88
+ project_path = get_project_path
89
+ root_command = @command_group || @current_command
90
+
91
+ # 如果没有有效的项目路径或命令,不保存
92
+ unless project_path && root_command
93
+ puts "[PindoContext] 警告: 无法保存选择,缺少项目路径或命令上下文"
94
+ return
95
+ end
96
+
97
+ # 初始化三级结构(总是保存到内存,不管是否启用缓存)
98
+ @memory_selections[project_path] ||= {}
99
+ @memory_selections[project_path][root_command] ||= {}
100
+ @memory_selections[project_path][root_command][key] = value
61
101
 
62
- @memory_selections[context_key] ||= {}
63
- @memory_selections[context_key][key] = value
102
+ # 更新该命令组的最后修改时间
103
+ @memory_selections[project_path][root_command]['__last_modified__'] = Time.now.to_i
64
104
 
65
- # 立即保存到文件缓存
66
- save_file_cache
105
+ puts "[PindoContext] 保存到内存: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}" if verbose?
67
106
 
68
- if ENV['PINDO_DEBUG']
69
- puts "[PindoContext] 记录选择: #{key} = #{value.inspect}"
107
+ # 仅在启用缓存时保存到文件
108
+ if @cache_enabled
109
+ save_file_cache
110
+ puts "[PindoContext] 已保存到文件缓存" if verbose?
111
+ else
112
+ puts "[PindoContext] 缓存未启用,仅保存到内存" if verbose?
70
113
  end
71
114
  end
72
115
 
73
- # 获取用户选择
116
+ # 获取用户选择(三级结构访问)
74
117
  def get_selection(key)
75
- context_key = get_context_key
76
- return nil unless context_key
118
+ # 使用统一的项目路径获取方法
119
+ project_path = get_project_path
120
+ root_command = @command_group || @current_command
121
+
122
+ return nil unless project_path && root_command
77
123
 
78
- value = @memory_selections[context_key] && @memory_selections[context_key][key]
124
+ # 从三级结构中获取值(总是从内存获取,不管是否启用缓存)
125
+ value = @memory_selections.dig(project_path, root_command, key)
79
126
 
80
- if value && ENV['PINDO_DEBUG']
81
- puts "[PindoContext] 使用缓存: #{key} = #{value.inspect}"
127
+ if value
128
+ puts "[PindoContext] 从内存获取: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}" if verbose?
129
+ else
130
+ puts "[PindoContext] 内存中未找到: [#{project_path}][#{root_command}][#{key}]" if verbose?
82
131
  end
83
132
 
84
133
  value
@@ -86,18 +135,82 @@ module Pindo
86
135
 
87
136
  # 检查是否有缓存的选择
88
137
  def has_selection?(key)
138
+ # 总是检查内存中是否有值,不管是否启用缓存
89
139
  !get_selection(key).nil?
90
140
  end
91
141
 
142
+ # 启用/禁用缓存
143
+ def enable_cache(enabled = true)
144
+ @cache_enabled = enabled
145
+ if enabled && !@file_cache_loaded && @current_command
146
+ load_file_cache_with_confirmation
147
+ @file_cache_loaded = true
148
+ end
149
+ end
150
+
151
+ # 检查缓存是否启用
152
+ def cache_enabled?
153
+ @cache_enabled
154
+ end
155
+
92
156
  # 是否是嵌套调用
93
157
  def nested_call?
94
- @is_nested_call
158
+ !@current_command.nil?
159
+ end
160
+
161
+ # 是否是顶层命令(非嵌套)
162
+ def top_level_command?
163
+ @current_command.nil?
164
+ end
165
+
166
+ # 获取当前根命令
167
+ def root_command
168
+ @command_group || @current_command
169
+ end
170
+
171
+ # 获取当前项目路径(统一的获取方法,确保一致性)
172
+ def project_path
173
+ get_project_path
174
+ end
175
+
176
+ # 内部使用的项目路径获取方法
177
+ # 优先使用已设置的目录,如果没有则尝试获取Git仓库根目录
178
+ def get_project_path
179
+ # 如果已经设置了目录,直接返回
180
+ return @current_directory if @current_directory
181
+
182
+ # 尝试获取Git仓库根目录
183
+ begin
184
+ git_root = `git rev-parse --show-toplevel 2>/dev/null`.strip
185
+ return git_root if $?.success? && !git_root.empty?
186
+ rescue
187
+ # git命令失败
188
+ end
189
+
190
+ # 最后的后备:使用当前目录
191
+ Dir.pwd
192
+ end
193
+
194
+ # 清除当前上下文的缓存
195
+ def clear_current_cache
196
+ return unless @cache_enabled
197
+
198
+ proj_path = get_project_path
199
+ cmd = root_command
200
+ return unless proj_path && cmd
201
+
202
+ if @memory_selections[proj_path] && @memory_selections[proj_path][cmd]
203
+ @memory_selections[proj_path].delete(cmd)
204
+ @memory_selections.delete(proj_path) if @memory_selections[proj_path].empty?
205
+ save_file_cache
206
+ puts "[PindoContext] 清除缓存: [#{proj_path}][#{cmd}]" if verbose?
207
+ end
95
208
  end
96
209
 
97
210
  # 选择键定义
98
211
  module SelectionKey
99
212
  TAG_DECISION = :tag_decision # 打Tag决定
100
- APP_KEY = :app_key # 项目名称/App代号
213
+ PROJECT_NAME = :project_name # 项目名称
101
214
  BUNDLE_ID = :bundle_id # Bundle ID
102
215
  CERT_TYPE = :cert_type # 证书类型
103
216
  end
@@ -116,35 +229,65 @@ module Pindo
116
229
  File.join(cache_dir, 'context_selections.json')
117
230
  end
118
231
 
119
- # 加载文件缓存并确认
232
+ # 加载文件缓存并确认(三级结构)
120
233
  def load_file_cache_with_confirmation
121
234
  file_path = cache_file_path
122
- return unless File.exist?(file_path)
235
+
236
+ puts "[PindoContext] 检查文件缓存: #{file_path}" if verbose?
237
+
238
+ unless File.exist?(file_path)
239
+ puts "[PindoContext] 文件缓存不存在,跳过加载" if verbose?
240
+ return
241
+ end
123
242
 
124
243
  begin
125
244
  file_content = File.read(file_path)
126
245
  file_cache = JSON.parse(file_content)
127
246
 
128
- # 获取当前上下文的缓存
129
- context_key = get_context_key
130
- cached_selections = file_cache[context_key]
247
+ # 清理过期缓存(超过7天)
248
+ file_cache = clean_expired_cache(file_cache)
249
+
250
+ # 获取当前项目和命令的缓存
251
+ project_path = get_project_path
252
+ root_command = @command_group || @current_command
253
+
254
+ puts "[PindoContext] 查找缓存: [#{project_path}][#{root_command}]" if verbose?
255
+
256
+ # 检查三级结构中是否有当前上下文的缓存
257
+ cached_selections = file_cache.dig(project_path, root_command)
131
258
 
132
259
  if cached_selections && !cached_selections.empty?
133
- # 显示缓存的选择
134
- puts "\n检测到之前的选择:"
260
+ # 根据命令组显示更友好的描述
261
+ group_desc = case root_command
262
+ when 'ios:autobuild'
263
+ 'iOS 构建'
264
+ when 'and:autobuild', 'android:autobuild'
265
+ 'Android 构建'
266
+ when 'web:autobuild'
267
+ 'Web 构建'
268
+ else
269
+ @current_command # 其他命令显示原始命令名
270
+ end
271
+
272
+ puts "\n检测到之前的选择 (#{group_desc}):"
135
273
  puts "────────────────────────────────────────"
136
274
 
137
275
  cached_selections.each do |key, value|
138
- case key
139
- when 'bundle_id', :bundle_id
276
+ # 跳过内部字段
277
+ next if key.to_s.start_with?('__')
278
+
279
+ case key.to_s
280
+ when 'bundle_id'
140
281
  puts " Bundle ID: #{value}"
141
- when 'app_key', :app_key
142
- puts " App代号: #{value}"
143
- when 'tag_decision', :tag_decision
282
+ when 'project_name', 'app_key' # 兼容旧的 app_key
283
+ puts " 项目名称: #{value}"
284
+ when 'tag_decision'
144
285
  if value.is_a?(Hash)
145
286
  action_desc = value['description'] || value['action']
146
287
  puts " Tag决定: #{action_desc}"
147
288
  end
289
+ when 'cert_type'
290
+ puts " 证书类型: #{value}"
148
291
  end
149
292
  end
150
293
  puts "────────────────────────────────────────"
@@ -156,100 +299,185 @@ module Pindo
156
299
 
157
300
  if confirm
158
301
  puts "使用缓存的选择\n"
159
- # 合并文件缓存到内存缓存
160
- file_cache.each do |ctx_key, selections|
161
- @memory_selections[ctx_key] ||= {}
162
- selections.each do |key, value|
163
- symbol_key = key.to_sym
164
- @memory_selections[ctx_key][symbol_key] = value
302
+ # 恢复三级结构的文件缓存到内存缓存
303
+ file_cache.each do |proj_path, commands|
304
+ @memory_selections[proj_path] ||= {}
305
+ commands.each do |cmd, selections|
306
+ @memory_selections[proj_path][cmd] ||= {}
307
+ selections.each do |key, value|
308
+ symbol_key = key.to_sym
309
+ @memory_selections[proj_path][cmd][symbol_key] = value
310
+ end
165
311
  end
166
312
  end
167
313
  else
168
314
  puts "清除缓存,重新选择\n"
169
- # 清除当前上下文的文件缓存
170
- file_cache.delete(context_key)
315
+ # 清除当前上下文的文件缓存(三级结构)
316
+ if file_cache[project_path] && file_cache[project_path][root_command]
317
+ file_cache[project_path].delete(root_command)
318
+ # 如果项目路径下没有任何命令缓存了,删除项目路径键
319
+ file_cache.delete(project_path) if file_cache[project_path].empty?
320
+ end
171
321
  File.write(file_path, JSON.pretty_generate(file_cache))
172
322
  # 不加载任何缓存到内存
173
323
  end
174
324
  else
175
- # 加载其他上下文的缓存(不需要确认)
176
- file_cache.each do |ctx_key, selections|
177
- next if ctx_key == context_key # 跳过当前上下文(已经是空的)
178
- @memory_selections[ctx_key] ||= {}
179
- selections.each do |key, value|
180
- symbol_key = key.to_sym
181
- @memory_selections[ctx_key][symbol_key] = value
325
+ # 加载整个文件缓存到内存(不需要确认)
326
+ file_cache.each do |proj_path, commands|
327
+ @memory_selections[proj_path] ||= {}
328
+ commands.each do |cmd, selections|
329
+ # 跳过当前上下文(已经是空的)
330
+ next if proj_path == project_path && cmd == root_command
331
+
332
+ @memory_selections[proj_path][cmd] ||= {}
333
+ selections.each do |key, value|
334
+ symbol_key = key.to_sym
335
+ @memory_selections[proj_path][cmd][symbol_key] = value
336
+ end
182
337
  end
183
338
  end
184
339
  end
185
340
 
186
- puts "[PindoContext] 处理文件缓存: #{file_path}" if ENV['PINDO_DEBUG']
341
+ puts "[PindoContext] 处理文件缓存: #{file_path}" if verbose?
187
342
  rescue => e
188
- puts "[PindoContext] 加载缓存失败: #{e.message}" if ENV['PINDO_DEBUG']
343
+ puts "[PindoContext] 加载缓存失败: #{e.message}" if verbose?
189
344
  end
190
345
  end
191
346
 
192
- # 保存文件缓存
347
+ # 保存文件缓存(三级结构)
193
348
  def save_file_cache
194
349
  file_path = cache_file_path
195
350
 
196
351
  begin
197
- # 转换内存缓存为可序列化的格式
352
+ # 转换内存缓存为可序列化的格式(保持三级结构)
198
353
  file_cache = {}
199
- @memory_selections.each do |context_key, selections|
200
- file_cache[context_key] = {}
201
- selections.each do |key, value|
202
- # 将符号键转换为字符串
203
- string_key = key.to_s
204
- file_cache[context_key][string_key] = value
354
+ @memory_selections.each do |project_path, commands|
355
+ file_cache[project_path] ||= {}
356
+ commands.each do |command, selections|
357
+ file_cache[project_path][command] ||= {}
358
+ selections.each do |key, value|
359
+ # 将符号键转换为字符串
360
+ string_key = key.to_s
361
+ file_cache[project_path][command][string_key] = value
362
+ end
205
363
  end
206
364
  end
207
365
 
208
366
  # 写入文件
209
367
  File.write(file_path, JSON.pretty_generate(file_cache))
210
368
 
211
- puts "[PindoContext] 保存文件缓存: #{file_path}" if ENV['PINDO_DEBUG']
369
+ puts "[PindoContext] 保存文件缓存: #{file_path}" if verbose?
212
370
  rescue => e
213
- puts "[PindoContext] 保存缓存失败: #{e.message}" if ENV['PINDO_DEBUG']
371
+ puts "[PindoContext] 保存缓存失败: #{e.message}" if verbose?
214
372
  end
215
373
  end
216
374
 
217
- # 命令归一化,将相关命令映射到同一组
218
- def normalize_command(command)
375
+ # 获取命令组名称(统一管理命令缓存组)
376
+ def get_command_group(command)
377
+ # 根据需求文档定义命令组,相关命令共享同一缓存
219
378
  case command
220
- when 'ios:autobuild', 'unity:ipa'
221
- 'ios_build_group'
222
- when 'android:autobuild', 'android:build', 'unity:apk'
223
- 'android_build_group'
224
- when 'unity:webgl'
225
- 'webgl_build_group'
379
+ # iOS 构建相关命令组
380
+ when 'unity:ipa'
381
+ 'ios:autobuild'
382
+
383
+ # Android 构建相关命令组
384
+ when 'unity:apk'
385
+ 'and:autobuild'
386
+
387
+ # Web 构建相关命令组
388
+ when 'unity:web'
389
+ 'web:autobuild'
390
+
226
391
  else
227
- command
392
+ command # 其他命令使用独立缓存(命令名本身作为组)
228
393
  end
229
394
  end
230
395
 
231
- # 生成上下文键
232
- def get_context_key
233
- return nil unless @current_command
396
+ # 清理过期缓存(超过7天的缓存)
397
+ def clean_expired_cache(cache_data)
398
+ return {} unless cache_data.is_a?(Hash)
399
+
400
+ current_time = Time.now.to_i
401
+ seven_days_in_seconds = 7 * 24 * 60 * 60
402
+ cleaned_cache = {}
403
+ expired_commands = []
404
+ expired_projects = []
405
+
406
+ cache_data.each do |project_path, commands|
407
+ # 初始化项目路径
408
+ cleaned_commands = {}
409
+
410
+ commands.each do |command, selections|
411
+ # 获取最后修改时间
412
+ last_modified = selections['__last_modified__']
413
+
414
+ # 如果没有时间戳,视为过期
415
+ if last_modified.nil?
416
+ expired_commands << "[#{project_path}][#{command}] (无时间戳)"
417
+ puts "[PindoContext] 清理无时间戳缓存: [#{project_path}][#{command}]" if verbose?
418
+ next
419
+ end
420
+
421
+ # 检查是否过期(超过7天)
422
+ if (current_time - last_modified.to_i) > seven_days_in_seconds
423
+ days_old = (current_time - last_modified.to_i) / (24 * 60 * 60)
424
+ expired_commands << "[#{project_path}][#{command}] (#{days_old}天前)"
425
+ puts "[PindoContext] 清理过期缓存 (#{days_old}天前): [#{project_path}][#{command}]" if verbose?
426
+ next
427
+ end
428
+
429
+ # 保留未过期的缓存
430
+ cleaned_commands[command] = selections
431
+ end
432
+
433
+ # 如果该项目路径下还有有效的命令缓存,保留它
434
+ if cleaned_commands.any?
435
+ cleaned_cache[project_path] = cleaned_commands
436
+ else
437
+ # 整个项目路径下的所有命令都过期了,删除整个项目路径
438
+ expired_projects << project_path
439
+ puts "[PindoContext] 删除空项目路径: #{project_path}" if verbose?
440
+ end
441
+ end
442
+
443
+ # 输出清理总结
444
+ if expired_commands.any? || expired_projects.any?
445
+ puts "[PindoContext] 缓存清理完成:"
446
+ if expired_commands.any?
447
+ puts " - 清理了 #{expired_commands.size} 个过期命令缓存"
448
+ expired_commands.each { |cmd| puts " • #{cmd}" } if verbose?
449
+ end
450
+ if expired_projects.any?
451
+ puts " - 删除了 #{expired_projects.size} 个空项目路径"
452
+ expired_projects.each { |proj| puts " • #{proj}" } if verbose?
453
+ end
234
454
 
235
- # 使用命令组和目录哈希作为键
236
- dir_hash = Digest::MD5.hexdigest(@current_directory || Dir.pwd)[0..7]
237
- "#{@current_command}:#{dir_hash}"
455
+ # 立即保存清理后的缓存到文件
456
+ File.write(cache_file_path, JSON.pretty_generate(cleaned_cache))
457
+ end
458
+
459
+ cleaned_cache
238
460
  end
239
461
 
462
+
240
463
  public
241
464
 
242
465
  # 调试信息
243
466
  def debug_info
244
467
  puts "\n=== PindoContext Debug Info ==="
245
468
  puts "当前命令: #{@current_command || '无'}"
246
- puts "当前目录: #{@current_directory || Dir.pwd}"
247
- puts "是否嵌套: #{@is_nested_call}"
248
- puts "上下文键: #{get_context_key || '无'}"
469
+ puts "命令组: #{@command_group || '无'}"
470
+ puts "设置的目录: #{@current_directory || '未设置'}"
471
+ puts "实际项目路径: #{get_project_path}"
472
+ puts "缓存启用: #{@cache_enabled}"
473
+
474
+ proj_path = get_project_path
475
+ root_cmd = @command_group || @current_command
249
476
 
250
- if @memory_selections[get_context_key]
477
+ if root_cmd && @memory_selections.dig(proj_path, root_cmd)
251
478
  puts "当前缓存的选择:"
252
- @memory_selections[get_context_key].each do |k, v|
479
+ @memory_selections[proj_path][root_cmd].each do |k, v|
480
+ next if k.to_s.start_with?('__') # 跳过内部字段
253
481
  puts " #{k}: #{v.inspect}"
254
482
  end
255
483
  end
@@ -14,6 +14,12 @@ module Pindo
14
14
  include Pindo::Githelper
15
15
 
16
16
  self.summary = '打包Android工程并发布到蒲公英'
17
+
18
+ # 启用缓存机制
19
+ def self.use_cache?
20
+ true # 此命令启用缓存
21
+ end
22
+
17
23
  self.description = <<-DESC
18
24
  编译Android包并支持上传到测试平台。
19
25
 
@@ -12,11 +12,18 @@ module Pindo
12
12
  class Command
13
13
  class Ios < Command
14
14
  class Autobuild < Ios
15
-
15
+
16
16
  include Appselect
17
17
  include Pindo::Githelper
18
18
  # 命令的简要说明 - 打包iOS工程并发布到蒲公英
19
19
  self.summary = '打包iOS工程并发布到蒲公英'
20
+
21
+ # 启用缓存机制
22
+ def self.use_cache?
23
+ true # 此命令启用缓存
24
+ end
25
+ # 缓存组已在 PindoContext#get_command_group 中定义
26
+ # ios:autobuild 与 unity:ipa 共享 'ios:autobuild' 缓存组
20
27
 
21
28
  # 命令的详细说明,包含用法示例
22
29
  self.description = <<-DESC
@@ -84,10 +91,6 @@ module Pindo
84
91
  def run
85
92
  pindo_project_dir = Dir.pwd
86
93
 
87
- # 设置 PindoContext 上下文
88
- context = Pindo::PindoContext.instance
89
- context.set_context('ios:autobuild', pindo_project_dir)
90
-
91
94
  build_helper = Pindo::BuildHelper.share_instance
92
95
  project_type = build_helper.project_type(pindo_project_dir)
93
96
 
@@ -13,6 +13,13 @@ module Pindo
13
13
  # 命令的简要说明 - 编译iOS工程并可选择上传到测试平台
14
14
  self.summary = '编译iOS工程,并支持上传ipa'
15
15
 
16
+ # 启用缓存机制
17
+ def self.use_cache?
18
+ true # 此命令启用缓存
19
+ end
20
+ # 缓存组已在 PindoContext#get_command_group 中定义
21
+ # ios:build 与 ios:autobuild 共享 'ios:autobuild' 缓存组
22
+
16
23
  # 命令的详细说明,包含用法示例
17
24
  self.description = <<-DESC
18
25
  编译iOS工程并生成ipa文件。
@@ -14,6 +14,11 @@ module Pindo
14
14
  # 命令的简要说明 - 编译Unity工程生成Android APK
15
15
  self.summary = '编译Unity工程生成Android APK'
16
16
 
17
+ # 启用缓存机制
18
+ def self.use_cache?
19
+ true # 此命令启用缓存
20
+ end
21
+
17
22
  # 命令的详细说明,包含用法示例
18
23
  self.description = <<-DESC
19
24
  编译Unity工程生成Android APK。
@@ -13,11 +13,18 @@ module Pindo
13
13
  class Ipa < Unity
14
14
 
15
15
  include Appselect
16
-
16
+
17
17
  include Pindo::Githelper
18
18
  # Unity IPA包编译和上传命令
19
19
  self.summary = '编译Unity工程生成iOS IPA并支持上传到测试平台'
20
20
 
21
+ # 启用缓存机制
22
+ def self.use_cache?
23
+ true # 此命令启用缓存
24
+ end
25
+ # 缓存组已在 PindoContext#get_command_group 中定义
26
+ # unity:ipa 与 ios:autobuild 共享 'ios:autobuild' 缓存组
27
+
21
28
  # 详细说明
22
29
  self.description = <<-DESC
23
30
  编译Unity工程生成iOS IPA并支持上传到测试平台。
@@ -158,9 +165,10 @@ module Pindo
158
165
  if @args_send_flag
159
166
  args_temp << "--send"
160
167
  end
161
-
168
+
169
+
162
170
  Dir.chdir(pindo_ios_project_dir)
163
-
171
+
164
172
  Pindo::Command::Ios::Autobuild::run(args_temp)
165
173
 
166
174
 
@@ -14,30 +14,35 @@ module Pindo
14
14
  include Appselect
15
15
 
16
16
  include Pindo::Githelper
17
- # Unity IPA包编译和上传命令
18
- self.summary = '编译Unity工程生成iOS IPA并支持上传到测试平台'
17
+ # Unity WebGL包编译和上传命令
18
+ self.summary = '编译Unity工程生成WebGL并支持上传到测试平台'
19
+
20
+ # 启用缓存机制
21
+ def self.use_cache?
22
+ true # 此命令启用缓存
23
+ end
19
24
 
20
25
  # 详细说明
21
26
  self.description = <<-DESC
22
- 编译Unity工程生成iOS IPA并支持上传到测试平台。
27
+ 编译Unity工程生成WebGL并支持上传到测试平台。
23
28
 
24
29
  支持功能:
25
30
 
26
- * 编译生成IPA
31
+ * 编译生成WebGL
27
32
 
28
- * 上传到测试平台
33
+ * 上传到测试平台
29
34
 
30
35
  * 发送测试通知
31
36
 
32
37
  使用示例:
33
38
 
34
- $ pindo unity ipa # 编译IPA
39
+ $ pindo unity web # 编译WebGL
35
40
 
36
- $ pindo unity ipa --upload # 编译并上传
41
+ $ pindo unity web --upload # 编译并上传
37
42
 
38
- $ pindo unity ipa --send # 编译上传并发送通知
43
+ $ pindo unity web --send # 编译上传并发送通知
39
44
 
40
- $ pindo unity ipa --proj=myapp # 指定项目名称
45
+ $ pindo unity web --proj=myapp # 指定项目名称
41
46
  DESC
42
47
 
43
48
  # 命令参数
@@ -49,7 +54,7 @@ module Pindo
49
54
  def self.options
50
55
  [
51
56
  ['--proj', '指定上传到测试平台的项目名称'],
52
- ['--upload', '上传编译后的IPA到测试平台'],
57
+ ['--upload', '上传编译后的WebGL到测试平台'],
53
58
  ['--send', '上传成功后发送测试通知'],
54
59
  ['--base', 'Unity工程编译lib模式'],
55
60
  ['--unity-version', '切换Unity版本']
@@ -16,6 +16,11 @@ module Pindo
16
16
 
17
17
  self.summary = '打包Unity WebGL包'
18
18
 
19
+ # 启用缓存机制
20
+ def self.use_cache?
21
+ true # 此命令启用缓存
22
+ end
23
+
19
24
  # 命令的详细说明,包含用法示例
20
25
  self.description = <<-DESC
21
26
  编译WebGL包并支持上传到测试平台。
data/lib/pindo/command.rb CHANGED
@@ -60,6 +60,13 @@ module Pindo
60
60
  self.version = VERSION
61
61
  self.description = 'pindo, make it easy!'
62
62
 
63
+ # 缓存配置:子类可以重写此方法来启用缓存
64
+ def self.use_cache?
65
+ false # 默认不使用缓存
66
+ end
67
+ # 注意:缓存组的定义已经移至 PindoContext#get_command_group 中统一管理
68
+ # 使用命令名作为组名,如 ios:autobuild, and:autobuild, web:autobuild
69
+
63
70
 
64
71
  DEFAULT_ROOT_OPTIONS = [
65
72
  ['--version', '查看pindo版本'],
@@ -67,6 +74,7 @@ module Pindo
67
74
 
68
75
  DEFAULT_OPTIONS = [
69
76
  ['--help', '查看命令行用法'],
77
+ ['--verbose', '显示详细的调试信息'],
70
78
  ]
71
79
 
72
80
 
@@ -90,23 +98,67 @@ module Pindo
90
98
  end
91
99
 
92
100
  def self.run(argv)
93
- # 设置上下文
94
- context = Pindo::PindoContext.instance
95
- command_name = self.command # 获取完整的命令名称,如 'ios:autobuild'
96
- context.set_context(command_name)
97
-
98
- begin
99
- result = super(argv)
100
- ensure
101
- # 确保在命令结束时重置上下文
102
- context.reset_context
103
- end
104
- result
101
+ # 直接调用父类的 run 方法
102
+ # PindoContext 的设置在 initialize 中处理
103
+ super(argv)
105
104
  end
106
105
 
107
106
  def initialize(argv)
108
107
  super
109
108
  @args_help_flag = argv.flag?('help', false)
109
+ @args_verbose_flag = argv.flag?('verbose', false)
110
+
111
+ # 设置全局 verbose 标志
112
+ ENV['PINDO_VERBOSE'] = '1' if @args_verbose_flag
113
+
114
+ # 在非抽象命令初始化时设置上下文
115
+ if !self.class.abstract_command? && !@args_help_flag
116
+ context = Pindo::PindoContext.instance
117
+
118
+ # 只在上下文未设置时才设置(避免重复设置)
119
+ if context.instance_variable_get(:@current_command).nil?
120
+ # 获取完整的命令路径
121
+ command_parts = []
122
+ current = self.class
123
+ while current < Pindo::Command
124
+ if current.command && current.command != 'pindo'
125
+ command_parts.unshift(current.command)
126
+ end
127
+ current = current.superclass
128
+ end
129
+ command_name = command_parts.empty? ? self.class.command : command_parts.join(':')
130
+
131
+ # 配置选项
132
+ cache_enabled_value = self.class.respond_to?(:use_cache?) ? self.class.use_cache? : false
133
+ options = {
134
+ cache_enabled: cache_enabled_value,
135
+ verbose: @args_verbose_flag
136
+ }
137
+
138
+ # 获取项目根目录(Git仓库根目录或当前目录)
139
+ project_dir = get_project_root_directory(Dir.pwd)
140
+
141
+ context.set_context(command_name, project_dir, options)
142
+ end
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ # 获取项目根目录(优先使用Git仓库根目录)
149
+ def get_project_root_directory(current_dir)
150
+ # 尝试获取Git仓库根目录
151
+ begin
152
+ git_root = `cd "#{current_dir}" && git rev-parse --show-toplevel 2>/dev/null`.strip
153
+ if $?.success? && !git_root.empty?
154
+ return git_root
155
+ end
156
+ rescue
157
+ # git命令失败,继续使用当前目录
158
+ end
159
+
160
+ # 如果不是Git仓库,返回当前目录
161
+ current_dir
110
162
  end
111
163
 
112
164
  end
@@ -263,8 +263,9 @@ module Pindo
263
263
  activities.each do |activity|
264
264
  intent_filters = activity.xpath("intent-filter")
265
265
  intent_filters.each do |intent_filter|
266
- has_main = intent_filter.xpath("action[@android:name='android.intent.action.MAIN']").any?
267
- has_launcher = intent_filter.xpath("category[@android:name='android.intent.category.LAUNCHER']").any?
266
+ # 修复:移除命名空间后,应该使用 @name 而不是 @android:name
267
+ has_main = intent_filter.xpath("action[@name='android.intent.action.MAIN']").any?
268
+ has_launcher = intent_filter.xpath("category[@name='android.intent.category.LAUNCHER']").any?
268
269
 
269
270
  if has_main && has_launcher
270
271
  best_manifest = manifest_path
@@ -277,6 +278,7 @@ module Pindo
277
278
  end
278
279
  rescue => e
279
280
  # 静默处理解析错误,继续尝试下一个文件
281
+ puts "解析 #{manifest_path} 时出错: #{e.message}" if ENV['PINDO_DEBUG']
280
282
  end
281
283
 
282
284
  break if best_activity
@@ -290,8 +292,8 @@ module Pindo
290
292
  scheme_exists = false
291
293
  existing_scheme = nil
292
294
 
293
- # 首先检查完全一致的scheme
294
- activity.xpath("intent-filter/data[@#{android_prefix}:scheme='#{scheme_name}']").each do |node|
295
+ # 首先检查完全一致的scheme(修复:移除命名空间后使用 @scheme)
296
+ activity.xpath("intent-filter/data[@scheme='#{scheme_name}']").each do |node|
295
297
  scheme_exists = true
296
298
  existing_scheme = scheme_name
297
299
  break
@@ -299,8 +301,8 @@ module Pindo
299
301
 
300
302
  # 如果没有找到完全一致的,检查可能格式不同的scheme
301
303
  if !scheme_exists
302
- activity.xpath("intent-filter/data[@#{android_prefix}:scheme]").each do |node|
303
- current_scheme = node["#{android_prefix}:scheme"]
304
+ activity.xpath("intent-filter/data[@scheme]").each do |node|
305
+ current_scheme = node["scheme"]
304
306
  normalized_current = current_scheme.to_s.downcase.strip.gsub(/[\s\-_]/, '')
305
307
 
306
308
  if normalized_current == scheme_name
@@ -389,7 +389,7 @@ module Pindo
389
389
  additional_args = {}
390
390
  additional_args[:platform] = platform if platform
391
391
  additional_args[:buildtype] = 'library' if isLibrary
392
-
392
+
393
393
  # 首先尝试使用GoodUnityBuild.BuildManager.BatchBuild
394
394
  result = execute_unity_command(unity_exe_full_path, project_path, additional_args)
395
395
 
@@ -537,7 +537,6 @@ module Pindo
537
537
  # 解析Unity进程信息
538
538
  def parse_unity_processes(processes_output, unity_exe_full_path: nil, project_path: nil)
539
539
  processes = []
540
- current_pid = Process.pid.to_s
541
540
 
542
541
  processes_output.lines.each do |line|
543
542
  # 解析 ps aux 输出格式
@@ -546,14 +545,14 @@ module Pindo
546
545
  pid = parts[1]
547
546
  command = parts[10..-1].join(' ')
548
547
 
549
- # 过滤掉grep进程本身、pindo进程和当前进程
550
- unless command.include?('grep') || command.include?('pindo') || pid == current_pid
548
+ # 过滤掉grep进程本身和pindo进程
549
+ unless command.include?('grep') || command.include?('pindo')
551
550
  # 精确匹配Unity进程
552
551
  is_relevant_unity_process = false
553
552
  match_reasons = []
554
553
 
555
554
  # 1. 必须是Unity Editor主进程(排除VS Code等其他进程)
556
- is_unity_editor = command.match?(/Unity\.app.*\/Unity/i) || command.match?(/Unity\.exe$/i)
555
+ is_unity_editor = command.match?(/Unity\.app.*\/Unity/i) || command.match?(/Unity\.exe/i)
557
556
 
558
557
  if is_unity_editor
559
558
  # 2. 检查是否是打开了指定项目的Unity进程
@@ -108,7 +108,7 @@ module Pindo
108
108
  # 检查缓存的 App Key
109
109
  require_relative '../../base/pindocontext'
110
110
  context = Pindo::PindoContext.instance
111
- cached_app_key = context.get_selection(Pindo::PindoContext::SelectionKey::APP_KEY)
111
+ cached_app_key = context.get_selection(Pindo::PindoContext::SelectionKey::PROJECT_NAME)
112
112
 
113
113
  if cached_app_key && proj_name_array.include?(cached_app_key)
114
114
  puts "\n使用之前选择的App代号: #{cached_app_key}"
@@ -135,7 +135,7 @@ module Pindo
135
135
 
136
136
  # 保存选择到缓存(排除自定义输入选项)
137
137
  if upload_proj_name && !upload_proj_name.include?("自定义输入")
138
- context.set_selection(Pindo::PindoContext::SelectionKey::APP_KEY, upload_proj_name)
138
+ context.set_selection(Pindo::PindoContext::SelectionKey::PROJECT_NAME, upload_proj_name)
139
139
  end
140
140
  end
141
141
 
data/lib/pindo/version.rb CHANGED
@@ -6,7 +6,7 @@ require 'time'
6
6
 
7
7
  module Pindo
8
8
 
9
- VERSION = "5.3.7"
9
+ VERSION = "5.4.1"
10
10
 
11
11
  class VersionCheck
12
12
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pindo
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.7
4
+ version: 5.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-09-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: claide
@@ -457,7 +457,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
457
457
  - !ruby/object:Gem::Version
458
458
  version: '0'
459
459
  requirements: []
460
- rubygems_version: 3.6.9
460
+ rubygems_version: 3.6.3
461
461
  specification_version: 3
462
462
  summary: easy work
463
463
  test_files: []