pindo 5.17.5 → 5.18.4

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +120 -38
  3. data/lib/pindo/command/android/autobuild.rb +81 -40
  4. data/lib/pindo/command/appstore/adhocbuild.rb +1 -1
  5. data/lib/pindo/command/appstore/autobuild.rb +1 -1
  6. data/lib/pindo/command/appstore/autoresign.rb +1 -1
  7. data/lib/pindo/command/appstore/updateid.rb +229 -0
  8. data/lib/pindo/command/appstore.rb +1 -0
  9. data/lib/pindo/command/ios/autobuild.rb +70 -33
  10. data/lib/pindo/command/ios/podpush.rb +1 -1
  11. data/lib/pindo/command/jps/apptest.rb +2 -2
  12. data/lib/pindo/command/jps/bind.rb +1 -1
  13. data/lib/pindo/command/jps/media.rb +1 -1
  14. data/lib/pindo/command/jps/upload.rb +52 -22
  15. data/lib/pindo/command/unity/autobuild.rb +61 -44
  16. data/lib/pindo/command/utils/allcopyconfig.rb +144 -0
  17. data/lib/pindo/command/utils/copyconfig.rb +207 -0
  18. data/lib/pindo/command/utils/icon.rb +2 -2
  19. data/lib/pindo/command/utils/renewbundleid.rb +199 -0
  20. data/lib/pindo/command/utils/renewcert.rb +56 -54
  21. data/lib/pindo/command/utils.rb +3 -0
  22. data/lib/pindo/command/web/autobuild.rb +32 -26
  23. data/lib/pindo/config/build_info_manager.rb +1 -3
  24. data/lib/pindo/module/android/android_build_helper.rb +193 -33
  25. data/lib/pindo/module/android/android_config_helper.rb +305 -88
  26. data/lib/pindo/module/android/android_project_helper.rb +69 -14
  27. data/lib/pindo/module/android/android_res_helper.rb +349 -51
  28. data/lib/pindo/module/android/keystore_helper.rb +611 -295
  29. data/lib/pindo/module/android/workflow_gradle_injector.rb +702 -0
  30. data/lib/pindo/module/appselect.rb +4 -4
  31. data/lib/pindo/module/appstore/bundleid_helper.rb +204 -14
  32. data/lib/pindo/module/build/build_helper.rb +110 -10
  33. data/lib/pindo/module/build/git_repo_helper.rb +4 -4
  34. data/lib/pindo/module/cert/mode/base_cert_operator.rb +8 -6
  35. data/lib/pindo/module/pgyer/pgyerhelper.rb +105 -42
  36. data/lib/pindo/module/task/core/task_executor.rb +2 -0
  37. data/lib/pindo/module/task/model/build/android_build_dev_task.rb +64 -6
  38. data/lib/pindo/module/task/model/git/git_commit_task.rb +70 -54
  39. data/lib/pindo/module/task/model/git/git_tag_task.rb +13 -9
  40. data/lib/pindo/module/task/model/jps/jps_upload_task.rb +104 -1
  41. data/lib/pindo/module/task/model/unity/unity_export_task.rb +2 -1
  42. data/lib/pindo/module/task/model/unity/unity_update_task.rb +2 -1
  43. data/lib/pindo/module/task/model/unity/unity_yoo_asset_task.rb +2 -1
  44. data/lib/pindo/module/task/model/unity_task.rb +2 -1
  45. data/lib/pindo/module/task/task_manager.rb +8 -0
  46. data/lib/pindo/module/unity/unity_helper.rb +13 -10
  47. data/lib/pindo/module/unity/unity_proc_helper.rb +27 -2
  48. data/lib/pindo/module/xcode/applovin_xcode_helper.rb +4 -2
  49. data/lib/pindo/module/xcode/res/xcode_res_constant.rb +72 -0
  50. data/lib/pindo/module/xcode/xcode_build_config.rb +36 -17
  51. data/lib/pindo/module/xcode/xcode_build_helper.rb +180 -23
  52. data/lib/pindo/module/xcode/xcode_project_helper.rb +1 -1
  53. data/lib/pindo/module/xcode/xcode_res_helper.rb +32 -16
  54. data/lib/pindo/options/groups/build_options.rb +16 -5
  55. data/lib/pindo/options/groups/git_options.rb +7 -5
  56. data/lib/pindo/options/groups/unity_options.rb +11 -0
  57. data/lib/pindo/options/helpers/bundleid_selector.rb +25 -0
  58. data/lib/pindo/options/helpers/git_constants.rb +7 -6
  59. data/lib/pindo/version.rb +2 -2
  60. metadata +10 -5
