Class: Pindo::PindoContext
- Inherits:
-
Object
- Object
- Pindo::PindoContext
- Includes:
- Singleton
- Defined in:
- lib/pindo/base/pindocontext.rb
Defined Under Namespace
Modules: SelectionKey
Instance Attribute Summary collapse
-
#current_command ⇒ Object
readonly
Returns the value of attribute current_command.
-
#current_directory ⇒ Object
readonly
Returns the value of attribute current_directory.
Instance Method Summary collapse
-
#cache_enabled? ⇒ Boolean
检查缓存是否启用.
-
#clear_current_cache ⇒ Object
清除当前上下文的缓存.
-
#confirm_and_apply_cache ⇒ Object
确认并应用缓存(供命令在 run 函数中调用) 返回值:true 表示使用缓存,false 表示不使用缓存.
-
#debug_info ⇒ Object
调试信息.
-
#enable_cache(enabled = true) ⇒ Object
启用/禁用缓存.
-
#get_project_path ⇒ Object
内部使用的项目路径获取方法 优先使用已设置的目录,如果没有则尝试获取Git仓库根目录.
-
#get_selection(key) ⇒ Object
获取用户选择(三级结构访问).
-
#has_selection?(key) ⇒ Boolean
检查是否有缓存的选择.
-
#initialize ⇒ PindoContext
constructor
A new instance of PindoContext.
-
#load_and_apply_jps_config(project_dir = nil) ⇒ Object
加载 JPSBuildConfig.json 并覆盖项目名称(如果存在) 应在 confirm_and_apply_cache 之前调用.
-
#nested_call? ⇒ Boolean
是否是嵌套调用.
-
#project_path ⇒ Object
获取当前项目路径(统一的获取方法,确保一致性).
-
#reset_context ⇒ Object
重置上下文(顶层命令结束时调用).
-
#root_command ⇒ Object
获取当前根命令.
-
#set_context(command, directory = nil, options = {}) ⇒ Object
设置当前上下文.
-
#set_selection(key, value) ⇒ Object
设置用户选择(三级结构:项目路径 -> 根命令 -> 键值).
-
#top_level_command? ⇒ Boolean
是否是顶层命令(非嵌套).
-
#verbose? ⇒ Boolean
判断是否处于 verbose 模式.
Constructor Details
#initialize ⇒ PindoContext
Returns a new instance of PindoContext.
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/pindo/base/pindocontext.rb', line 20 def initialize @current_command = nil # 根命令(第一个设置的命令) @current_directory = nil # 项目路径 @memory_selections = {} # 三级结构的内存缓存 @file_cache_loaded = false # 标记文件缓存是否已加载 @cache_enabled = false # 默认禁用缓存 @command_group = nil # 命令组名称 @verbose = false # 是否输出详细日志 @loaded_file_cache = nil # 已加载但未应用的文件缓存数据 @cache_confirmed = false # 标记缓存确认是否已完成 ensure_cache_dir end |
Instance Attribute Details
#current_command ⇒ Object (readonly)
Returns the value of attribute current_command.
18 19 20 |
# File 'lib/pindo/base/pindocontext.rb', line 18 def current_command @current_command end |
#current_directory ⇒ Object (readonly)
Returns the value of attribute current_directory.
18 19 20 |
# File 'lib/pindo/base/pindocontext.rb', line 18 def current_directory @current_directory end |
Instance Method Details
#cache_enabled? ⇒ Boolean
检查缓存是否启用
163 164 165 |
# File 'lib/pindo/base/pindocontext.rb', line 163 def cache_enabled? @cache_enabled end |
#clear_current_cache ⇒ Object
清除当前上下文的缓存
206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/pindo/base/pindocontext.rb', line 206 def clear_current_cache return unless @cache_enabled proj_path = get_project_path cmd = root_command return unless proj_path && cmd if @memory_selections[proj_path] && @memory_selections[proj_path][cmd] @memory_selections[proj_path].delete(cmd) @memory_selections.delete(proj_path) if @memory_selections[proj_path].empty? save_file_cache puts "[PindoContext] 清除缓存: [#{proj_path}][#{cmd}]" if verbose? end end |
#confirm_and_apply_cache ⇒ Object
确认并应用缓存(供命令在 run 函数中调用)返回值:true 表示使用缓存,false 表示不使用缓存
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
# File 'lib/pindo/base/pindocontext.rb', line 463 def confirm_and_apply_cache return false unless @cache_enabled return false unless @loaded_file_cache # 如果已经确认过缓存,直接返回(避免嵌套调用时重复询问) if @cache_confirmed puts "[PindoContext] 缓存已确认,跳过重复询问" if verbose? # 检查内存中是否已有缓存数据 project_path = get_project_path root_command = @command_group || @current_command return @memory_selections.dig(project_path, root_command) != nil end project_path = get_project_path root_command = @command_group || @current_command return false unless project_path && root_command # 检查三级结构中是否有当前上下文的缓存 cached_selections = @loaded_file_cache.dig(project_path, root_command) unless cached_selections && !cached_selections.empty? puts "[PindoContext] 当前上下文没有缓存数据" if verbose? return false end # 根据命令组显示更友好的描述 group_desc = case root_command when 'ios:autobuild' 'iOS 构建' when 'and:autobuild', 'android:autobuild' 'Android 构建' when 'web:autobuild' 'Web 构建' else @current_command # 其他命令显示原始命令名 end puts "\n检测到之前的选择 (#{group_desc}):" puts "────────────────────────────────────────" cached_selections.each do |key, value| # 跳过内部字段 next if key.to_s.start_with?('__') case key.to_s when 'bundle_id' puts " Bundle ID: #{value}" when 'project_name', 'app_key' # 兼容旧的 app_key puts " 项目名称: #{value}" when 'tag_decision' if value.is_a?(Hash) action_desc = value['description'] || value['action'] puts " Tag决定: #{action_desc}" end when 'cert_type' puts " 证书类型: #{value}" end end puts "────────────────────────────────────────" # 检查是否设置了强制编译环境变量 force_build = ENV['PINDO_FORCE_BUILD'] confirm = false if force_build && !force_build.empty? # 环境变量存在,自动使用缓存 puts "\n检测到 PINDO_FORCE_BUILD 环境变量,自动使用缓存的选择" confirm = true else # 询问用户是否使用缓存 require 'highline/import' cli = HighLine.new confirm = cli.agree("\n是否使用以上缓存的选择? (y/n) ") end if confirm puts "使用缓存的选择\n" unless force_build # 恢复当前上下文的文件缓存到内存缓存 @memory_selections[project_path] ||= {} @memory_selections[project_path][root_command] ||= {} cached_selections.each do |key, value| symbol_key = key.to_sym @memory_selections[project_path][root_command][symbol_key] = symbolize_keys(value) end # 标记缓存已确认,避免嵌套调用时重复询问 @cache_confirmed = true return true else puts "清除缓存,重新选择\n" # 清除当前上下文的文件缓存(三级结构) file_path = cache_file_path if @loaded_file_cache[project_path] && @loaded_file_cache[project_path][root_command] @loaded_file_cache[project_path].delete(root_command) # 如果项目路径下没有任何命令缓存了,删除项目路径键 @loaded_file_cache.delete(project_path) if @loaded_file_cache[project_path].empty? # 保存清理后的缓存到文件 save_file_cache end # 标记缓存已确认(用户选择不使用) @cache_confirmed = true return false end end |
#debug_info ⇒ Object
调试信息
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/pindo/base/pindocontext.rb', line 569 def debug_info puts "\n=== PindoContext Debug Info ===" puts "当前命令: #{@current_command || '无'}" puts "命令组: #{@command_group || '无'}" puts "设置的目录: #{@current_directory || '未设置'}" puts "实际项目路径: #{get_project_path}" puts "缓存启用: #{@cache_enabled}" proj_path = get_project_path root_cmd = @command_group || @current_command if root_cmd && @memory_selections.dig(proj_path, root_cmd) puts "当前缓存的选择:" @memory_selections[proj_path][root_cmd].each do |k, v| next if k.to_s.start_with?('__') # 跳过内部字段 puts " #{k}: #{v.inspect}" end end puts "================================\n" end |
#enable_cache(enabled = true) ⇒ Object
启用/禁用缓存
154 155 156 157 158 159 160 |
# File 'lib/pindo/base/pindocontext.rb', line 154 def enable_cache(enabled = true) @cache_enabled = enabled if enabled && !@file_cache_loaded && @current_command load_file_cache @file_cache_loaded = true end end |
#get_project_path ⇒ Object
内部使用的项目路径获取方法优先使用已设置的目录,如果没有则尝试获取Git仓库根目录
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/pindo/base/pindocontext.rb', line 189 def get_project_path # 如果已经设置了目录,直接返回 return @current_directory if @current_directory # 尝试获取Git仓库根目录 begin git_root = `git rev-parse --show-toplevel 2>/dev/null`.strip return git_root if $?.success? && !git_root.empty? rescue # git命令失败 end # 最后的后备:使用当前目录 Dir.pwd end |
#get_selection(key) ⇒ Object
获取用户选择(三级结构访问)
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/pindo/base/pindocontext.rb', line 128 def get_selection(key) # 使用统一的项目路径获取方法 project_path = get_project_path root_command = @command_group || @current_command return nil unless project_path && root_command # 从三级结构中获取值(总是从内存获取,不管是否启用缓存) value = @memory_selections.dig(project_path, root_command, key) if value puts "[PindoContext] 从内存获取: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}" if verbose? else puts "[PindoContext] 内存中未找到: [#{project_path}][#{root_command}][#{key}]" if verbose? end value end |
#has_selection?(key) ⇒ Boolean
检查是否有缓存的选择
148 149 150 151 |
# File 'lib/pindo/base/pindocontext.rb', line 148 def has_selection?(key) # 总是检查内存中是否有值,不管是否启用缓存 !get_selection(key).nil? end |
#load_and_apply_jps_config(project_dir = nil) ⇒ Object
加载 JPSBuildConfig.json 并覆盖项目名称(如果存在)应在 confirm_and_apply_cache 之前调用
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/pindo/base/pindocontext.rb', line 416 def load_and_apply_jps_config(project_dir = nil) project_dir ||= get_project_path # 判断工程类型并确定配置文件路径 # Unity 工程:ProjectSettings/JPSBuildConfig.json # iOS/Android 工程:JPSBuildConfig.json config_file = nil project_type = nil # 检查是否是 Unity 工程(存在 ProjectSettings 目录) if File.directory?(File.join(project_dir, 'ProjectSettings')) config_file = File.join(project_dir, 'ProjectSettings', 'JPSBuildConfig.json') project_type = 'Unity' else # iOS/Android 工程,直接在根目录 config_file = File.join(project_dir, 'JPSBuildConfig.json') project_type = 'iOS/Android' end unless File.exist?(config_file) puts "[PindoContext] JPSBuildConfig.json 不存在 (#{project_type} 工程),跳过" if verbose? return nil end begin config_content = File.read(config_file) jps_config = JSON.parse(config_content) if jps_config['project_name'] && !jps_config['project_name'].empty? project_name = jps_config['project_name'] puts "[PindoContext] 从 JPSBuildConfig.json 加载项目名称 (#{project_type}): #{project_name}" if verbose? # 设置到当前上下文的缓存中 set_selection(SelectionKey::PROJECT_NAME, project_name) puts "使用 JPS 配置的项目名称: #{project_name}" return project_name end rescue => e puts "[PindoContext] 加载 JPSBuildConfig.json 失败: #{e.message}" if verbose? end nil end |
#nested_call? ⇒ Boolean
是否是嵌套调用
168 169 170 |
# File 'lib/pindo/base/pindocontext.rb', line 168 def nested_call? !@current_command.nil? end |
#project_path ⇒ Object
获取当前项目路径(统一的获取方法,确保一致性)
183 184 185 |
# File 'lib/pindo/base/pindocontext.rb', line 183 def project_path get_project_path end |
#reset_context ⇒ Object
重置上下文(顶层命令结束时调用)
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/pindo/base/pindocontext.rb', line 83 def reset_context # 仅在启用缓存时保存文件缓存 save_file_cache if @cache_enabled && @current_command @current_command = nil @current_directory = nil @file_cache_loaded = false @cache_enabled = false @command_group = nil @cache_confirmed = false # 暂不清理内存缓存,让同一进程内可以复用 end |
#root_command ⇒ Object
获取当前根命令
178 179 180 |
# File 'lib/pindo/base/pindocontext.rb', line 178 def root_command @command_group || @current_command end |
#set_context(command, directory = nil, options = {}) ⇒ Object
设置当前上下文
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 |
# File 'lib/pindo/base/pindocontext.rb', line 39 def set_context(command, directory = nil, = {}) # 如果已有命令在执行,这是嵌套调用,不需要做任何事 unless @current_command.nil? puts "[PindoContext] 嵌套调用 #{command},使用已有上下文 (根命令: #{@current_command},命令组: #{@command_group})" if verbose? return end # 第一次设置,是顶层命令 @current_command = command # 保持原始命令名称 @current_directory = directory || Dir.pwd # 固定项目目录 # 从选项中获取缓存配置 @cache_enabled = [:cache_enabled] || false @verbose = [:verbose] || false # 使用 get_command_group 来确定缓存组 @command_group = get_command_group(command) if verbose? puts "\n[PindoContext] ========== 设置顶层命令上下文 ==========" puts "[PindoContext] 命令: #{command}" puts "[PindoContext] 目录: #{@current_directory}" puts "[PindoContext] 缓存启用: #{@cache_enabled}" puts "[PindoContext] 命令组: #{@command_group}" puts "[PindoContext] options: #{options.inspect}" end # 仅在启用缓存时加载文件缓存(不确认,只加载到临时变量) if @cache_enabled && !@file_cache_loaded puts "[PindoContext] 准备加载文件缓存..." if verbose? load_file_cache @file_cache_loaded = true else if verbose? if !@cache_enabled puts "[PindoContext] 缓存未启用,跳过文件缓存加载" elsif @file_cache_loaded puts "[PindoContext] 文件缓存已加载,跳过重复加载" end end end puts "[PindoContext] ======================================\n" if verbose? end |
#set_selection(key, value) ⇒ Object
设置用户选择(三级结构:项目路径 -> 根命令 -> 键值)
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 |
# File 'lib/pindo/base/pindocontext.rb', line 97 def set_selection(key, value) # 构建三级键 - 使用统一的项目路径获取方法 project_path = get_project_path root_command = @command_group || @current_command # 如果没有有效的项目路径或命令,不保存 unless project_path && root_command puts "[PindoContext] 警告: 无法保存选择,缺少项目路径或命令上下文" return end # 初始化三级结构(总是保存到内存,不管是否启用缓存) @memory_selections[project_path] ||= {} @memory_selections[project_path][root_command] ||= {} @memory_selections[project_path][root_command][key] = value # 更新该命令组的最后修改时间 @memory_selections[project_path][root_command]['__last_modified__'] = Time.now.to_i puts "[PindoContext] 保存到内存: [#{project_path}][#{root_command}][#{key}] = #{value.inspect}" if verbose? # 仅在启用缓存时保存到文件 if @cache_enabled save_file_cache puts "[PindoContext] 已保存到文件缓存" if verbose? else puts "[PindoContext] 缓存未启用,仅保存到内存" if verbose? end end |
#top_level_command? ⇒ Boolean
是否是顶层命令(非嵌套)
173 174 175 |
# File 'lib/pindo/base/pindocontext.rb', line 173 def top_level_command? @current_command.nil? end |
#verbose? ⇒ Boolean
判断是否处于 verbose 模式
34 35 36 |
# File 'lib/pindo/base/pindocontext.rb', line 34 def verbose? @verbose || ENV['PINDO_VERBOSE'] == '1' || ENV['PINDO_DEBUG'] == '1' end |