pindo 5.18.20 → 5.19.2
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/git_handler.rb +38 -60
- data/lib/pindo/command/android/autobuild.rb +8 -4
- data/lib/pindo/command/ios/autobuild.rb +8 -4
- data/lib/pindo/command/repo/create.rb +1 -1
- data/lib/pindo/command/repo/search.rb +1 -1
- data/lib/pindo/command/unity/autobuild.rb +1 -1
- data/lib/pindo/command/utils/installskills.rb +2 -2
- data/lib/pindo/command/utils/renewproj.rb +0 -1
- data/lib/pindo/command/web/autobuild.rb +8 -4
- data/lib/pindo/module/android/android_build_helper.rb +39 -16
- data/lib/pindo/module/android/gradle_helper.rb +8 -14
- data/lib/pindo/module/cert/cert_helper.rb +2 -2
- data/lib/pindo/module/pgyer/pgyerhelper.rb +18 -20
- data/lib/pindo/module/task/model/build/android_build_dev_task.rb +1 -37
- data/lib/pindo/module/task/model/build/android_build_task.rb +40 -0
- data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +5 -5
- data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +5 -5
- data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +2 -2
- data/lib/pindo/module/task/model/build_task.rb +2 -0
- data/lib/pindo/module/task/model/git/git_commit_task.rb +11 -1
- data/lib/pindo/module/task/model/git/git_tag_task.rb +2 -2
- data/lib/pindo/module/task/model/jps/jps_workflow_message_task.rb +8 -10
- data/lib/pindo/module/task/pindo_task.rb +2 -2
- data/lib/pindo/module/task/task_manager.rb +14 -6
- data/lib/pindo/module/unity/nuget_helper.rb +5 -20
- data/lib/pindo/module/utils/git_repo_helper.rb +40 -45
- data/lib/pindo/module/xcode/ipa_resign_helper.rb +33 -62
- data/lib/pindo/options/groups/unity_options.rb +1 -1
- data/lib/pindo/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68c6a51d50dad94212ebaf6360ce8a9f6a196b30aaf98a98e2114875ed6c0984
|
|
4
|
+
data.tar.gz: 34d0ca5bf09f50c5c3d2d25fa48cf761f526bd15381c57fca95c6b73567a41c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7318ecbfadf6b0bee7febebff7f35e289984049f37b95760722abed6a59cc497b58f3fcb6786566a0f0ea71688da5434fc1c139cd68905f8b24dd326628a2187
|
|
7
|
+
data.tar.gz: c08a9a8fc36bdbe9850bff8601c1d4da3a371466fa2c7b95c24cdcdcbe9fa4e059d12e3cd692a7491c15f6faa7d5cbaac3f73b855b0b69470790a5c72e184f56
|
|
@@ -86,8 +86,7 @@ module Pindo
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def add_branch(local_repo_dir: nil, branch: nil)
|
|
89
|
-
|
|
90
|
-
current=Dir.pwd
|
|
89
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
91
90
|
result = false
|
|
92
91
|
|
|
93
92
|
if !local_branch_exists?(local_repo_dir: local_repo_dir, branch: branch)
|
|
@@ -97,13 +96,11 @@ module Pindo
|
|
|
97
96
|
|
|
98
97
|
git_remote!(local_repo_dir, %W(-C #{local_repo_dir} push origin #{branch}:#{branch}))
|
|
99
98
|
|
|
100
|
-
Dir.chdir(current)
|
|
101
99
|
return result
|
|
102
100
|
end
|
|
103
101
|
|
|
104
102
|
def remove_branch(local_repo_dir: nil, branch: nil)
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
107
104
|
result = false
|
|
108
105
|
if File.exist?(local_repo_dir)
|
|
109
106
|
current_branch = git!(%W(-C #{local_repo_dir} rev-parse --abbrev-ref HEAD)).strip
|
|
@@ -120,51 +117,40 @@ module Pindo
|
|
|
120
117
|
else
|
|
121
118
|
result = false
|
|
122
119
|
end
|
|
123
|
-
Dir.chdir(current)
|
|
124
120
|
return result
|
|
125
121
|
end
|
|
126
122
|
|
|
127
123
|
|
|
128
124
|
def local_branch_exists?(local_repo_dir: nil, branch: nil)
|
|
129
|
-
|
|
125
|
+
# 命令改带 -C,去掉 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
130
126
|
result = false
|
|
131
127
|
|
|
132
128
|
if File.exist?(local_repo_dir)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
res_data = Executable.capture_command('git', %W(rev-parse --verify #{branch}), :capture => :out)
|
|
136
|
-
# puts "=====1"
|
|
137
|
-
# puts res_data
|
|
138
|
-
# res_data = git!(%W(-C #{local_repo_dir} --no-pager branch --list origin/#{branch} --no-color -r))
|
|
129
|
+
res_data = Executable.capture_command('git', %W(-C #{local_repo_dir} rev-parse --verify #{branch}), :capture => :out)
|
|
139
130
|
result = !res_data.nil? && !res_data.empty?
|
|
140
131
|
else
|
|
141
132
|
result = false
|
|
142
133
|
end
|
|
143
|
-
Dir.chdir(current)
|
|
144
134
|
return result
|
|
145
135
|
end
|
|
146
136
|
|
|
147
137
|
def remote_branch_exists?(local_repo_dir: nil, branch: nil)
|
|
148
|
-
|
|
138
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
149
139
|
result = false
|
|
150
140
|
if File.exist?(local_repo_dir)
|
|
151
|
-
Dir.chdir(local_repo_dir)
|
|
152
141
|
res_data = git_remote!(local_repo_dir, %W(-C #{local_repo_dir} ls-remote --heads origin refs/heads/#{branch}))
|
|
153
142
|
result = !res_data.nil? && !res_data.empty?
|
|
154
143
|
else
|
|
155
144
|
result = false
|
|
156
145
|
end
|
|
157
|
-
Dir.chdir(current)
|
|
158
146
|
return result
|
|
159
147
|
end
|
|
160
148
|
|
|
161
149
|
|
|
162
150
|
def add_tag(local_repo_dir: nil, tag_name: nil)
|
|
163
|
-
|
|
164
|
-
current=Dir.pwd
|
|
151
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
165
152
|
result = false
|
|
166
153
|
if File.exist?(local_repo_dir)
|
|
167
|
-
Dir.chdir(local_repo_dir)
|
|
168
154
|
if !local_tag_exists?(local_repo_dir: local_repo_dir, tag_name: tag_name)
|
|
169
155
|
git!(%W(-C #{local_repo_dir} tag #{tag_name}))
|
|
170
156
|
result = true
|
|
@@ -173,7 +159,6 @@ module Pindo
|
|
|
173
159
|
else
|
|
174
160
|
result = false
|
|
175
161
|
end
|
|
176
|
-
Dir.chdir(current)
|
|
177
162
|
return result
|
|
178
163
|
end
|
|
179
164
|
|
|
@@ -207,11 +192,9 @@ module Pindo
|
|
|
207
192
|
end
|
|
208
193
|
|
|
209
194
|
def remove_tag(local_repo_dir: nil, tag_name: nil)
|
|
210
|
-
|
|
195
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
211
196
|
result = false
|
|
212
|
-
current=Dir.pwd
|
|
213
197
|
if File.exist?(local_repo_dir)
|
|
214
|
-
Dir.chdir(local_repo_dir)
|
|
215
198
|
if local_tag_exists?(local_repo_dir: local_repo_dir, tag_name: tag_name)
|
|
216
199
|
git!(%W(-C #{local_repo_dir} tag -d #{tag_name}))
|
|
217
200
|
result = true
|
|
@@ -223,7 +206,6 @@ module Pindo
|
|
|
223
206
|
else
|
|
224
207
|
result = false
|
|
225
208
|
end
|
|
226
|
-
Dir.chdir(current)
|
|
227
209
|
return result
|
|
228
210
|
|
|
229
211
|
end
|
|
@@ -234,12 +216,17 @@ module Pindo
|
|
|
234
216
|
def remote_tag_commit(local_repo_dir: nil, tag_name: nil)
|
|
235
217
|
return nil if local_repo_dir.nil? || !File.exist?(local_repo_dir)
|
|
236
218
|
tag_ref = "refs/tags/#{tag_name}"
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
#
|
|
241
|
-
|
|
242
|
-
|
|
219
|
+
peeled_ref = "#{tag_ref}^{}"
|
|
220
|
+
# annotated tag 需要 ^{} 解引用行才能拿到真实 commit;但只传 tag_ref 精确过滤时,
|
|
221
|
+
# git ls-remote 不会附带 ^{} 行,必须显式把 peeled_ref 一起传入才能拿到它
|
|
222
|
+
res_data = git_remote!(local_repo_dir, %W(-C #{local_repo_dir} ls-remote --tags origin #{tag_ref} #{peeled_ref}))
|
|
223
|
+
entries = res_data.to_s.lines.map { |l| l.strip.split(/\s+/, 2) }
|
|
224
|
+
.select { |sha, ref| sha && ref }
|
|
225
|
+
return nil if entries.empty?
|
|
226
|
+
# 优先取 ^{} 行(annotated tag 的真实 commit);lightweight tag 只有 tag_ref 行且本身即 commit
|
|
227
|
+
peeled = entries.find { |_sha, ref| ref == peeled_ref }
|
|
228
|
+
plain = entries.find { |_sha, ref| ref == tag_ref }
|
|
229
|
+
(peeled || plain)&.first
|
|
243
230
|
end
|
|
244
231
|
|
|
245
232
|
def remote_tag_exists?(local_repo_dir: nil, tag_name: nil)
|
|
@@ -253,9 +240,7 @@ module Pindo
|
|
|
253
240
|
end
|
|
254
241
|
|
|
255
242
|
def git_latest_commit_id(local_repo_dir:nil)
|
|
256
|
-
|
|
257
|
-
current=Dir.pwd
|
|
258
|
-
|
|
243
|
+
# 命令已带 -C,无需 Dir.chdir(并发模式下 chdir 会污染全局 cwd)
|
|
259
244
|
unless File.exist?(File::join(local_repo_dir, ".git"))
|
|
260
245
|
return nil
|
|
261
246
|
end
|
|
@@ -263,16 +248,9 @@ module Pindo
|
|
|
263
248
|
commit_id = nil
|
|
264
249
|
|
|
265
250
|
if File.exist?(local_repo_dir)
|
|
266
|
-
Dir.chdir(local_repo_dir)
|
|
267
251
|
current_branch = git!(%W(-C #{local_repo_dir} rev-parse --abbrev-ref HEAD)).strip
|
|
268
|
-
# puts "current_branch: #{current_branch}"
|
|
269
|
-
|
|
270
|
-
# git log -n 1 --pretty=format:"commit %H"
|
|
271
|
-
# format_str = "commit %H"
|
|
272
|
-
# latest_log_info = git!(%W(-C #{current} log -n 1 --pretty=#{format_str} #{current_branch})).strip
|
|
273
252
|
commit_id = git!(%W(-C #{local_repo_dir} rev-parse #{current_branch})).strip
|
|
274
253
|
end
|
|
275
|
-
Dir.chdir(current)
|
|
276
254
|
|
|
277
255
|
return commit_id
|
|
278
256
|
end
|
|
@@ -362,9 +340,11 @@ module Pindo
|
|
|
362
340
|
rescue StandardError => e
|
|
363
341
|
Funlog.instance.fancyinfo_error("仓库#{local_repo_dir}更新失败!")
|
|
364
342
|
raise Informative, e.to_s
|
|
343
|
+
ensure
|
|
344
|
+
# 无论成功失败都还原 cwd,避免异常路径下污染全局工作目录
|
|
345
|
+
Dir.chdir(current)
|
|
365
346
|
end
|
|
366
347
|
|
|
367
|
-
Dir.chdir(current)
|
|
368
348
|
return local_repo_dir
|
|
369
349
|
end
|
|
370
350
|
|
|
@@ -464,12 +444,8 @@ module Pindo
|
|
|
464
444
|
end
|
|
465
445
|
|
|
466
446
|
def git_addpush_repo(path:nil, message:"res", commit_file_params:nil)
|
|
467
|
-
|
|
468
|
-
Dir.chdir(path)
|
|
469
|
-
|
|
470
|
-
# gitee.com 仓库自动去除代理
|
|
447
|
+
# gitee.com 仓库自动去除代理;is_gitee_repo? 命令已带 -C,无需 chdir
|
|
471
448
|
if is_gitee_repo?(local_repo_dir: path)
|
|
472
|
-
Dir.chdir(current)
|
|
473
449
|
return without_proxy { git_addpush_repo_impl(path: path, message: message, commit_file_params: commit_file_params) }
|
|
474
450
|
end
|
|
475
451
|
|
|
@@ -512,10 +488,10 @@ module Pindo
|
|
|
512
488
|
rescue => error
|
|
513
489
|
# puts(error.to_s)
|
|
514
490
|
raise Informative, "\n#{path}\n 仓库失败 !!!"
|
|
491
|
+
ensure
|
|
492
|
+
# 无论成功失败都还原 cwd,避免异常路径下污染全局工作目录
|
|
493
|
+
Dir.chdir(current)
|
|
515
494
|
end
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
Dir.chdir(current)
|
|
519
495
|
end
|
|
520
496
|
|
|
521
497
|
|
|
@@ -548,8 +524,11 @@ module Pindo
|
|
|
548
524
|
return nil
|
|
549
525
|
end
|
|
550
526
|
|
|
551
|
-
#
|
|
552
|
-
|
|
527
|
+
# git!/IO#readpartial 返回的是 ASCII-8BIT 字符串,含非 ASCII 字节(如中文路径、
|
|
528
|
+
# core.quotePath=false 时的原始多字节)会与下游 UTF-8 字面量拼接失败,这里统一
|
|
529
|
+
# 标成 UTF-8 并 scrub 无效字节,避免上层 `puts "...#{file}"` 抛 Encoding::CompatibilityError
|
|
530
|
+
raw_list = files_list.is_a?(String) ? files_list.split("\n") : Array(files_list)
|
|
531
|
+
raw_list.map { |f| f.dup.force_encoding('UTF-8').scrub }.reject(&:empty?)
|
|
553
532
|
rescue => e
|
|
554
533
|
Funlog.instance.fancyinfo_error("获取未提交文件列表失败: #{e.message}")
|
|
555
534
|
nil
|
|
@@ -624,14 +603,13 @@ module Pindo
|
|
|
624
603
|
puts
|
|
625
604
|
|
|
626
605
|
# 将文件列表分行并用红色显示
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
end
|
|
606
|
+
# 防御性编码归一化:git! 返回的是 ASCII-8BIT,与 UTF-8 字面量 " • " 拼接会抛
|
|
607
|
+
# Encoding::CompatibilityError;此处再兜一层,避免其它调用方传入 BINARY 字符串时崩溃
|
|
608
|
+
file_lines = files.is_a?(String) ? files.split("\n") : Array(files)
|
|
609
|
+
file_lines.each do |file|
|
|
610
|
+
next if file.nil? || file.empty?
|
|
611
|
+
safe_file = file.dup.force_encoding('UTF-8').scrub
|
|
612
|
+
puts " • #{safe_file}".red
|
|
635
613
|
end
|
|
636
614
|
|
|
637
615
|
puts
|
|
@@ -98,7 +98,7 @@ module Pindo
|
|
|
98
98
|
@option_items ||= Pindo::Options::OptionGroup.merge(
|
|
99
99
|
Pindo::Options::BuildOptions.select(:bundle_name, :release),
|
|
100
100
|
Pindo::Options::JPSOptions.select(:conf, :upload, :media, :bind, :send),
|
|
101
|
-
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
|
|
101
|
+
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo, :kill_unity),
|
|
102
102
|
Pindo::Options::UnityOptions.select_with_defaults(skipmacro: true),
|
|
103
103
|
Pindo::Options::TaskOptions.select(:multi),
|
|
104
104
|
Pindo::Options::GitOptions.all
|
|
@@ -130,6 +130,7 @@ module Pindo
|
|
|
130
130
|
# Unity 参数
|
|
131
131
|
@args_skip_lib = @options[:skiplib] || false
|
|
132
132
|
@args_skip_yoo = @options[:skipyoo] || false
|
|
133
|
+
@args_kill_unity = @options[:kill_unity] || false
|
|
133
134
|
|
|
134
135
|
# Task 参数
|
|
135
136
|
@args_multi_flag = @options[:multi] || false
|
|
@@ -313,7 +314,8 @@ module Pindo
|
|
|
313
314
|
# 2.1 Unity 更新必备库任务(可选)
|
|
314
315
|
unless @args_skip_lib
|
|
315
316
|
unity_update_task = Pindo::TaskSystem::UnityUpdateTask.new(
|
|
316
|
-
project_path: config[:project_path]
|
|
317
|
+
project_path: config[:project_path],
|
|
318
|
+
auto_kill: @args_kill_unity
|
|
317
319
|
)
|
|
318
320
|
unity_update_task.dependencies << last_task.id
|
|
319
321
|
tasks << unity_update_task
|
|
@@ -324,7 +326,8 @@ module Pindo
|
|
|
324
326
|
unless @args_skip_yoo
|
|
325
327
|
unity_yoo_task = Pindo::TaskSystem::UnityYooAssetTask.new(
|
|
326
328
|
'android',
|
|
327
|
-
project_path: config[:project_path]
|
|
329
|
+
project_path: config[:project_path],
|
|
330
|
+
auto_kill: @args_kill_unity
|
|
328
331
|
)
|
|
329
332
|
unity_yoo_task.dependencies << last_task.id
|
|
330
333
|
tasks << unity_yoo_task
|
|
@@ -339,7 +342,8 @@ module Pindo
|
|
|
339
342
|
'android',
|
|
340
343
|
project_path: config[:project_path],
|
|
341
344
|
export_path: android_export_path,
|
|
342
|
-
context: unity_context
|
|
345
|
+
context: unity_context,
|
|
346
|
+
auto_kill: @args_kill_unity
|
|
343
347
|
)
|
|
344
348
|
unity_export_task.dependencies << last_task.id
|
|
345
349
|
tasks << unity_export_task
|
|
@@ -101,7 +101,7 @@ module Pindo
|
|
|
101
101
|
@option_items ||= Pindo::Options::OptionGroup.merge(
|
|
102
102
|
Pindo::Options::BuildOptions.select(:bundleid, :build_type),
|
|
103
103
|
Pindo::Options::JPSOptions.select(:conf, :upload, :media, :bind, :send),
|
|
104
|
-
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
|
|
104
|
+
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo, :kill_unity),
|
|
105
105
|
Pindo::Options::UnityOptions.select_with_defaults(skipmacro: true),
|
|
106
106
|
Pindo::Options::TaskOptions.select(:multi),
|
|
107
107
|
Pindo::Options::GitOptions.all
|
|
@@ -141,6 +141,7 @@ module Pindo
|
|
|
141
141
|
# Unity 参数
|
|
142
142
|
@args_skip_lib = @options[:skiplib] || false
|
|
143
143
|
@args_skip_yoo = @options[:skipyoo] || false
|
|
144
|
+
@args_kill_unity = @options[:kill_unity] || false
|
|
144
145
|
|
|
145
146
|
# Task 参数
|
|
146
147
|
@args_multi_flag = @options[:multi] || false
|
|
@@ -282,7 +283,8 @@ module Pindo
|
|
|
282
283
|
# 2.1 Unity 更新必备库任务(可选)
|
|
283
284
|
unless @args_skip_lib
|
|
284
285
|
unity_update_task = Pindo::TaskSystem::UnityUpdateTask.new(
|
|
285
|
-
project_path: config[:project_path]
|
|
286
|
+
project_path: config[:project_path],
|
|
287
|
+
auto_kill: @args_kill_unity
|
|
286
288
|
)
|
|
287
289
|
unity_update_task.dependencies << last_task.id
|
|
288
290
|
tasks << unity_update_task
|
|
@@ -293,7 +295,8 @@ module Pindo
|
|
|
293
295
|
unless @args_skip_yoo
|
|
294
296
|
unity_yoo_task = Pindo::TaskSystem::UnityYooAssetTask.new(
|
|
295
297
|
'ios',
|
|
296
|
-
project_path: config[:project_path]
|
|
298
|
+
project_path: config[:project_path],
|
|
299
|
+
auto_kill: @args_kill_unity
|
|
297
300
|
)
|
|
298
301
|
unity_yoo_task.dependencies << last_task.id
|
|
299
302
|
tasks << unity_yoo_task
|
|
@@ -309,7 +312,8 @@ module Pindo
|
|
|
309
312
|
project_path: config[:project_path],
|
|
310
313
|
export_path: ios_export_path,
|
|
311
314
|
deploy_mode: @build_type, # 根据 build_type 传递部署模式
|
|
312
|
-
context: unity_context
|
|
315
|
+
context: unity_context,
|
|
316
|
+
auto_kill: @args_kill_unity
|
|
313
317
|
)
|
|
314
318
|
unity_export_task.dependencies << last_task.id
|
|
315
319
|
tasks << unity_export_task
|
|
@@ -159,8 +159,8 @@ module Pindo
|
|
|
159
159
|
Funlog.fancyinfo_start("克隆仓库: #{url}...")
|
|
160
160
|
Funlog.info("仓库 URL: #{url}") if ENV['PINDO_DEBUG']
|
|
161
161
|
|
|
162
|
-
#
|
|
163
|
-
success = system("git clone
|
|
162
|
+
# 克隆仓库(数组参数形式,避免 URL 中的 shell 元字符注入)
|
|
163
|
+
success = system("git", "clone", url, temp_dir, "--quiet", err: File::NULL)
|
|
164
164
|
|
|
165
165
|
unless success && File.exist?(File.join(temp_dir, '.git'))
|
|
166
166
|
Funlog.fancyinfo_error("仓库克隆失败: #{url}")
|
|
@@ -142,7 +142,6 @@ module Pindo
|
|
|
142
142
|
new_project_dir = File.join(File::expand_path(current_dir + "/../") , temp_dir_name)
|
|
143
143
|
|
|
144
144
|
if File.exist?(new_project_dir)
|
|
145
|
-
system 'sh rm -rf ' + new_project_dir
|
|
146
145
|
FileUtils.rm_rf(new_project_dir)
|
|
147
146
|
end
|
|
148
147
|
FileUtils.mkdir(new_project_dir)
|
|
@@ -94,7 +94,7 @@ module Pindo
|
|
|
94
94
|
@option_items ||= Pindo::Options::OptionGroup.merge(
|
|
95
95
|
Pindo::Options::BuildOptions.select(:bundleid),
|
|
96
96
|
Pindo::Options::JPSOptions.select(:conf, :upload, :send, :media, :bind),
|
|
97
|
-
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo),
|
|
97
|
+
Pindo::Options::UnityOptions.select(:skiplib, :skipyoo, :kill_unity),
|
|
98
98
|
Pindo::Options::UnityOptions.select_with_defaults(skipmacro: true),
|
|
99
99
|
Pindo::Options::TaskOptions.select(:multi),
|
|
100
100
|
Pindo::Options::UtilsOptions.select(:run),
|
|
@@ -128,6 +128,7 @@ module Pindo
|
|
|
128
128
|
# Unity 参数
|
|
129
129
|
@args_skip_lib = @options[:skiplib] || false
|
|
130
130
|
@args_skip_yoo = @options[:skipyoo] || false
|
|
131
|
+
@args_kill_unity = @options[:kill_unity] || false
|
|
131
132
|
|
|
132
133
|
# Task 参数
|
|
133
134
|
@args_multi_flag = @options[:multi] || false
|
|
@@ -283,7 +284,8 @@ module Pindo
|
|
|
283
284
|
# 3. Unity 更新必备库任务(可选)
|
|
284
285
|
unless @args_skip_lib
|
|
285
286
|
unity_update_task = Pindo::TaskSystem::UnityUpdateTask.new(
|
|
286
|
-
project_path: config[:project_path]
|
|
287
|
+
project_path: config[:project_path],
|
|
288
|
+
auto_kill: @args_kill_unity
|
|
287
289
|
)
|
|
288
290
|
unity_update_task.dependencies << last_task.id if last_task
|
|
289
291
|
tasks << unity_update_task
|
|
@@ -294,7 +296,8 @@ module Pindo
|
|
|
294
296
|
unless @args_skip_yoo
|
|
295
297
|
unity_yoo_task = Pindo::TaskSystem::UnityYooAssetTask.new(
|
|
296
298
|
'web',
|
|
297
|
-
project_path: config[:project_path]
|
|
299
|
+
project_path: config[:project_path],
|
|
300
|
+
auto_kill: @args_kill_unity
|
|
298
301
|
)
|
|
299
302
|
unity_yoo_task.dependencies << last_task.id if last_task
|
|
300
303
|
tasks << unity_yoo_task
|
|
@@ -313,7 +316,8 @@ module Pindo
|
|
|
313
316
|
'web',
|
|
314
317
|
project_path: config[:project_path],
|
|
315
318
|
export_path: web_export_path,
|
|
316
|
-
context: unity_context
|
|
319
|
+
context: unity_context,
|
|
320
|
+
auto_kill: @args_kill_unity
|
|
317
321
|
)
|
|
318
322
|
unity_export_task.dependencies << last_task.id if last_task
|
|
319
323
|
tasks << unity_export_task
|
|
@@ -6,6 +6,7 @@ require_relative 'java_env_helper'
|
|
|
6
6
|
require_relative 'keystore_helper'
|
|
7
7
|
require_relative 'workflow_gradle_injector'
|
|
8
8
|
require 'fileutils'
|
|
9
|
+
require 'find'
|
|
9
10
|
|
|
10
11
|
module Pindo
|
|
11
12
|
class AndroidBuildHelper
|
|
@@ -24,6 +25,10 @@ module Pindo
|
|
|
24
25
|
raise ArgumentError, "项目目录不能为空" if project_dir.nil?
|
|
25
26
|
raise ArgumentError, "项目目录不存在" unless File.directory?(project_dir)
|
|
26
27
|
|
|
28
|
+
# 构建前先清理 macOS 自动生成的 .DS_Store
|
|
29
|
+
# 避免其被带入 base / asset pack 模块的 assets/ 导致冲突,或引起 Gradle clean 在遍历删除时出现竞态
|
|
30
|
+
prune_ds_store_files!(project_dir)
|
|
31
|
+
|
|
27
32
|
# 设置 Java Home 环境变量
|
|
28
33
|
Pindo::JavaEnvHelper.setup_java_home_from_project(project_dir)
|
|
29
34
|
|
|
@@ -396,20 +401,19 @@ module Pindo
|
|
|
396
401
|
puts ' AAB 构建前先执行 Gradle clean'
|
|
397
402
|
gradle_clean_resilient!(project_path)
|
|
398
403
|
|
|
399
|
-
|
|
400
|
-
system(
|
|
404
|
+
# 数组参数 + chdir,避免 project_path 拼接进 shell
|
|
405
|
+
system("./gradlew", "--no-daemon", bundle_task, chdir: project_path)
|
|
401
406
|
end
|
|
402
407
|
|
|
403
408
|
# clean 失败(占用、.DS_Store 竞态等)时:停 Daemon → 再删 .DS_Store → 物理删除各模块 build/,与 Gradle clean 产物一致,不中断后续 bundle
|
|
404
409
|
private def gradle_clean_resilient!(project_path)
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return if system(cmd)
|
|
410
|
+
prune_ds_store_files!(project_path)
|
|
411
|
+
return if system("./gradlew", "--no-daemon", "clean", chdir: project_path)
|
|
408
412
|
|
|
409
413
|
puts ' ⚠ Gradle clean 失败,正在自动恢复:--stop、清理 .DS_Store、删除各模块 build/ ...'
|
|
410
|
-
system(
|
|
414
|
+
system("./gradlew", "--stop", chdir: project_path, out: File::NULL, err: File::NULL)
|
|
411
415
|
sleep 0.3
|
|
412
|
-
|
|
416
|
+
prune_ds_store_files!(project_path)
|
|
413
417
|
remove_android_module_build_dirs!(project_path)
|
|
414
418
|
end
|
|
415
419
|
|
|
@@ -445,18 +449,37 @@ module Pindo
|
|
|
445
449
|
puts " ⚠ 物理删除 build 目录时出现异常(将继续尝试 bundle): #{e.message}"
|
|
446
450
|
end
|
|
447
451
|
|
|
448
|
-
# macOS
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
# 清理 macOS 自动生成的 .DS_Store 文件
|
|
453
|
+
# 作用:
|
|
454
|
+
# 1) 避免被带入 base 与 asset pack 模块的 assets/ 造成打包冲突
|
|
455
|
+
# 2) 避免 Gradle clean 遍历删除 build 目录时 Finder 回写 .DS_Store 触发
|
|
456
|
+
# Unable to delete / New files were found 的竞态错误
|
|
457
|
+
private def prune_ds_store_files!(project_path)
|
|
458
|
+
return 0 unless project_path && File.directory?(project_path)
|
|
459
|
+
|
|
460
|
+
count = 0
|
|
461
|
+
Find.find(project_path) do |path|
|
|
462
|
+
next unless File.basename(path) == '.DS_Store'
|
|
463
|
+
next unless File.file?(path)
|
|
464
|
+
|
|
465
|
+
begin
|
|
466
|
+
File.delete(path)
|
|
467
|
+
count += 1
|
|
468
|
+
rescue StandardError
|
|
469
|
+
# 个别文件删除失败不影响整体流程
|
|
470
|
+
next
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
puts " 已清理 #{count} 个 .DS_Store 文件" if count.positive?
|
|
474
|
+
count
|
|
475
|
+
rescue StandardError => e
|
|
476
|
+
puts " ⚠ 清理 .DS_Store 异常:#{e.message}"
|
|
477
|
+
0
|
|
454
478
|
end
|
|
455
479
|
|
|
456
480
|
def build_so_library(project_path)
|
|
457
|
-
# 编译so库 (Thread Safe)
|
|
458
|
-
|
|
459
|
-
system(cmd)
|
|
481
|
+
# 编译so库 (Thread Safe);数组参数 + chdir,避免 project_path 拼接进 shell
|
|
482
|
+
system("./gradlew", "unityLibrary:BuildIl2CppTask", chdir: project_path)
|
|
460
483
|
end
|
|
461
484
|
|
|
462
485
|
def copy_so_files(source_path, target_path)
|
|
@@ -518,18 +518,16 @@ module Pindo
|
|
|
518
518
|
return false
|
|
519
519
|
end
|
|
520
520
|
|
|
521
|
-
# 3. 使用unzip -t测试ZIP
|
|
522
|
-
|
|
523
|
-
system(test_cmd)
|
|
521
|
+
# 3. 使用unzip -t测试ZIP文件完整性(数组参数,避免路径注入)
|
|
522
|
+
system("unzip", "-t", zip_file, out: File::NULL, err: File::NULL)
|
|
524
523
|
rescue => e
|
|
525
524
|
false
|
|
526
525
|
end
|
|
527
526
|
|
|
528
527
|
# 使用curl下载文件
|
|
529
528
|
def download_with_curl(url, output_path)
|
|
530
|
-
#
|
|
531
|
-
|
|
532
|
-
system(cmd)
|
|
529
|
+
# 数组参数形式,避免 URL/路径中的 shell 元字符注入
|
|
530
|
+
system("curl", "-L", "-o", output_path, url)
|
|
533
531
|
rescue => e
|
|
534
532
|
false
|
|
535
533
|
end
|
|
@@ -537,9 +535,8 @@ module Pindo
|
|
|
537
535
|
# 解压Gradle分发包
|
|
538
536
|
def extract_gradle_distribution(zip_file, extract_dir, gradle_version)
|
|
539
537
|
begin
|
|
540
|
-
# 使用unzip
|
|
541
|
-
|
|
542
|
-
if system(extract_cmd)
|
|
538
|
+
# 使用unzip命令解压(数组参数 + chdir,避免路径注入)
|
|
539
|
+
if system("unzip", "-q", zip_file, chdir: File.dirname(extract_dir))
|
|
543
540
|
# 设置执行权限
|
|
544
541
|
gradle_script = File.join(extract_dir, "bin/gradle")
|
|
545
542
|
if File.exist?(gradle_script)
|
|
@@ -577,11 +574,8 @@ module Pindo
|
|
|
577
574
|
|
|
578
575
|
# 使用官方Gradle命令生成wrapper
|
|
579
576
|
def generate_gradle_wrapper_official(project_path, gradle_version)
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
cmd = "gradle wrapper"
|
|
583
|
-
system(cmd)
|
|
584
|
-
end
|
|
577
|
+
# 数组参数 + chdir,避免 shell 解析
|
|
578
|
+
system("gradle", "wrapper", chdir: project_path)
|
|
585
579
|
rescue => e
|
|
586
580
|
false
|
|
587
581
|
end
|
|
@@ -165,9 +165,9 @@ module Pindo
|
|
|
165
165
|
puts "找到 #{identity_ids.size} 个证书:"
|
|
166
166
|
puts identity_ids
|
|
167
167
|
|
|
168
|
-
#
|
|
168
|
+
# 删除证书(数组参数形式,避免 identity_id 拼接进 shell)
|
|
169
169
|
identity_ids.each do |identity_id|
|
|
170
|
-
system
|
|
170
|
+
system("security", "delete-certificate", "-Z", identity_id)
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
# 清理 Provisioning Profiles
|