@@ -111,7 +111,10 @@ module Pindo
111
111
  )
112
112
  end
113
113
 
114
- # 3. 上传到 JPS
114
+ # 3. 自动解析上传描述(未手动指定时)
115
+ @upload_desc = resolve_upload_desc(file_to_upload) if @upload_desc.nil?
116
+
117
+ # 4. 上传到 JPS
115
118
  app_version_info = upload_to_jps(file_to_upload)
116
119
 
117
120
  {
@@ -158,6 +161,106 @@ module Pindo
158
161
  end
159
162
  end
160
163
 
164
+ # 根据依赖任务类型或 IPA 描述文件类型自动推断上传描述
165
+ # 规则:
166
+ # 依赖 IosBuildAdhocTask → "Commit id: <commit_id>"
167
+ # 依赖 IosBuildAppStoreTask → "重签名"
168
+ # 依赖其他 IosBuildTask 子类 → nil(不传描述)
169
+ # 直接上传 IPA(无构建依赖) → 检测描述文件类型后同上
170
+ def resolve_upload_desc(file_path)
171
+ # 路径1:检查任务依赖
172
+ if @dependencies && !@dependencies.empty?
173
+ @dependencies.each do |dep_id|
174
+ dep_task = get_dependency_task(dep_id)
175
+ next unless dep_task
176
+
177
+ class_name = dep_task.class.name || ''
178
+ is_ios_build = dep_task.class.ancestors.any? do |a|
179
+ a.name == 'Pindo::TaskSystem::IosBuildTask'
180
+ end
181
+ next unless is_ios_build
182
+
183
+ if class_name == 'Pindo::TaskSystem::IosBuildAdhocTask'
184
+ commit_id = get_current_commit_id
185
+ return commit_id ? "Commit id: #{commit_id}" : nil
186
+ elsif class_name == 'Pindo::TaskSystem::IosBuildAppStoreTask'
187
+ return "重签名"
188
+ else
189
+ return nil
190
+ end
191
+ end
192
+ end
193
+
194
+ # 路径2:直接上传 IPA 时,检测 Xcode 工程描述文件类型
195
+ if @file_type == 'ipa'
196
+ profile_type = detect_xcode_profile_type
197
+ case profile_type
198
+ when :adhoc
199
+ commit_id = get_current_commit_id
200
+ return commit_id ? "Commit id: #{commit_id}" : nil
201
+ when :appstore
202
+ return "重签名"
203
+ end
204
+ end
205
+
206
+ nil
207
+ end
208
+
209
+ # 获取当前 git commit id(从 upload_path 所在的 git 仓库)
210
+ def get_current_commit_id
211
+ dir = @upload_path || Dir.pwd
212
+ commit_id = `git -C "#{dir}" rev-parse HEAD 2>/dev/null`.strip
213
+ commit_id.empty? ? nil : commit_id
214
+ rescue
215
+ nil
216
+ end
217
+
218
+ # 检测当前目录下 Xcode 工程的描述文件类型
219
+ # 通过读取主 target Release 配置的 PROVISIONING_PROFILE_SPECIFIER 判断
220
+ # @return [Symbol, nil] :adhoc / :appstore / :development / nil
221
+ def detect_xcode_profile_type
222
+ require 'xcodeproj'
223
+
224
+ # 从 upload_path 向上查找包含 .xcodeproj 的目录
225
+ search_dir = File.expand_path(@upload_path || Dir.pwd)
226
+ project_fullname = nil
227
+ loop do
228
+ candidates = Dir.glob(File.join(search_dir, '*.xcodeproj'))
229
+ if candidates.any?
230
+ project_fullname = candidates.max_by { |f| File.mtime(f) }
231
+ break
232
+ end
233
+ parent = File.dirname(search_dir)
234
+ break if parent == search_dir # 已到文件系统根目录
235
+ search_dir = parent
236
+ end
237
+
238
+ return nil unless project_fullname && File.exist?(project_fullname)
239
+
240
+ project_obj = Xcodeproj::Project.open(project_fullname)
241
+ main_target = project_obj.targets.select do |t|
242
+ t.respond_to?(:product_type) &&
243
+ t.product_type.include?(Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application])
244
+ end.first
245
+ return nil unless main_target
246
+
247
+ # 优先取 Release 配置,找不到则取第一个
248
+ release_config = main_target.build_configurations.find { |c| c.name == 'Release' } ||
249
+ main_target.build_configurations.first
250
+ return nil unless release_config
251
+
252
+ specifier = release_config.build_settings['PROVISIONING_PROFILE_SPECIFIER'].to_s.downcase
253
+ if specifier.include?('adhoc')
254
+ :adhoc
255
+ elsif specifier.include?('development')
256
+ :development
257
+ else
258
+ :appstore
259
+ end
260
+ rescue
261
+ nil
262
+ end
263
+
161
264
  # 延迟获取 JPS 配置(上传任务专用)
