pindo 5.13.12 → 5.13.13
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/funlog.rb +62 -5
- data/lib/pindo/base/git_handler.rb +83 -22
- data/lib/pindo/base/output_sink.rb +69 -0
- data/lib/pindo/command/android/autobuild.rb +57 -8
- data/lib/pindo/command/appstore/autobuild.rb +10 -1
- data/lib/pindo/command/ios/autobuild.rb +59 -7
- data/lib/pindo/command/jps/media.rb +164 -13
- data/lib/pindo/command/jps/upload.rb +14 -9
- data/lib/pindo/command/unity/autobuild.rb +64 -10
- data/lib/pindo/command/utils/tag.rb +9 -1
- data/lib/pindo/command/web/autobuild.rb +59 -10
- data/lib/pindo/module/android/android_build_helper.rb +6 -7
- data/lib/pindo/module/build/git_repo_helper.rb +29 -25
- data/lib/pindo/module/pgyer/pgyerhelper.rb +174 -77
- data/lib/pindo/module/task/core/concurrent_execution_strategy.rb +237 -0
- data/lib/pindo/module/task/core/dependency_checker.rb +123 -0
- data/lib/pindo/module/task/core/execution_strategy.rb +61 -0
- data/lib/pindo/module/task/core/resource_lock_manager.rb +190 -0
- data/lib/pindo/module/task/core/serial_execution_strategy.rb +60 -0
- data/lib/pindo/module/task/core/task_executor.rb +131 -0
- data/lib/pindo/module/task/core/task_queue.rb +221 -0
- data/lib/pindo/module/task/model/build/android_build_dev_task.rb +1 -1
- data/lib/pindo/module/task/model/build/android_build_task.rb +6 -2
- data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +2 -3
- data/lib/pindo/module/task/model/build/ios_build_task.rb +6 -0
- data/lib/pindo/module/task/model/build_task.rb +22 -0
- data/lib/pindo/module/task/model/git/git_commit_task.rb +11 -2
- data/lib/pindo/module/task/model/git_task.rb +6 -0
- data/lib/pindo/module/task/model/jps/jps_message_task.rb +9 -11
- data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +204 -103
- data/lib/pindo/module/task/model/jps_task.rb +0 -1
- data/lib/pindo/module/task/model/unity_task.rb +38 -2
- data/lib/pindo/module/task/output/multi_line_output_manager.rb +380 -0
- data/lib/pindo/module/task/output/multi_line_task_display.rb +185 -0
- data/lib/pindo/module/task/output/stdout_redirector.rb +95 -0
- data/lib/pindo/module/task/pindo_task.rb +133 -9
- data/lib/pindo/module/task/task_manager.rb +98 -268
- data/lib/pindo/module/task/task_reporter.rb +135 -0
- data/lib/pindo/module/task/task_resources/resource_instance.rb +90 -0
- data/lib/pindo/module/task/task_resources/resource_registry.rb +105 -0
- data/lib/pindo/module/task/task_resources/resource_type.rb +59 -0
- data/lib/pindo/module/task/task_resources/types/directory_based_resource.rb +63 -0
- data/lib/pindo/module/task/task_resources/types/global_exclusive_resource.rb +33 -0
- data/lib/pindo/module/task/task_resources/types/global_shared_resource.rb +34 -0
- data/lib/pindo/module/xcode/xcode_build_helper.rb +26 -8
- data/lib/pindo/options/groups/jps_options.rb +10 -0
- data/lib/pindo/options/groups/task_options.rb +39 -0
- data/lib/pindo/version.rb +3 -2
- metadata +20 -1
|
@@ -10,10 +10,10 @@ module Pindo
|
|
|
10
10
|
#
|
|
11
11
|
# 支持两种模式:
|
|
12
12
|
# 1. 指定模式:传入 file_paths 和 git_commit_id
|
|
13
|
-
# 2. 自动模式:只传入
|
|
13
|
+
# 2. 自动模式:只传入 upload_path,自动查找 JPSMedia/ 目录和 git HEAD 信息
|
|
14
14
|
class JPSUploadMediaTask < JPSTask
|
|
15
15
|
attr_reader :file_paths, :git_commit_id, :git_commit_time, :git_commit_desc
|
|
16
|
-
attr_reader :
|
|
16
|
+
attr_reader :upload_path
|
|
17
17
|
|
|
18
18
|
# 支持的媒体文件扩展名
|
|
19
19
|
MEDIA_EXTENSIONS = %w[png jpg jpeg gif bmp webp mp4 mov avi mkv webm].freeze
|
|
@@ -25,20 +25,20 @@ module Pindo
|
|
|
25
25
|
|
|
26
26
|
# 初始化 Media 上传任务
|
|
27
27
|
# @param file_paths [Array<String>] 要上传的文件路径列表(可选,为空时自动查找)
|
|
28
|
+
# @param upload_path [String] 项目路径(必需,用于查找 git 仓库和 JPSMedia 目录)
|
|
28
29
|
# @param options [Hash] 选项
|
|
29
30
|
# @option options [String] :git_commit_id Git commit SHA(可选,为空时自动获取 HEAD)
|
|
30
31
|
# @option options [String] :git_commit_time Git commit 时间(可选)
|
|
31
32
|
# @option options [String] :git_commit_desc Git commit 描述(可选)
|
|
32
|
-
# @option options [
|
|
33
|
-
# @option options [
|
|
34
|
-
# @option options [String] :
|
|
35
|
-
def initialize(file_paths, options = {})
|
|
33
|
+
# @option options [Hash] :app_info_obj JPS 应用信息对象(可选,继承自基类)
|
|
34
|
+
# @option options [Hash] :workflow_info 工作流信息(可选,继承自基类)
|
|
35
|
+
# @option options [String] :project_name 项目名称(可选,继承自基类)
|
|
36
|
+
def initialize(file_paths, upload_path, options = {})
|
|
36
37
|
@file_paths = file_paths || [] # 要上传的文件路径列表
|
|
38
|
+
@upload_path = upload_path # 项目路径
|
|
37
39
|
@git_commit_id = options[:git_commit_id] # Git commit SHA
|
|
38
40
|
@git_commit_time = options[:git_commit_time] # Git commit 时间
|
|
39
41
|
@git_commit_desc = options[:git_commit_desc] # Git commit 描述
|
|
40
|
-
@workflow_id = options[:workflow_id] # 工作流ID
|
|
41
|
-
@project_path = options[:project_path] # 项目路径
|
|
42
42
|
|
|
43
43
|
# 设置任务优先级为 LOW,确保在其他任务之后执行
|
|
44
44
|
options[:priority] ||= TaskPriority::LOW
|
|
@@ -49,12 +49,14 @@ module Pindo
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def validate
|
|
52
|
-
# 验证
|
|
53
|
-
unless @
|
|
54
|
-
@error = "缺少必需参数:
|
|
52
|
+
# 验证 upload_path(必需参数)
|
|
53
|
+
unless @upload_path && !@upload_path.empty? && Dir.exist?(@upload_path)
|
|
54
|
+
@error = "缺少必需参数: upload_path(项目路径)或路径不存在"
|
|
55
55
|
return false
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
# workflow_info 可以延迟获取,不在这里验证
|
|
59
|
+
|
|
58
60
|
true
|
|
59
61
|
end
|
|
60
62
|
|
|
@@ -88,14 +90,14 @@ module Pindo
|
|
|
88
90
|
|
|
89
91
|
def do_work
|
|
90
92
|
# 1. 查找 git 仓库根目录
|
|
91
|
-
git_root = find_git_root(@
|
|
93
|
+
git_root = find_git_root(@upload_path)
|
|
92
94
|
unless git_root
|
|
93
|
-
raise "未找到 git 仓库,请确保
|
|
95
|
+
raise "未找到 git 仓库,请确保 upload_path 在 git 仓库内"
|
|
94
96
|
end
|
|
95
97
|
|
|
96
|
-
# 2. 如果没有提供 git_commit_id
|
|
98
|
+
# 2. 如果没有提供 git_commit_id,获取最新的符合规范的 commit
|
|
97
99
|
if @git_commit_id.nil? || @git_commit_id.empty?
|
|
98
|
-
git_info =
|
|
100
|
+
git_info = Pindo::GitHandler.get_latest_conventional_commit(project_dir: git_root)
|
|
99
101
|
@git_commit_id = git_info[:commit_id]
|
|
100
102
|
@git_commit_time = git_info[:commit_time]
|
|
101
103
|
@git_commit_desc = git_info[:commit_desc]
|
|
@@ -107,13 +109,11 @@ module Pindo
|
|
|
107
109
|
end
|
|
108
110
|
|
|
109
111
|
# 3. 打印 git commit 信息
|
|
110
|
-
puts
|
|
111
|
-
puts "
|
|
112
|
-
puts "
|
|
113
|
-
puts "
|
|
114
|
-
puts "
|
|
115
|
-
puts " " + "=" * 28
|
|
116
|
-
puts
|
|
112
|
+
puts ""
|
|
113
|
+
puts " 📝 Commit: #{@git_commit_desc}" if @git_commit_desc
|
|
114
|
+
puts " ID: #{@git_commit_id[0..7]}"
|
|
115
|
+
puts " Time: #{@git_commit_time}" if @git_commit_time
|
|
116
|
+
puts ""
|
|
117
117
|
|
|
118
118
|
# 4. 处理文件路径
|
|
119
119
|
if @file_paths.nil? || @file_paths.empty?
|
|
@@ -124,11 +124,17 @@ module Pindo
|
|
|
124
124
|
@file_paths = expand_file_paths(@file_paths)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
-
#
|
|
127
|
+
# 5. 自动压缩文件(如果有文件需要上传)
|
|
128
|
+
if @file_paths.any?
|
|
129
|
+
@file_paths = compress_media_files(@file_paths, git_root)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# 6. 过滤存在的文件
|
|
128
133
|
existing_files = @file_paths.select { |f| File.exist?(f) }
|
|
129
134
|
if existing_files.empty?
|
|
130
|
-
puts " 没有找到有效的 media 文件"
|
|
135
|
+
puts " ❌ 没有找到有效的 media 文件"
|
|
131
136
|
puts " 提示: 请在项目根目录创建 JPSMedia/ 目录并放入要上传的图片或视频文件"
|
|
137
|
+
puts ""
|
|
132
138
|
return {
|
|
133
139
|
success: false,
|
|
134
140
|
success_urls: [],
|
|
@@ -141,23 +147,23 @@ module Pindo
|
|
|
141
147
|
}
|
|
142
148
|
end
|
|
143
149
|
|
|
144
|
-
|
|
145
|
-
existing_files.each_with_index do |file, index|
|
|
146
|
-
puts " #{index + 1}. #{File.basename(file)}"
|
|
147
|
-
end
|
|
148
|
-
puts
|
|
149
|
-
|
|
150
|
-
# 5. 确保 PgyerHelper 已登录
|
|
150
|
+
# 7. 确保 PgyerHelper 已登录
|
|
151
151
|
pgyer_helper = PgyerHelper.share_instace
|
|
152
152
|
unless pgyer_helper.login
|
|
153
153
|
raise "JPS 登录失败"
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
#
|
|
156
|
+
# 8. 从 workflow_info 提取 workflow_id
|
|
157
|
+
workflow_id = @workflow_info&.dig(:workflow_id) || @workflow_info&.dig('id')
|
|
158
|
+
unless workflow_id
|
|
159
|
+
raise "缺少 workflow_info,无法获取 workflow_id"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# 9. 调用 PgyerHelper 的 start_media_upload 方法
|
|
157
163
|
upload_result = pgyer_helper.start_media_upload(
|
|
158
164
|
file_paths: existing_files,
|
|
159
165
|
git_commit_id: @git_commit_id,
|
|
160
|
-
workflow_id:
|
|
166
|
+
workflow_id: workflow_id
|
|
161
167
|
)
|
|
162
168
|
|
|
163
169
|
# 7. 判断是否成功
|
|
@@ -200,43 +206,14 @@ module Pindo
|
|
|
200
206
|
nil
|
|
201
207
|
end
|
|
202
208
|
|
|
203
|
-
# 获取 git HEAD 信息
|
|
204
|
-
# @param git_root [String] git 仓库根目录
|
|
205
|
-
# @return [Hash] 包含 :commit_id, :commit_time, :commit_desc
|
|
206
|
-
def get_git_head_info(git_root)
|
|
207
|
-
result = {
|
|
208
|
-
commit_id: nil,
|
|
209
|
-
commit_time: nil,
|
|
210
|
-
commit_desc: nil
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
Dir.chdir(git_root) do
|
|
214
|
-
# 获取 HEAD commit id
|
|
215
|
-
commit_id = `git rev-parse HEAD 2>/dev/null`.strip
|
|
216
|
-
result[:commit_id] = commit_id unless commit_id.empty?
|
|
217
|
-
|
|
218
|
-
# 获取 commit time (ISO 8601 格式)
|
|
219
|
-
commit_time = `git log -1 --format=%ci 2>/dev/null`.strip
|
|
220
|
-
result[:commit_time] = commit_time unless commit_time.empty?
|
|
221
|
-
|
|
222
|
-
# 获取 commit message (第一行)
|
|
223
|
-
commit_desc = `git log -1 --format=%s 2>/dev/null`.strip
|
|
224
|
-
result[:commit_desc] = commit_desc unless commit_desc.empty?
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
result
|
|
228
|
-
end
|
|
229
|
-
|
|
230
209
|
# 展开文件路径(支持通配符和目录)
|
|
231
|
-
#
|
|
232
|
-
# 超过时间的文件自动移动到 Backup_日期 子目录
|
|
210
|
+
# 自动过滤 3 小时以内的文件,超过 3 小时的文件归档
|
|
233
211
|
# @param paths [Array<String>] 原始路径列表
|
|
234
|
-
# @return [Array<String>]
|
|
212
|
+
# @return [Array<String>] 展开后的文件路径列表(3 小时以内)
|
|
235
213
|
def expand_file_paths(paths)
|
|
236
214
|
return [] if paths.nil? || paths.empty?
|
|
237
215
|
|
|
238
216
|
expanded = []
|
|
239
|
-
time_threshold = Time.now - (3 * 60 * 60) # 3 小时前
|
|
240
217
|
|
|
241
218
|
paths.each do |path|
|
|
242
219
|
if path.include?('*')
|
|
@@ -257,29 +234,8 @@ module Pindo
|
|
|
257
234
|
# 去重并过滤有效文件
|
|
258
235
|
valid_files = expanded.uniq.select { |f| File.file?(f) }
|
|
259
236
|
|
|
260
|
-
#
|
|
261
|
-
|
|
262
|
-
expired_files = []
|
|
263
|
-
|
|
264
|
-
valid_files.each do |f|
|
|
265
|
-
mtime = File.mtime(f)
|
|
266
|
-
ctime = File.ctime(f)
|
|
267
|
-
# 取创建时间和更新时间中较新的一个
|
|
268
|
-
latest_time = [mtime, ctime].max
|
|
269
|
-
|
|
270
|
-
if latest_time >= time_threshold
|
|
271
|
-
recent_files << f
|
|
272
|
-
else
|
|
273
|
-
expired_files << f
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# 移动超时文件到备份目录
|
|
278
|
-
if expired_files.any?
|
|
279
|
-
move_expired_files_to_backup(expired_files)
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
recent_files
|
|
237
|
+
# 应用时间过滤(3 小时以内)并自动归档超时文件
|
|
238
|
+
filter_files_by_time(valid_files)
|
|
283
239
|
end
|
|
284
240
|
|
|
285
241
|
# 将超时文件移动到备份目录
|
|
@@ -287,10 +243,10 @@ module Pindo
|
|
|
287
243
|
def move_expired_files_to_backup(files)
|
|
288
244
|
return if files.empty?
|
|
289
245
|
|
|
290
|
-
# 备份目录名:
|
|
291
|
-
backup_dir_name = "
|
|
246
|
+
# 备份目录名:backup_YYYY-MM-DD_HHMMSS
|
|
247
|
+
backup_dir_name = "backup_#{Time.now.strftime('%Y-%m-%d_%H%M%S')}"
|
|
292
248
|
|
|
293
|
-
puts "
|
|
249
|
+
puts " 📦 归档 #{files.size} 个超时文件 → JPSMedia/#{backup_dir_name}/"
|
|
294
250
|
|
|
295
251
|
files.each do |file_path|
|
|
296
252
|
begin
|
|
@@ -305,41 +261,186 @@ module Pindo
|
|
|
305
261
|
file_name = File.basename(file_path)
|
|
306
262
|
dest_path = File.join(backup_dir, file_name)
|
|
307
263
|
|
|
308
|
-
#
|
|
264
|
+
# 如果目标文件已存在,添加序号避免覆盖
|
|
309
265
|
if File.exist?(dest_path)
|
|
310
266
|
ext = File.extname(file_name)
|
|
311
267
|
base = File.basename(file_name, ext)
|
|
312
|
-
|
|
313
|
-
|
|
268
|
+
counter = 1
|
|
269
|
+
while File.exist?(dest_path)
|
|
270
|
+
dest_path = File.join(backup_dir, "#{base}_#{counter}#{ext}")
|
|
271
|
+
counter += 1
|
|
272
|
+
end
|
|
314
273
|
end
|
|
315
274
|
|
|
316
275
|
FileUtils.mv(file_path, dest_path)
|
|
317
|
-
puts "
|
|
276
|
+
puts " ✓ #{file_name}"
|
|
318
277
|
rescue => e
|
|
319
|
-
|
|
278
|
+
puts " ✗ #{file_name} - #{e.message}"
|
|
320
279
|
end
|
|
321
280
|
end
|
|
322
281
|
end
|
|
323
282
|
|
|
324
|
-
# 在 JPSMedia 目录下查找 media
|
|
283
|
+
# 在 JPSMedia 目录下查找 media 文件(仅查找根目录,不递归子目录)
|
|
284
|
+
# 自动过滤 3 小时以内的文件,超过 3 小时的文件归档
|
|
325
285
|
# @param git_root [String] git 仓库根目录
|
|
326
|
-
# @return [Array<String>]
|
|
286
|
+
# @return [Array<String>] 找到的文件路径列表(3 小时以内)
|
|
327
287
|
def find_media_files(git_root)
|
|
328
288
|
jps_media_dir = File.join(git_root, 'JPSMedia')
|
|
329
289
|
|
|
330
290
|
unless File.directory?(jps_media_dir)
|
|
331
|
-
puts " 未找到 JPSMedia/ 目录: #{jps_media_dir}"
|
|
291
|
+
puts " ❌ 未找到 JPSMedia/ 目录: #{jps_media_dir}"
|
|
332
292
|
return []
|
|
333
293
|
end
|
|
334
294
|
|
|
335
|
-
puts "
|
|
295
|
+
puts " 🔍 查找 JPSMedia/ 目录下的媒体文件(3 小时以内)..."
|
|
336
296
|
|
|
337
|
-
#
|
|
338
|
-
pattern = File.join(jps_media_dir, "
|
|
339
|
-
|
|
297
|
+
# 只查找 JPSMedia/ 目录下的文件(不递归子目录)
|
|
298
|
+
pattern = File.join(jps_media_dir, "*.{#{MEDIA_EXTENSIONS.join(',')}}")
|
|
299
|
+
all_files = Dir.glob(pattern, File::FNM_CASEFOLD)
|
|
340
300
|
|
|
341
301
|
# 过滤有效文件并去重
|
|
342
|
-
|
|
302
|
+
valid_files = all_files.uniq.select { |f| File.file?(f) }
|
|
303
|
+
|
|
304
|
+
if valid_files.empty?
|
|
305
|
+
puts " ⚠️ 目录为空或没有支持的媒体文件"
|
|
306
|
+
return []
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# 应用时间过滤(3 小时以内)并自动归档超时文件
|
|
310
|
+
filter_files_by_time(valid_files)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# 压缩媒体文件(批量压缩)
|
|
314
|
+
# @param files [Array<String>] 要压缩的文件列表
|
|
315
|
+
# @param git_root [String] git 仓库根目录
|
|
316
|
+
# @return [Array<String>] 压缩后的文件路径列表
|
|
317
|
+
def compress_media_files(files, git_root)
|
|
318
|
+
return [] if files.nil? || files.empty?
|
|
319
|
+
|
|
320
|
+
# 创建临时压缩输出目录: JPSMedia/compress_cli_YYYY-MM-DD_HHMMSS
|
|
321
|
+
# 放在 JPSMedia 目录下,避免污染 git 根目录
|
|
322
|
+
compress_dir_name = "compress_cli_#{Time.now.strftime('%Y-%m-%d_%H%M%S')}"
|
|
323
|
+
jps_media_dir = File.join(git_root, "JPSMedia")
|
|
324
|
+
compress_dir = File.join(jps_media_dir, compress_dir_name)
|
|
325
|
+
|
|
326
|
+
FileUtils.mkdir_p(compress_dir) unless Dir.exist?(compress_dir)
|
|
327
|
+
|
|
328
|
+
puts ""
|
|
329
|
+
puts " 📁 待压缩文件(共 #{files.size} 个)"
|
|
330
|
+
files.each_with_index do |file, index|
|
|
331
|
+
size_str = format_file_size(File.size(file))
|
|
332
|
+
file_name = File.basename(file)
|
|
333
|
+
puts " #{index + 1}. #{file_name} (#{size_str})"
|
|
334
|
+
end
|
|
335
|
+
puts ""
|
|
336
|
+
|
|
337
|
+
# MacCompressCliTool 路径
|
|
338
|
+
pindo_dir = File.expand_path(Pindoconfig.instance.pindo_dir)
|
|
339
|
+
compress_tool = File.join(pindo_dir, "pindo_common_config", "MacCompressCliTool")
|
|
340
|
+
|
|
341
|
+
# 检查压缩工具是否存在
|
|
342
|
+
unless File.exist?(compress_tool)
|
|
343
|
+
raise "未找到压缩工具: #{compress_tool}"
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# 计算原始文件总大小
|
|
347
|
+
original_total_size = files.sum { |f| File.size(f) }
|
|
348
|
+
|
|
349
|
+
# 构建文件列表参数: -f file1.mp4,file2.png,file3.mov
|
|
350
|
+
file_list = files.map { |f| "\"#{f}\"" }.join(',')
|
|
351
|
+
|
|
352
|
+
# 调用压缩工具: compress-cli -s -f file1,file2,file3 -o output_dir/
|
|
353
|
+
# -s: 静默模式
|
|
354
|
+
# -f: 文件列表
|
|
355
|
+
# -o: 输出目录
|
|
356
|
+
# 使用默认参数: 分辨率等级 3 (1280x720), 质量等级 3
|
|
357
|
+
cmd = "#{compress_tool} -s -f #{file_list} -o \"#{compress_dir}\""
|
|
358
|
+
|
|
359
|
+
Funlog.instance.fancyinfo_start("正在压缩 #{files.size} 个文件...")
|
|
360
|
+
output = `#{cmd} 2>&1`
|
|
361
|
+
exit_code = $?.exitstatus
|
|
362
|
+
|
|
363
|
+
if exit_code != 0
|
|
364
|
+
Funlog.instance.fancyinfo_error("压缩失败")
|
|
365
|
+
puts " 错误信息: #{output.strip}" if output && !output.strip.empty?
|
|
366
|
+
raise "媒体文件批量压缩失败: #{output.strip}"
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# 从临时目录获取所有压缩后的媒体文件
|
|
370
|
+
compressed_files = get_media_files_from_dir(compress_dir)
|
|
371
|
+
|
|
372
|
+
if compressed_files.empty?
|
|
373
|
+
Funlog.instance.fancyinfo_error("压缩失败:未找到压缩结果")
|
|
374
|
+
raise "压缩失败:未在输出目录中找到压缩结果"
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# 计算压缩后总大小
|
|
378
|
+
compressed_total_size = compressed_files.sum { |f| File.size(f) }
|
|
379
|
+
total_ratio = ((1 - compressed_total_size.to_f / original_total_size) * 100).round(1)
|
|
380
|
+
|
|
381
|
+
# 显示压缩统计
|
|
382
|
+
Funlog.instance.fancyinfo_success("压缩完成:#{format_file_size(original_total_size)} → #{format_file_size(compressed_total_size)}(减少 #{total_ratio}%)")
|
|
383
|
+
puts ""
|
|
384
|
+
|
|
385
|
+
compressed_files
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# 从目录获取所有媒体文件
|
|
389
|
+
# @param dir [String] 目录路径
|
|
390
|
+
# @return [Array<String>] 媒体文件路径列表
|
|
391
|
+
def get_media_files_from_dir(dir)
|
|
392
|
+
return [] unless Dir.exist?(dir)
|
|
393
|
+
|
|
394
|
+
# 使用 MEDIA_EXTENSIONS 常量构建匹配模式
|
|
395
|
+
pattern = File.join(dir, "*.{#{MEDIA_EXTENSIONS.join(',')}}")
|
|
396
|
+
Dir.glob(pattern).select { |f| File.file?(f) }.sort
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# 格式化文件大小
|
|
400
|
+
# @param size [Integer] 字节数
|
|
401
|
+
# @return [String] 格式化后的大小
|
|
402
|
+
def format_file_size(size)
|
|
403
|
+
if size < 1024
|
|
404
|
+
"#{size}B"
|
|
405
|
+
elsif size < 1024 * 1024
|
|
406
|
+
"#{(size / 1024.0).round(1)}KB"
|
|
407
|
+
else
|
|
408
|
+
"#{(size / 1024.0 / 1024.0).round(1)}MB"
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# 按时间过滤文件(3 小时以内)
|
|
413
|
+
# 超过 3 小时的文件自动移动到备份目录
|
|
414
|
+
# @param files [Array<String>] 文件列表
|
|
415
|
+
# @return [Array<String>] 3 小时以内的文件列表
|
|
416
|
+
def filter_files_by_time(files)
|
|
417
|
+
return [] if files.nil? || files.empty?
|
|
418
|
+
|
|
419
|
+
time_threshold = Time.now - (3 * 60 * 60) # 3 小时前
|
|
420
|
+
|
|
421
|
+
# 分离:3 小时以内的文件 和 超时的文件
|
|
422
|
+
recent_files = []
|
|
423
|
+
expired_files = []
|
|
424
|
+
|
|
425
|
+
files.each do |f|
|
|
426
|
+
mtime = File.mtime(f)
|
|
427
|
+
ctime = File.ctime(f)
|
|
428
|
+
# 取创建时间和更新时间中较新的一个
|
|
429
|
+
latest_time = [mtime, ctime].max
|
|
430
|
+
|
|
431
|
+
if latest_time >= time_threshold
|
|
432
|
+
recent_files << f
|
|
433
|
+
else
|
|
434
|
+
expired_files << f
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
# 移动超时文件到备份目录
|
|
439
|
+
if expired_files.any?
|
|
440
|
+
move_expired_files_to_backup(expired_files)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
recent_files
|
|
343
444
|
end
|
|
344
445
|
|
|
345
446
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'pindo/module/task/pindo_task'
|
|
2
2
|
require 'pindo/module/unity/unity_helper'
|
|
3
3
|
require 'pindo/module/unity/unity_proc_helper'
|
|
4
|
+
require 'pindo/base/git_handler'
|
|
4
5
|
|
|
5
6
|
module Pindo
|
|
6
7
|
module TaskSystem
|
|
@@ -10,12 +11,22 @@ module Pindo
|
|
|
10
11
|
attr_reader :project_path, :unity_root_path
|
|
11
12
|
|
|
12
13
|
def initialize(name, options = {})
|
|
13
|
-
@project_path = options[:project_path] ?
|
|
14
|
-
@unity_root_path = options[:unity_root_path]
|
|
14
|
+
@project_path = options[:project_path] ? normalize_path(options[:project_path]) : nil
|
|
15
|
+
@unity_root_path = options[:unity_root_path] ? normalize_path(options[:unity_root_path]) : @project_path
|
|
15
16
|
|
|
16
17
|
super(name, options)
|
|
17
18
|
end
|
|
18
19
|
|
|
20
|
+
# 规范化路径辅助方法
|
|
21
|
+
def normalize_path(path)
|
|
22
|
+
return nil if path.nil?
|
|
23
|
+
begin
|
|
24
|
+
File.realpath(File.expand_path(path))
|
|
25
|
+
rescue
|
|
26
|
+
File.expand_path(path)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
# Unity 任务类型
|
|
20
31
|
def self.task_type
|
|
21
32
|
:unity
|
|
@@ -59,6 +70,17 @@ module Pindo
|
|
|
59
70
|
@unity_helper ||= Pindo::Unity::UnityHelper.share_instance
|
|
60
71
|
end
|
|
61
72
|
|
|
73
|
+
# 声明所需资源(锁住项目目录,防止并发执行)
|
|
74
|
+
def required_resources
|
|
75
|
+
# 1. Unity 资源:锁定 Unity 项目目录
|
|
76
|
+
# 2. Build 资源:锁定构建目录(git 仓库或项目目录)
|
|
77
|
+
build_lock_dir = get_build_lock_directory
|
|
78
|
+
(super || []) + [
|
|
79
|
+
{ type: :unity, directory: @unity_root_path },
|
|
80
|
+
{ type: :build, directory: build_lock_dir }
|
|
81
|
+
]
|
|
82
|
+
end
|
|
83
|
+
|
|
62
84
|
# 重试前清理 Unity 进程
|
|
63
85
|
def before_retry
|
|
64
86
|
super
|
|
@@ -67,6 +89,20 @@ module Pindo
|
|
|
67
89
|
|
|
68
90
|
protected
|
|
69
91
|
|
|
92
|
+
# 获取 build 资源锁定的目录
|
|
93
|
+
# 优先使用 git 根目录(如果在 git 仓库内),否则使用 Unity 根目录
|
|
94
|
+
# 这样可以确保同一 git 仓库下的所有构建任务串行执行
|
|
95
|
+
def get_build_lock_directory
|
|
96
|
+
return @unity_root_path unless @unity_root_path
|
|
97
|
+
|
|
98
|
+
begin
|
|
99
|
+
git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: @unity_root_path)
|
|
100
|
+
git_root || @unity_root_path
|
|
101
|
+
rescue
|
|
102
|
+
@unity_root_path
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
70
106
|
# 检查 Unity 项目是否有效
|
|
71
107
|
def valid_unity_project?
|
|
72
108
|
# 检查是否存在 Assets 和 ProjectSettings 目录
|