pindo 5.1.5 → 5.1.6
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/command/android/autobuild.rb +1 -1
- data/lib/pindo/command/ios/autobuild.rb +1 -1
- data/lib/pindo/command/pgyer/upload.rb +1 -0
- data/lib/pindo/command/unity/apk.rb +1 -1
- data/lib/pindo/command/unity/autobuild.rb +2 -2
- data/lib/pindo/command/unity/ipa.rb +1 -1
- data/lib/pindo/command/unity/web.rb +2 -2
- data/lib/pindo/command/web/autobuild.rb +2 -2
- data/lib/pindo/module/android/apk_helper.rb +33 -5
- data/lib/pindo/module/android/base_helper.rb +223 -124
- data/lib/pindo/module/android/build_helper.rb +4 -4
- data/lib/pindo/module/android/gradle_helper.rb +10 -1
- data/lib/pindo/module/build/buildhelper.rb +34 -27
- data/lib/pindo/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeb5144aeaf56d2e5bafd3484f8217e9e4ce46a54485eb9b2b5d454cfe3c34fe
|
4
|
+
data.tar.gz: abf8c96e71101c513b825593aa6627e5252770a31d144afe6803bec6b030cda0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b01b26770891a88284b6e2c63ed10f9fc22cb13f17038a648655ea856eb6fc9eaf3392032faf991662e2d2ac1c20a3ebe59aa439a339150c8d96f5a0fceda53
|
7
|
+
data.tar.gz: 0ddad442cb9c1973230a91931f3d38f4ed6089aab55c65f07661d600ccc9f91dba7950a70ac3ed144af1a7f1f71a80ef5a52c9eaa50301d81f7914efd763d53a
|
@@ -88,7 +88,7 @@ module Pindo
|
|
88
88
|
|
89
89
|
build_helper = Pindo::BuildHelper.share_instance
|
90
90
|
if @args_upload_flag
|
91
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
91
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
92
92
|
if is_need_add_tag
|
93
93
|
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
94
94
|
end
|
@@ -108,7 +108,7 @@ module Pindo
|
|
108
108
|
pindo_project_dir = Dir.pwd
|
109
109
|
build_helper = Pindo::BuildHelper.share_instance
|
110
110
|
if @args_upload_flag
|
111
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
111
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
112
112
|
if is_need_add_tag
|
113
113
|
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
114
114
|
end
|
@@ -108,6 +108,7 @@ module Pindo
|
|
108
108
|
build_helper = Pindo::BuildHelper.share_instance
|
109
109
|
|
110
110
|
Dir.chdir(current_project_dir)
|
111
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(current_project_dir)
|
111
112
|
if is_need_add_tag
|
112
113
|
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
113
114
|
end
|
@@ -78,7 +78,7 @@ module Pindo
|
|
78
78
|
end
|
79
79
|
build_helper = Pindo::BuildHelper.share_instance
|
80
80
|
if @args_upload_flag
|
81
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
81
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
82
82
|
if is_need_add_tag
|
83
83
|
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
84
84
|
end
|
@@ -78,9 +78,9 @@ module Pindo
|
|
78
78
|
|
79
79
|
if @args_upload_flag
|
80
80
|
build_helper = Pindo::BuildHelper.share_instance
|
81
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
81
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
82
82
|
if is_need_add_tag
|
83
|
-
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
83
|
+
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -88,7 +88,7 @@ module Pindo
|
|
88
88
|
|
89
89
|
build_helper = Pindo::BuildHelper.share_instance
|
90
90
|
if @args_upload_flag
|
91
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
91
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
92
92
|
if is_need_add_tag
|
93
93
|
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
94
94
|
end
|
@@ -87,9 +87,9 @@ module Pindo
|
|
87
87
|
|
88
88
|
if @args_upload_flag
|
89
89
|
build_helper = Pindo::BuildHelper.share_instance
|
90
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
90
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
91
91
|
if is_need_add_tag
|
92
|
-
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
92
|
+
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -110,9 +110,9 @@ module Pindo
|
|
110
110
|
build_helper = Pindo::BuildHelper.share_instance
|
111
111
|
|
112
112
|
if @args_upload_flag
|
113
|
-
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir)
|
113
|
+
is_need_add_tag,tag_action_parms = build_helper.check_is_need_add_tag?(pindo_project_dir, auto_mode: true)
|
114
114
|
if is_need_add_tag
|
115
|
-
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
115
|
+
Pindo::Command::Dev::Tag::run(tag_action_parms)
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -43,15 +43,43 @@ module Pindo
|
|
43
43
|
raise RuntimeError, "找不到 AAB 文件: #{paths[:bundle]}"
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
# --- AAB 包体积检测 ---
|
47
|
+
aab_size = File.size(paths[:bundle])
|
48
|
+
aab_size_mb = (aab_size.to_f / 1024 / 1024).round(2)
|
49
|
+
base_size = 0
|
50
|
+
base_size_mb = 0
|
51
|
+
base_percent = 0
|
52
|
+
base_limit_bytes = 194615705 # 185MB
|
53
|
+
base_limit_mb = 185
|
54
|
+
begin
|
55
|
+
# 用 unzip -v 统计 base/ 文件夹压缩体积
|
56
|
+
unzip_out = `unzip -v "#{paths[:bundle]}"`
|
57
|
+
base_lines = unzip_out.lines.select { |l| l.include?(" base/") }
|
58
|
+
base_size = base_lines.map { |l| l.split[2].to_i }.sum
|
59
|
+
base_size_mb = (base_size.to_f / 1024 / 1024).round(2)
|
60
|
+
base_percent = aab_size > 0 ? ((base_size.to_f * 100) / aab_size).round(2) : 0
|
61
|
+
rescue => e
|
62
|
+
puts "\e[31mAAB base 文件夹体积检测失败: #{e.message}\e[0m"
|
63
|
+
end
|
64
|
+
puts "\e[36mAAB 包体积: #{aab_size_mb} MB\e[0m"
|
65
|
+
puts "\e[36mbase 文件夹压缩体积: #{base_size_mb} MB (占比 #{base_percent}%)\e[0m"
|
66
|
+
if base_size > base_limit_bytes
|
67
|
+
puts "\e[41;97m警告: base 文件夹已超出 Google Play 限制(#{base_limit_mb}MB),请优化资源或分包!\e[0m"
|
68
|
+
puts "\e[31mAAB 包体积不符合 Google Play 提交标准,需要缩减包体积才能提交!!!\e[0m"
|
69
|
+
else
|
70
|
+
puts "\e[32mAAB 包体积符合 Google Play 提交标准,可以正常提交\e[0m"
|
71
|
+
end
|
72
|
+
# --- END ---
|
73
|
+
|
74
|
+
# puts "解析 keystore 配置"
|
47
75
|
ks = keystore_config[:store_file]
|
48
|
-
puts "读取 keystore path = #{ks}"
|
76
|
+
# puts "读取 keystore path = #{ks}"
|
49
77
|
ks_pass = keystore_config[:store_password]
|
50
|
-
puts "读取 keystore pass = #{ks_pass}"
|
78
|
+
# puts "读取 keystore pass = #{ks_pass}"
|
51
79
|
key_alias = keystore_config[:key_alias]
|
52
|
-
puts "读取 key alias = #{key_alias}"
|
80
|
+
# puts "读取 key alias = #{key_alias}"
|
53
81
|
key_pass = keystore_config[:key_password]
|
54
|
-
puts "读取 key pass = #{key_pass}"
|
82
|
+
# puts "读取 key pass = #{key_pass}"
|
55
83
|
|
56
84
|
# 构建 APK
|
57
85
|
bundletool_cmd = [
|
@@ -67,17 +67,34 @@ module Pindo
|
|
67
67
|
|
68
68
|
def get_main_module(project_path)
|
69
69
|
settings_gradle_path = File.join(project_path, "settings.gradle")
|
70
|
-
|
70
|
+
settings_gradle_kts_path = File.join(project_path, "settings.gradle.kts")
|
71
|
+
|
72
|
+
# 优先使用 settings.gradle.kts,如果不存在则使用 settings.gradle
|
73
|
+
if File.exist?(settings_gradle_kts_path)
|
74
|
+
settings_gradle_path = settings_gradle_kts_path
|
75
|
+
elsif !File.exist?(settings_gradle_path)
|
76
|
+
return nil
|
77
|
+
end
|
71
78
|
|
72
79
|
content = File.read(settings_gradle_path)
|
73
|
-
|
80
|
+
# 兼容 include ':app' 和 include(":app")
|
81
|
+
modules = content.scan(/include\s*\(?\s*['\"]?([:\w\-]+)['\"]?\s*\)?/).flatten
|
74
82
|
|
75
83
|
main_module = modules.find do |m|
|
76
84
|
module_name = m.split(':').last
|
77
85
|
gradle_path = File.join(project_path, module_name, "build.gradle")
|
86
|
+
gradle_kts_path = File.join(project_path, module_name, "build.gradle.kts")
|
87
|
+
|
88
|
+
# 优先使用 build.gradle.kts,如果不存在则使用 build.gradle
|
89
|
+
if File.exist?(gradle_kts_path)
|
90
|
+
gradle_path = gradle_kts_path
|
91
|
+
end
|
92
|
+
|
78
93
|
if File.exist?(gradle_path)
|
79
|
-
File.read(gradle_path)
|
80
|
-
|
94
|
+
gradle_content = File.read(gradle_path)
|
95
|
+
gradle_content.include?("apply plugin: 'com.android.application") ||
|
96
|
+
gradle_content.include?("id 'com.android.application") ||
|
97
|
+
(gradle_content.include?("plugins {") && gradle_content.include?("com.android.application"))
|
81
98
|
end
|
82
99
|
end
|
83
100
|
return nil unless main_module
|
@@ -90,153 +107,225 @@ module Pindo
|
|
90
107
|
main_module = get_main_module(project_path)
|
91
108
|
return nil unless main_module
|
92
109
|
|
93
|
-
|
94
|
-
|
110
|
+
gradle_kts_path = File.join(main_module, "build.gradle.kts")
|
111
|
+
gradle_path = File.join(main_module, "build.gradle")
|
112
|
+
|
113
|
+
if File.exist?(gradle_kts_path)
|
114
|
+
puts "KTS 项目,读取 #{File.basename(gradle_kts_path)} 文件"
|
115
|
+
get_keystore_config_kts(gradle_kts_path, project_path, debug)
|
116
|
+
elsif File.exist?(gradle_path)
|
117
|
+
puts "Groovy 项目,读取 #{File.basename(gradle_path)} 文件"
|
118
|
+
get_keystore_config_groovy(gradle_path, project_path, debug)
|
119
|
+
else
|
120
|
+
puts "未找到 build.gradle 或 build.gradle.kts 文件"
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# 处理 Kotlin DSL (build.gradle.kts)
|
126
|
+
def get_keystore_config_kts(gradle_kts_path, project_path, debug)
|
127
|
+
content = File.read(gradle_kts_path)
|
128
|
+
puts "读取 #{File.basename(gradle_kts_path)} 文件"
|
129
|
+
signing_configs_block = extract_signing_configs_kts(content)
|
130
|
+
# puts "==== signingConfigs block ===="
|
131
|
+
# puts signing_configs_block
|
132
|
+
# puts "==============================" if signing_configs_block
|
133
|
+
return nil unless signing_configs_block
|
134
|
+
|
135
|
+
config_type = debug ? 'debug' : 'release'
|
136
|
+
config_block = extract_config_block_kts(signing_configs_block, config_type)
|
137
|
+
# puts "==== config_block ===="
|
138
|
+
# puts config_block
|
139
|
+
# puts "=====================" if config_block
|
140
|
+
return nil unless config_block
|
141
|
+
|
142
|
+
config_block = remove_kts_comments(config_block)
|
143
|
+
ext_values = get_ext_values(project_path)
|
144
|
+
store_file, store_password, key_alias, key_password = extract_keystore_fields_kts(config_block, ext_values)
|
145
|
+
store_file = fix_store_file_path(store_file, project_path)
|
146
|
+
keystore_config = {
|
147
|
+
store_file: store_file,
|
148
|
+
store_password: store_password,
|
149
|
+
key_alias: key_alias,
|
150
|
+
key_password: key_password
|
151
|
+
}
|
152
|
+
if keystore_config.values.any?(&:nil?)
|
153
|
+
puts "警告: 部分 keystore 配置为 nil: #{keystore_config}"
|
154
|
+
end
|
155
|
+
keystore_config
|
156
|
+
end
|
95
157
|
|
158
|
+
# 处理 Groovy DSL (build.gradle)
|
159
|
+
def get_keystore_config_groovy(gradle_path, project_path, debug)
|
96
160
|
content = File.read(gradle_path)
|
161
|
+
puts "读取 #{File.basename(gradle_path)} 文件"
|
162
|
+
signing_configs_block = extract_signing_configs_groovy(content)
|
163
|
+
# puts "==== signingConfigs block ===="
|
164
|
+
# puts signing_configs_block
|
165
|
+
# puts "==============================" if signing_configs_block
|
166
|
+
return nil unless signing_configs_block
|
97
167
|
|
98
|
-
|
99
|
-
|
168
|
+
config_type = debug ? 'debug' : 'release'
|
169
|
+
config_block = extract_config_block_groovy(signing_configs_block, config_type)
|
170
|
+
# puts "==== config_block ===="
|
171
|
+
# puts config_block
|
172
|
+
# puts "=====================" if config_block
|
173
|
+
return nil unless config_block
|
174
|
+
|
175
|
+
config_block = remove_groovy_comments(config_block)
|
176
|
+
ext_values = get_ext_values(project_path)
|
177
|
+
store_file, store_password, key_alias, key_password = extract_keystore_fields_groovy(config_block, ext_values)
|
178
|
+
store_file = fix_store_file_path(store_file, project_path)
|
179
|
+
keystore_config = {
|
180
|
+
store_file: store_file,
|
181
|
+
store_password: store_password,
|
182
|
+
key_alias: key_alias,
|
183
|
+
key_password: key_password
|
184
|
+
}
|
185
|
+
if keystore_config.values.any?(&:nil?)
|
186
|
+
puts "警告: 部分 keystore 配置为 nil: #{keystore_config}"
|
187
|
+
end
|
188
|
+
keystore_config
|
189
|
+
end
|
100
190
|
|
101
|
-
|
102
|
-
|
103
|
-
|
191
|
+
# --- 工具方法 ---
|
192
|
+
def extract_signing_configs_kts(content)
|
193
|
+
# 提取 signingConfigs { ... },支持多层嵌套
|
194
|
+
match = content.match(/signingConfigs\s*\{([\s\S]*?)^\}/m)
|
195
|
+
match ? match[1] : nil
|
196
|
+
end
|
104
197
|
|
105
|
-
|
106
|
-
|
107
|
-
|
198
|
+
def extract_signing_configs_groovy(content)
|
199
|
+
# 提取 signingConfigs { ... },支持多层嵌套
|
200
|
+
match = content.match(/signingConfigs\s*\{([\s\S]*?)^\}/m)
|
201
|
+
match ? match[1] : nil
|
202
|
+
end
|
108
203
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
204
|
+
def extract_config_block_kts(signing_configs_block, config_type)
|
205
|
+
# 支持 create("xxx") { ... }
|
206
|
+
all_blocks = signing_configs_block.scan(/create\(["']?([A-Za-z0-9_]+)["']?\)\s*\{([\s\S]*?)^\s*\}/m)
|
207
|
+
# 优先 release/debug/Android_Sign/自定义名
|
208
|
+
priority_names = [config_type, "Android_Sign", "release", "debug"]
|
209
|
+
config_block = nil
|
210
|
+
priority_names.each do |name|
|
211
|
+
block = all_blocks.find { |n, b| n == name && b.include?("storeFile") }
|
212
|
+
if block
|
213
|
+
config_block = block[1]
|
214
|
+
break
|
215
|
+
end
|
216
|
+
end
|
217
|
+
# 没找到就取第一个有 storeFile 的块
|
218
|
+
if config_block.nil?
|
219
|
+
all_blocks.each do |name, block|
|
220
|
+
if block.include?("storeFile")
|
221
|
+
config_block = block
|
116
222
|
break
|
117
223
|
end
|
118
224
|
end
|
119
225
|
end
|
226
|
+
config_block
|
227
|
+
end
|
120
228
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# 检查 buildTypes 中使用的签名配置
|
133
|
-
config_type = debug ? 'debug' : 'release'
|
134
|
-
build_type_match = content.match(/buildTypes\s*\{.*?#{config_type}\s*\{(.*?)}/m)
|
135
|
-
if build_type_match && build_type_match[1] =~ /signingConfig\s+signingConfigs\.(\w+)/
|
136
|
-
config_name = $1
|
229
|
+
def extract_config_block_groovy(signing_configs_block, config_type)
|
230
|
+
# 支持 xxx { ... }
|
231
|
+
all_blocks = signing_configs_block.scan(/([A-Za-z0-9_]+)\s*\{([\s\S]*?)^\s*\}/m)
|
232
|
+
priority_names = [config_type, "Android_Sign", "release", "debug"]
|
233
|
+
config_block = nil
|
234
|
+
priority_names.each do |name|
|
235
|
+
block = all_blocks.find { |n, b| n == name && b.include?("storeFile") }
|
236
|
+
if block
|
237
|
+
config_block = block[1]
|
238
|
+
break
|
239
|
+
end
|
137
240
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
# 从配置开始位置查找匹配的闭合大括号
|
144
|
-
open_braces = 0
|
145
|
-
config_end = nil
|
146
|
-
|
147
|
-
signing_configs_block[config_start..-1].each_char.with_index do |char, i|
|
148
|
-
if char == '{'
|
149
|
-
open_braces += 1
|
150
|
-
elsif char == '}'
|
151
|
-
open_braces -= 1
|
152
|
-
if open_braces == 0
|
153
|
-
config_end = config_start + i
|
241
|
+
if config_block.nil?
|
242
|
+
all_blocks.each do |name, block|
|
243
|
+
if block.include?("storeFile")
|
244
|
+
config_block = block
|
154
245
|
break
|
155
246
|
end
|
156
247
|
end
|
157
248
|
end
|
249
|
+
config_block
|
250
|
+
end
|
158
251
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
puts "解析 signing config:"
|
165
|
-
puts "=" * 50
|
166
|
-
puts config_block
|
167
|
-
puts "=" * 50
|
168
|
-
|
169
|
-
# 从配置块中提取各项参数
|
170
|
-
store_file_match = config_block.match(/storeFile\s+file\(["']?\${([^}]+)}["']?\)/m)
|
171
|
-
store_password_match = config_block.match(/storePassword\s+["']?\${([^}]+)}["']?/m)
|
172
|
-
key_alias_match = config_block.match(/keyAlias\s+["']?\${([^}]+)}["']?/m)
|
173
|
-
key_password_match = config_block.match(/keyPassword\s+["']?\${([^}]+)}["']?/m)
|
174
|
-
|
175
|
-
# 如果使用了外部变量,尝试从 ext_signing.gradle 或其他配置文件中获取实际值
|
176
|
-
if store_file_match || store_password_match || key_alias_match || key_password_match
|
177
|
-
ext_values = get_ext_values(project_path)
|
178
|
-
puts "尝试从 ext values 中获取"
|
179
|
-
|
180
|
-
# 获取 store_file 并处理 $rootDir 路径
|
181
|
-
store_file = store_file_match ? ext_values[store_file_match[1]] : nil
|
182
|
-
if store_file && store_file.include?('$rootDir')
|
183
|
-
# 替换 $rootDir 为项目根目录的绝对路径
|
184
|
-
# 查找项目根目录(包含settings.gradle的目录)
|
185
|
-
root_dir = project_path
|
186
|
-
while root_dir && !File.exist?(File.join(root_dir, "settings.gradle"))
|
187
|
-
parent_dir = File.dirname(root_dir)
|
188
|
-
# 防止无限循环
|
189
|
-
break if parent_dir == root_dir
|
190
|
-
root_dir = parent_dir
|
191
|
-
end
|
252
|
+
def remove_kts_comments(block)
|
253
|
+
# 去除 // 注释
|
254
|
+
block.lines.reject { |line| line.strip.start_with?("//") }.join
|
255
|
+
end
|
192
256
|
|
193
|
-
|
194
|
-
|
195
|
-
|
257
|
+
def remove_groovy_comments(block)
|
258
|
+
# 去除 // 和 /* ... */ 注释
|
259
|
+
block = block.gsub(/\/\*[\s\S]*?\*\//, "")
|
260
|
+
block.lines.reject { |line| line.strip.start_with?("//") }.join
|
261
|
+
end
|
196
262
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
key_password: key_password_match ? ext_values[key_password_match[1]] : nil
|
202
|
-
}
|
263
|
+
# 通用字段递归解析
|
264
|
+
def extract_keystore_fields_common(fields, ext_values)
|
265
|
+
fields.map { |val| extract_var_or_value(val, ext_values) }
|
266
|
+
end
|
203
267
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
268
|
+
def extract_keystore_fields_groovy(config_block, ext_values)
|
269
|
+
# 只处理 groovy 语法
|
270
|
+
store_file = config_block[/storeFile\s+file\(["']?([^\)"']+)["']?\)/, 1]
|
271
|
+
store_password = config_block[/storePassword\s+["']?([^\)"']+)["']?/, 1]
|
272
|
+
key_alias = config_block[/keyAlias\s+["']?([^\)"']+)["']?/, 1]
|
273
|
+
key_password = config_block[/keyPassword\s+["']?([^\)"']+)["']?/, 1]
|
274
|
+
extract_keystore_fields_common([store_file, store_password, key_alias, key_password], ext_values)
|
275
|
+
end
|
208
276
|
|
209
|
-
|
277
|
+
def extract_keystore_fields_kts(config_block, ext_values)
|
278
|
+
# 只处理 kts 语法
|
279
|
+
store_file = config_block[/storeFile\s*=\s*file\(["']?([^\)"']+)["']?\)/, 1] ||
|
280
|
+
config_block[/storeFile\s*=\s*rootProject\.file\(["']?([^\)"']+)["']?\)/, 1]
|
281
|
+
store_password = config_block[/storePassword\s*=\s*["']?([^\)"']+)["']?/, 1]
|
282
|
+
key_alias = config_block[/keyAlias\s*=\s*["']?([^\)"']+)["']?/, 1]
|
283
|
+
key_password = config_block[/keyPassword\s*=\s*["']?([^\)"']+)["']?/, 1]
|
284
|
+
extract_keystore_fields_common([store_file, store_password, key_alias, key_password], ext_values)
|
285
|
+
end
|
286
|
+
|
287
|
+
def extract_var_or_value(val, ext_values, depth=0)
|
288
|
+
return nil if val.nil? || val.empty? || depth > 5
|
289
|
+
# 匹配 ${KEY}、$KEY、"${KEY}"、'${KEY}'
|
290
|
+
if val =~ /^\$\{?([A-Za-z0-9_]+)\}?$/
|
291
|
+
key = $1
|
292
|
+
v = ext_values[key]
|
293
|
+
v ? extract_var_or_value(v, ext_values, depth+1) : nil
|
294
|
+
elsif val =~ /^"?\$\{([A-Za-z0-9_]+)\}"?$/
|
295
|
+
key = $1
|
296
|
+
v = ext_values[key]
|
297
|
+
v ? extract_var_or_value(v, ext_values, depth+1) : nil
|
210
298
|
else
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
key_alias = config_block.match(/keyAlias\s+['"]([^'"]+)['"]/m)&.[](1)
|
215
|
-
key_password = config_block.match(/keyPassword\s+['"]([^'"]+)['"]/m)&.[](1)
|
216
|
-
|
217
|
-
keystore_config = {
|
218
|
-
store_file: store_file,
|
219
|
-
store_password: store_password,
|
220
|
-
key_alias: key_alias,
|
221
|
-
key_password: key_password
|
222
|
-
}
|
223
|
-
|
224
|
-
# 确保所有值都不为 nil
|
225
|
-
if keystore_config.values.any?(&:nil?)
|
226
|
-
puts "警告: 部分 keystore 配置为 nil: #{keystore_config}"
|
227
|
-
end
|
299
|
+
val
|
300
|
+
end
|
301
|
+
end
|
228
302
|
|
229
|
-
|
303
|
+
def resolve_var(val, ext_values, depth=0)
|
304
|
+
return val if val.nil? || depth > 5
|
305
|
+
if ext_values[val]
|
306
|
+
resolve_var(ext_values[val], ext_values, depth+1)
|
307
|
+
else
|
308
|
+
val
|
230
309
|
end
|
231
310
|
end
|
232
311
|
|
312
|
+
def fix_store_file_path(store_file, project_path)
|
313
|
+
return nil if store_file.nil? || store_file.empty?
|
314
|
+
# 兼容 $rootDir、${rootDir}、project.rootDir、rootProject.file
|
315
|
+
store_file = store_file.gsub(/^\$?\{?rootDir\}?\/?/, project_path + "/")
|
316
|
+
store_file = store_file.gsub(/^project\.rootDir\/?/, project_path + "/")
|
317
|
+
store_file = store_file.gsub(/^rootProject\.file\(['"](.+?)['"]\)/, project_path + '/\\1')
|
318
|
+
store_file = File.expand_path(store_file, project_path) unless File.exist?(store_file)
|
319
|
+
store_file
|
320
|
+
end
|
321
|
+
|
233
322
|
# 新增方法:从 ext 配置文件中获取变量值
|
234
323
|
def get_ext_values(project_path)
|
235
324
|
ext_values = {}
|
236
325
|
|
237
|
-
# 查找可能的 ext 配置文件
|
238
326
|
ext_files = [
|
239
327
|
File.join(project_path, "buildScripts/cfg/ext_signing.gradle"),
|
328
|
+
File.join(project_path, "buildScripts/cfg/ext_signing.gradle.kts"),
|
240
329
|
File.join(project_path, "gradle.properties"),
|
241
330
|
File.join(project_path, "local.properties")
|
242
331
|
]
|
@@ -246,13 +335,18 @@ module Pindo
|
|
246
335
|
|
247
336
|
content = File.read(file_path)
|
248
337
|
|
249
|
-
#
|
338
|
+
# 支持 ext.KEY = "VALUE"
|
250
339
|
content.scan(/ext\.(\w+)\s*=\s*["']([^"']+)["']/m).each do |key, value|
|
251
340
|
ext_values[key] = value
|
252
341
|
end
|
253
342
|
|
254
|
-
#
|
255
|
-
content.scan(
|
343
|
+
# 支持 ext["KEY"] = "VALUE"
|
344
|
+
content.scan(/ext\[\s*["'](\w+)["']\s*\]\s*=\s*["']([^"']+)["']/m).each do |key, value|
|
345
|
+
ext_values[key] = value
|
346
|
+
end
|
347
|
+
|
348
|
+
# 支持 KEY = "VALUE"
|
349
|
+
content.scan(/^(\w+)\s*=\s*["']([^"']+)["']/m).each do |key, value|
|
256
350
|
ext_values[key] = value
|
257
351
|
end
|
258
352
|
end
|
@@ -265,9 +359,14 @@ module Pindo
|
|
265
359
|
unity_library_path = File.join(project_path, "unityLibrary")
|
266
360
|
return false unless File.directory?(unity_library_path)
|
267
361
|
|
268
|
-
# 检查 unityLibrary 的 build.gradle 是否存在
|
362
|
+
# 检查 unityLibrary 的 build.gradle 或 build.gradle.kts 是否存在
|
269
363
|
unity_gradle_path = File.join(unity_library_path, "build.gradle")
|
270
|
-
|
364
|
+
unity_gradle_kts_path = File.join(unity_library_path, "build.gradle.kts")
|
365
|
+
if File.exist?(unity_gradle_kts_path)
|
366
|
+
unity_gradle_path = unity_gradle_kts_path
|
367
|
+
elsif !File.exist?(unity_gradle_path)
|
368
|
+
return false
|
369
|
+
end
|
271
370
|
|
272
371
|
# 检查 build.gradle 中是否包含 Unity 特有的配置
|
273
372
|
content = File.read(unity_gradle_path)
|
@@ -153,13 +153,13 @@ module Pindo
|
|
153
153
|
keystore_config = get_keystore_config(project_path, debug)
|
154
154
|
|
155
155
|
ks = keystore_config[:store_file]
|
156
|
-
puts "读取 keystore path = #{ks}"
|
156
|
+
# puts "读取 keystore path = #{ks}"
|
157
157
|
ks_pass = keystore_config[:store_password]
|
158
|
-
puts "读取 keystore pass = #{ks_pass}"
|
158
|
+
# puts "读取 keystore pass = #{ks_pass}"
|
159
159
|
key_alias = keystore_config[:key_alias]
|
160
|
-
puts "读取 key alias = #{key_alias}"
|
160
|
+
# puts "读取 key alias = #{key_alias}"
|
161
161
|
key_pass = keystore_config[:key_password]
|
162
|
-
puts "读取 key pass = #{key_pass}"
|
162
|
+
# puts "读取 key pass = #{key_pass}"
|
163
163
|
end
|
164
164
|
|
165
165
|
private
|
@@ -28,8 +28,17 @@ module Pindo
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def update_build_gradle(project_path)
|
31
|
-
# 更新build.gradle
|
31
|
+
# 更新build.gradle 或 build.gradle.kts
|
32
32
|
build_gradle_path = File.join(project_path, "build.gradle")
|
33
|
+
build_gradle_kts_path = File.join(project_path, "build.gradle.kts")
|
34
|
+
|
35
|
+
# 优先使用 build.gradle.kts,如果不存在则使用 build.gradle
|
36
|
+
if File.exist?(build_gradle_kts_path)
|
37
|
+
build_gradle_path = build_gradle_kts_path
|
38
|
+
elsif !File.exist?(build_gradle_path)
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
33
42
|
content = File.read(build_gradle_path)
|
34
43
|
content.gsub!("classpath 'com.android.tools.build:gradle:4.0.1'",
|
35
44
|
"classpath 'com.android.tools.build:gradle:4.2.2'")
|
@@ -124,7 +124,7 @@ module Pindo
|
|
124
124
|
end
|
125
125
|
|
126
126
|
|
127
|
-
def check_is_need_add_tag?(project_path)
|
127
|
+
def check_is_need_add_tag?(project_path, auto_mode: false)
|
128
128
|
tag_action_parms = nil
|
129
129
|
is_need_add_tag = false
|
130
130
|
|
@@ -133,36 +133,43 @@ module Pindo
|
|
133
133
|
latest_tag = get_latest_version_tag(project_dir: current_git_root_path)
|
134
134
|
|
135
135
|
unless is_tag_at_head?(git_root_dir: current_git_root_path, tag_name: latest_tag)
|
136
|
-
|
137
|
-
|
138
|
-
"
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
136
|
+
if auto_mode || !$stdin.tty?
|
137
|
+
# 在自动化模式或没有交互式终端时,默认选择新增版本号打新Tag
|
138
|
+
puts "检测到当前代码没有打Tag,在自动模式下将自动新增版本号并打新Tag"
|
139
|
+
tag_action_parms = []
|
140
|
+
is_need_add_tag = false
|
141
|
+
else
|
142
|
+
cli = HighLine.new
|
143
|
+
menu_options = {
|
144
|
+
"新增版本号,打新Tag" => -> {
|
145
|
+
tag_action_parms = []
|
146
|
+
:new_tag
|
147
|
+
},
|
148
|
+
"将上次的Tag删除重新打Tag" => -> {
|
149
|
+
tag_action_parms = []
|
150
|
+
tag_action_parms << "--retag"
|
151
|
+
:recreate_tag
|
152
|
+
},
|
153
|
+
"不需要Tag继续编译且上传,手动修改上传备注" => -> {
|
154
|
+
puts ""
|
155
|
+
:continue_without_tag
|
156
|
+
},
|
157
|
+
"终止退出编译" => -> {
|
158
|
+
raise Informative, "终止退出编译!"
|
159
|
+
:exit
|
160
|
+
}
|
154
161
|
}
|
155
|
-
}
|
156
162
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
163
|
+
result = cli.choose do |menu|
|
164
|
+
menu.header = "当前代码并没有打Tag,上传的Changelog需要Tag"
|
165
|
+
menu.prompt = "请选中打Tag的方式, 请输入选项(1/2/3...):"
|
166
|
+
menu_options.each do |option, action|
|
167
|
+
menu.choice(option) { action.call }
|
168
|
+
end
|
162
169
|
end
|
163
|
-
end
|
164
170
|
|
165
|
-
|
171
|
+
is_need_add_tag = !tag_action_parms.nil?
|
172
|
+
end
|
166
173
|
end
|
167
174
|
end
|
168
175
|
|
data/lib/pindo/version.rb
CHANGED
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.1.
|
4
|
+
version: 5.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- wade
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: claide
|
@@ -453,7 +453,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
453
453
|
- !ruby/object:Gem::Version
|
454
454
|
version: '0'
|
455
455
|
requirements: []
|
456
|
-
rubygems_version: 3.6.
|
456
|
+
rubygems_version: 3.6.9
|
457
457
|
specification_version: 3
|
458
458
|
summary: easy work
|
459
459
|
test_files: []
|