162
265
  # @return [Array] 返回 [app_info_obj, workflow_info]
163
266
  def fetch_jps_config(working_directory: Dir.pwd, package_type: nil)
@@ -205,7 +205,8 @@ module Pindo
205
205
  platform: platform,
206
206
  isLibrary: @is_library_mode,
207
207
  indexNo: @index_count,
208
- deployMode: @deploy_mode
208
+ deployMode: @deploy_mode,
209
+ auto_kill: @auto_kill
209
210
  )
210
211
  end
211
212
  end
@@ -81,7 +81,8 @@ module Pindo
81
81
  # 调用 UnityHelper 的 force_update_libraries 方法
82
82
  result = unity_helper.force_update_libraries(
83
83
  unity_exe_full_path: @unity_exe_path,
84
- project_path: @unity_root_path
84
+ project_path: @unity_root_path,
85
+ auto_kill: @auto_kill
85
86
  )
86
87
 
87
88
  # 返回成功结果
@@ -100,7 +100,8 @@ module Pindo
100
100
  result = unity_helper.build_yoo_asset(
101
101
  unity_exe_full_path: @unity_exe_path,
102
102
  project_path: @unity_root_path,
103
- platform: platform_name
103
+ platform: platform_name,
104
+ auto_kill: @auto_kill
104
105
  )
105
106
 
106
107
  # 如果跳过(YooAsset 不存在),输出警告并显示命令
@@ -8,11 +8,12 @@ module Pindo
8
8
  # Unity 任务基类
9
9
  # 所有 Unity 相关任务的父类,提供通用的 Unity 操作和配置
10
10
  class UnityTask < PindoTask
11
- attr_reader :project_path, :unity_root_path
11
+ attr_reader :project_path, :unity_root_path, :auto_kill
12
12
 
13
13
  def initialize(name, options = {})
14
14
  @project_path = options[:project_path] ? normalize_path(options[:project_path]) : nil
15
15
  @unity_root_path = options[:unity_root_path] ? normalize_path(options[:unity_root_path]) : @project_path
16
+ @auto_kill = options[:auto_kill] || false
16
17
 
17
18
  super(name, options)
18
19
  end
@@ -117,6 +117,14 @@ module Pindo
117
117
 
118
118
  # 输出执行摘要
119
119
  @reporter.print_execution_summary
120
+
121
+ # 检查失败任务,有失败则抛出异常(确保进程返回非零退出码)
122
+ report = execution_report
123
+ if report[:failed] > 0
124
+ failed_tasks = @queue.completed_snapshot.select { |t| t.status == TaskStatus::FAILED }
125
+ failed_names = failed_tasks.map(&:name).join(', ')
126
+ raise Informative, "#{report[:failed]} 个任务执行失败: #{failed_names}"
127
+ end
120
128
  end
121
129
 
122
130
  # 获取执行报告
@@ -46,11 +46,11 @@ module Pindo
46
46
  # ============================================
47
47
 
48
48
  # 检查 GoodUnityBuild 版本是否满足要求
49
- def check_goodunitybuild_version(unity_exe_full_path, project_path)
49
+ def check_goodunitybuild_version(unity_exe_full_path, project_path, auto_kill: false)
50
50
  Funlog.instance.fancyinfo_start("检查 GoodUnityBuild 版本")
51
51
 
52
52
  # 检查是否有Unity进程在运行
53
- UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
53
+ UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path, auto_kill: auto_kill)
54
54
 
55
55
  # 执行 Unity 命令获取库版本
56
56
  result = UnityCommandHelper.execute_unity_command(
@@ -112,10 +112,10 @@ module Pindo
112
112
  Funlog.warning("GoodUnityBuild 库版本检查失败: #{e.message}")
113
113
  end
114
114
 
115
- def export_project(unity_exe_full_path:nil, project_path:nil, platform: nil, isLibrary: false, indexNo: nil, deployMode: nil)
115
+ def export_project(unity_exe_full_path:nil, project_path:nil, platform: nil, isLibrary: false, indexNo: nil, deployMode: nil, auto_kill: false)
116
116
 
117
117
  # 检查是否有Unity进程在运行,传入Unity路径和项目路径以精确匹配
118
- UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
118
+ UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path, auto_kill: auto_kill)
119
119
 
120
120
  additional_args = {}
121
121
  additional_args[:platform] = platform if platform
@@ -201,8 +201,9 @@ module Pindo
201
201
  # @param unity_exe_full_path [String] Unity 可执行文件路径
202
202
  # @param project_path [String] Unity 项目路径
203
203
  # @param platform [String] 目标平台 ('Android', 'iOS' 等)
204
+ # @param auto_kill [Boolean] 是否自动关闭进程(不询问用户)
204
205
  # @return [Hash] 执行结果,如果跳过则返回 { skipped: true }
205
- def build_yoo_asset(unity_exe_full_path:nil, project_path:nil, platform: nil)
206
+ def build_yoo_asset(unity_exe_full_path:nil, project_path:nil, platform: nil, auto_kill: false)
206
207
  # 检查项目中是否存在 YooAsset
207
208
  unless yoo_asset_exists?(project_path)
208
209
  return { skipped: true, reason: 'YooAsset not found' }
@@ -211,7 +212,7 @@ module Pindo
211
212
  puts "检测到 YooAsset,开始构建资源..."
212
213
 
213
214
  # 检查是否有Unity进程在运行
214
- UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
215
+ UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path, auto_kill: auto_kill)
215
216
 
216
217
  additional_args = {}
217
218
  additional_args[:platform] = platform if platform
@@ -244,10 +245,11 @@ module Pindo
244
245
  # 强制更新必备库(NugetForUnity)
245
246
  # @param unity_exe_full_path [String] Unity 可执行文件路径
246
247
  # @param project_path [String] Unity 项目路径
248
+ # @param auto_kill [Boolean] 是否自动关闭进程(不询问用户)
247
249
  # @return [Hash] 执行结果
248
- def force_update_libraries(unity_exe_full_path:nil, project_path:nil)
250
+ def force_update_libraries(unity_exe_full_path:nil, project_path:nil, auto_kill: false)
249
251
  # 检查是否有Unity进程在运行
250
- UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
252
+ UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path, auto_kill: auto_kill)
251
253
 
252
254
  # 使用 NugetForUnity.Joy.JoyTools.CheckForceUpdate 强制更新库
253
255
  result = UnityCommandHelper.execute_unity_command(
@@ -278,8 +280,9 @@ module Pindo
278
280
  # @param unity_exe_full_path [String] Unity 可执行文件路径
279
281
  # @param project_path [String] Unity 项目路径
280
282
  # @param deploy_mode [String] 部署模式 ('dev', 'adhoc', 'release')
283
+ # @param auto_kill [Boolean] 是否自动关闭进程(不询问用户)
281
284
  # @return [Hash] 执行结果
282
- def config_build_mode(unity_exe_full_path:nil, project_path:nil, deploy_mode: 'dev')
285
+ def config_build_mode(unity_exe_full_path:nil, project_path:nil, deploy_mode: 'dev', auto_kill: false)
283
286
  # 验证 deploy_mode 参数
284
287
  valid_modes = ['dev', 'adhoc', 'release']
285
288
  unless valid_modes.include?(deploy_mode)
@@ -287,7 +290,7 @@ module Pindo
287
290
  end
288
291
 
289
292
  # 检查是否有Unity进程在运行
290
- UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path)
293
+ UnityProcHelper.check_unity_processes(unity_exe_full_path: unity_exe_full_path, project_path: project_path, auto_kill: auto_kill)
291
294
 
292
295
  puts "配置 GoodUnityBuild 编译模式为: #{deploy_mode}"
293
296
 
@@ -5,10 +5,11 @@ module Pindo
5
5
  # 所有方法均为类方法,无需实例化
6
6
  class UnityProcHelper
7
7
 
8
- # 构建前检查 Unity 进程(交互式)
8
+ # 构建前检查 Unity 进程(交互式或自动关闭)
9
9
  # @param unity_exe_full_path [String] Unity 可执行文件路径
10
10
  # @param project_path [String] Unity 项目路径
11
- def self.check_unity_processes(unity_exe_full_path: nil, project_path: nil)
11
+ # @param auto_kill [Boolean] 是否自动关闭进程(不询问用户)
12
+ def self.check_unity_processes(unity_exe_full_path: nil, project_path: nil, auto_kill: false)
12
13
  # 如果没有提供路径参数,直接跳过Unity进程检查
13
14
  if unity_exe_full_path.nil? && project_path.nil?
14
15
  return
@@ -32,6 +33,30 @@ module Pindo
32
33
  end
33
34
  puts ""
34
35
 
36
+ # 如果指定了 auto_kill,直接关闭进程
37
+ if auto_kill
38
+ puts "自动关闭 Unity 进程..."
39
+ success_count = 0
40
+ unity_pids.each do |process_info|
41
+ if kill_unity_process(process_info[:pid])
42
+ puts "✅ 成功关闭进程 #{process_info[:pid]}"
43
+ success_count += 1
44
+ else
45
+ puts "❌ 关闭进程 #{process_info[:pid]} 失败"
46
+ end
47
+ end
48
+
49
+ if success_count > 0
50
+ puts "\n✅ 已关闭 #{success_count} 个 Unity 相关进程"
51
+ puts "等待3秒后继续编译..."
52
+ sleep(3)
53
+ else
54
+ puts "\n❌ 无法关闭 Unity 相关进程,请手动关闭后重试"
55
+ raise "Unity进程冲突:无法自动关闭 Unity 相关进程,请手动关闭后重试"
56
+ end
57
+ return
58
+ end
59
+
35
60
  # 询问用户是否要自动关闭Unity进程
36
61
  loop do
37
62
  puts "批处理模式需要关闭这些 Unity 进程以避免冲突"
@@ -4,6 +4,7 @@ require 'faraday'
4
4
  require 'xcodeproj'
5
5
  require 'pindo/base/git_handler'
6
6
  require 'pindo/config/pindoconfig'
7
+ require 'pindo/module/xcode/xcode_build_helper'
7
8
 
8
9
  module Pindo
9
10
  # Applovin Xcode 辅助类
@@ -258,8 +259,9 @@ module Pindo
258
259
  # 跳过非 native target(如 PBXAggregateTarget)
259
260
  next unless target.respond_to?(:product_type)
260
261
  if target.product_type.to_s == "com.apple.product-type.application"
261
- temp_info = target.build_configurations.first.build_settings['INFOPLIST_FILE']
262
- return File.join(project_dir, temp_info) if temp_info
262
+ raw_path = target.build_configurations.first.build_settings['INFOPLIST_FILE']
263
+ resolved = Pindo::XcodeBuildHelper.resolve_info_plist_path(project_dir, raw_path, target: target)
264
+ return resolved if resolved
263
265
  end
264
266
  end
265
267
  rescue => e
@@ -176,6 +176,78 @@ module Pindo
176
176
  # return model_data
177
177
  # end
178
178
 
179
+ def self.xcode_macos_icon_json
180
+ model_data = {
181
+ "images" => [
182
+ {
183
+ "size" => "16x16",
184
+ "idiom" => "mac",
185
+ "filename" => "app_icon_16.png",
186
+ "scale" => "1x"
187
+ },
188
+ {
189
+ "size" => "16x16",
190
+ "idiom" => "mac",
191
+ "filename" => "app_icon_32.png",
192
+ "scale" => "2x"
193
+ },
194
+ {
195
+ "size" => "32x32",
196
+ "idiom" => "mac",
197
+ "filename" => "app_icon_32.png",
198
+ "scale" => "1x"
199
+ },
200
+ {
201
+ "size" => "32x32",
202
+ "idiom" => "mac",
203
+ "filename" => "app_icon_64.png",
204
+ "scale" => "2x"
205
+ },
206
+ {
207
+ "size" => "128x128",
208
+ "idiom" => "mac",
209
+ "filename" => "app_icon_128.png",
210
+ "scale" => "1x"
211
+ },
212
+ {
213
+ "size" => "128x128",
214
+ "idiom" => "mac",
215
+ "filename" => "app_icon_256.png",
216
+ "scale" => "2x"
217
+ },
218
+ {
219
+ "size" => "256x256",
220
+ "idiom" => "mac",
221
+ "filename" => "app_icon_256.png",
222
+ "scale" => "1x"
223
+ },
224
+ {
225
+ "size" => "256x256",
226
+ "idiom" => "mac",
227
+ "filename" => "app_icon_512.png",
228
+ "scale" => "2x"
229
+ },
230
+ {
231
+ "size" => "512x512",
232
+ "idiom" => "mac",
233
+ "filename" => "app_icon_512.png",
234
+ "scale" => "1x"
235
+ },
236
+ {
237
+ "size" => "512x512",
238
+ "idiom" => "mac",
239
+ "filename" => "app_icon_1024.png",
240
+ "scale" => "2x"
241
+ }
242
+ ],
243
+ "info" => {
244
+ "author" => "xcode",
245
+ "version" => 1
246
+ }
247
+ }
248
+ return model_data
249
+ end
250
+
179
251
  def self.xcode_ios_imessage_icon_json
180
252
  model_data = {
181
253
  "images" => [
@@ -2,6 +2,7 @@ require 'fileutils'
2
2
  require 'xcodeproj'
3
3
  require 'json'
4
4
  require 'pindo/module/xcode/xcode_res_helper'
5
+ require 'pindo/module/xcode/xcode_build_helper'
5
6
  require 'pindo/module/utils/file_downloader'
6
7
  require 'open-uri'
7
8
  require_relative '../../base/funlog'
@@ -39,15 +40,19 @@ module Pindo
39
40
  # 跳过非 native target(如 PBXAggregateTarget)
40
41
  next unless target.respond_to?(:product_type)
41
42
  if target.product_type.to_s.eql?("com.apple.product-type.application")
42
- temp_info_file = target.build_configurations.first.build_settings['INFOPLIST_FILE']
43
- if temp_info_file && !temp_info_file.empty?
44
- info_plist_path = File.join(project_dir, temp_info_file)
45
- end
46
43
  app_target = target
47
44
  break # 找到第一个application target即可
48
45
  end
49
46
  end
50
47
 
48
+ return false unless app_target
49
+
50
+ # 确保 Info.plist 存在(不存在时自动创建)
51
+ info_plist_path = Pindo::XcodeBuildHelper.ensure_info_plist_exists(
52
+ project_dir: project_dir,
53
+ target: app_target,
54
+ project_obj: project_obj
55
+ )
51
56
  return false unless info_plist_path && File.exist?(info_plist_path)
52
57
 
53
58
  # 一次性读取plist
@@ -138,20 +143,26 @@ module Pindo
138
143
  current_bundle_id = nil
139
144
 
140
145
  project_obj = Xcodeproj::Project.open(project_fullname)
146
+ app_target = nil
141
147
  project_obj.targets.each do |target|
142
148
  # 跳过非 native target(如 PBXAggregateTarget)
143
149
  next unless target.respond_to?(:product_type)
144
150
  if target.product_type.to_s.eql?("com.apple.product-type.application")
145
- temp_info_file = target.build_configurations.first.build_settings['INFOPLIST_FILE']
146
- if temp_info_file && !temp_info_file.empty?
147
- info_plist_path = File.join(project_dir, temp_info_file)
148
- end
151
+ app_target = target
149
152
  # 获取当前实际的 Bundle ID
150
153
  current_bundle_id = target.build_configurations.first.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
151
154
  break # 找到第一个application target即可
152
155
  end
153
156
  end
154
157
 
158
+ return false unless app_target
159
+
160
+ # 确保 Info.plist 存在
161
+ info_plist_path = Pindo::XcodeBuildHelper.ensure_info_plist_exists(
162
+ project_dir: project_dir,
163
+ target: app_target,
164
+ project_obj: project_obj
165
+ )
155
166
  return false unless info_plist_path && File.exist?(info_plist_path)
156
167
  return false unless current_bundle_id && !current_bundle_id.empty?
157
168
 
@@ -209,19 +220,25 @@ module Pindo
209
220
  bundleid_scheme_name = nil
210
221
 
211
222
  project_obj = Xcodeproj::Project.open(project_fullname)
223
+ app_target = nil
212
224
  project_obj.targets.each do |target|
213
225
  # 跳过非 native target(如 PBXAggregateTarget)
214
226
  next unless target.respond_to?(:product_type)
215
227
  if target.product_type.to_s.eql?("com.apple.product-type.application")
216
- temp_info_file = target.build_configurations.first.build_settings['INFOPLIST_FILE']
217
- if temp_info_file && !temp_info_file.empty?
218
- info_plist_path = File.join(project_dir, temp_info_file)
219
- end
228
+ app_target = target
220
229
  bundleid_scheme_name = target.build_configurations.first.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
221
230
  break # 找到第一个application target即可
222
231
  end
223
232
  end
224
233
 
234
+ return false unless app_target
235
+
236
+ # 确保 Info.plist 存在
237
+ info_plist_path = Pindo::XcodeBuildHelper.ensure_info_plist_exists(
238
+ project_dir: project_dir,
239
+ target: app_target,
240
+ project_obj: project_obj
241
+ )
225
242
  return false unless info_plist_path && File.exist?(info_plist_path)
226
243
 
227
244
  info_plist_dict = Xcodeproj::Plist.read_from_path(info_plist_path)
@@ -311,9 +328,10 @@ module Pindo
311
328
  config.build_settings['CURRENT_PROJECT_VERSION'] = build_number.to_s
312
329
 
313
330
  # 兼容旧的设置方式,通过Info.plist更新
314
- if config.build_settings['INFOPLIST_FILE']
315
- info_plist_path = File.join(project_dir, config.build_settings['INFOPLIST_FILE'])
316
- if File.exist?(info_plist_path)
331
+ raw_plist_path = config.build_settings['INFOPLIST_FILE']
332
+ if raw_plist_path
333
+ info_plist_path = Pindo::XcodeBuildHelper.resolve_info_plist_path(project_dir, raw_plist_path, target: target)
334
+ if info_plist_path
317
335
  update_info_plist(info_plist_path, version, build_number.to_s)
318
336
  end
319
337
  end
@@ -478,7 +496,8 @@ module Pindo
478
496
  Funlog.instance.fancyinfo_start("正在创建 icon...")
479
497
  XcodeResHelper.create_icons(
480
498
  icon_name: icon_download_path,
481
- new_icon_dir: new_icon_dir
499
+ new_icon_dir: new_icon_dir,
500
+ proj_dir: project_dir
482
501
  )
483
502
  Funlog.instance.fancyinfo_success("创建 icon 完成!")
484
503
 
@@ -558,7 +577,7 @@ module Pindo
558
577
  new_icon_dir = File.join(project_dir, "icon_#{time}")
559
578
 
560
579
  Funlog.instance.fancyinfo_start("正在创建 icon...")
561
- Pindo::XcodeResHelper.create_icons(icon_name: icon_name, new_icon_dir: new_icon_dir)
580
+ Pindo::XcodeResHelper.create_icons(icon_name: icon_name, new_icon_dir: new_icon_dir, proj_dir: project_dir)
562
581
  Funlog.instance.fancyinfo_success("创建 icon 完成!")
563
582
 
564
583
  Funlog.instance.fancyinfo_start("正在替换 icon...")