pindo 5.10.6 → 5.10.8
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 +12 -1
- data/lib/pindo/base/pindocontext.rb +3 -0
- data/lib/pindo/command/android/autobuild.rb +62 -9
- data/lib/pindo/command/android/build.rb +6 -6
- data/lib/pindo/command/android/debug.rb +9 -9
- data/lib/pindo/command/deploy/build.rb +2 -4
- data/lib/pindo/command/deploy/cert.rb +4 -5
- data/lib/pindo/command/deploy/configproj.rb +3 -3
- data/lib/pindo/command/deploy/confusecode.rb +1 -1
- data/lib/pindo/command/deploy/confuseproj.rb +1 -1
- data/lib/pindo/command/deploy/pem.rb +3 -4
- data/lib/pindo/command/dev/autobuild.rb +1 -1
- data/lib/pindo/command/dev/build.rb +1 -1
- data/lib/pindo/command/dev/feishu.rb +1 -1
- data/lib/pindo/command/gplay/pullconfig.rb +48 -0
- data/lib/pindo/command/gplay.rb +6 -5
- data/lib/pindo/command/ios/adhoc.rb +6 -5
- data/lib/pindo/command/ios/autobuild.rb +24 -24
- data/lib/pindo/command/ios/build.rb +7 -6
- data/lib/pindo/command/ios/debug.rb +1 -0
- data/lib/pindo/command/ipa/import.rb +2 -3
- data/lib/pindo/command/ipa/output.rb +2 -3
- data/lib/pindo/command/jps/upload.rb +6 -5
- data/lib/pindo/command/unity/apk.rb +19 -2
- data/lib/pindo/command/unity/autobuild.rb +58 -63
- data/lib/pindo/command/unity/initpack.rb +1 -1
- data/lib/pindo/command/unity/ipa.rb +17 -14
- data/lib/pindo/command/unity/pack.rb +1 -1
- data/lib/pindo/command/unity/upload.rb +1 -1
- data/lib/pindo/command/unity/web.rb +2 -2
- data/lib/pindo/command/utils/icon.rb +1 -1
- data/lib/pindo/command/utils/renewcert.rb +1 -2
- data/lib/pindo/command/utils/renewproj.rb +9 -10
- data/lib/pindo/command/web/autobuild.rb +2 -2
- data/lib/pindo/command/web/run.rb +1 -1
- data/lib/pindo/command.rb +2 -1
- data/lib/pindo/module/android/android_build_config_helper.rb +267 -35
- data/lib/pindo/module/android/android_build_helper.rb +300 -0
- data/lib/pindo/module/android/android_project_helper.rb +279 -0
- data/lib/pindo/module/android/gp_compliance_helper.rb +33 -87
- data/lib/pindo/module/android/gradle_helper.rb +524 -255
- data/lib/pindo/module/android/java_env_helper.rb +633 -0
- data/lib/pindo/module/android/keystore_helper.rb +1118 -0
- data/lib/pindo/module/appselect.rb +109 -0
- data/lib/pindo/module/appstore/appstore_in_app_purchase.rb +1 -1
- data/lib/pindo/module/build/{buildhelper.rb → build_helper.rb} +1 -2
- data/lib/pindo/module/build/{commonconfuseproj.rb → confuse_xcodeproj.rb} +2 -2
- data/lib/pindo/module/cert/cert_helper.rb +245 -0
- data/lib/pindo/module/cert/keychain_helper.rb +152 -0
- data/lib/pindo/module/cert/pem_helper.rb +67 -0
- data/lib/pindo/module/cert/xcodecerthelper.rb +2 -2
- data/lib/pindo/module/{build/unityhelper.rb → unity/unity_helper.rb} +0 -17
- data/lib/pindo/module/xcode/{xcodereshandler.rb → res/xcode_res_handler.rb} +1 -1
- data/lib/pindo/module/xcode/{xcodebuildconfig.rb → xcode_build_config.rb} +7 -6
- data/lib/pindo/module/xcode/{xcodebuildhelper.rb → xcode_build_helper.rb} +4 -3
- data/lib/pindo/module/xcode/{xcodehelper.rb → xcode_project_helper.rb} +4 -2
- data/lib/pindo/module/xcode/{xcodereshelper.rb → xcode_res_helper.rb} +12 -9
- data/lib/pindo/version.rb +185 -7
- data/lib/pindo.rb +14 -9
- metadata +24 -23
- data/lib/pindo/module/android/apk_helper.rb +0 -138
- data/lib/pindo/module/android/base_helper.rb +0 -964
- data/lib/pindo/module/android/build_helper.rb +0 -128
- data/lib/pindo/module/android/so_helper.rb +0 -18
- data/lib/pindo/module/cert/certhelper.rb +0 -246
- data/lib/pindo/module/cert/keychainhelper.rb +0 -150
- data/lib/pindo/module/cert/pemhelper.rb +0 -65
- /data/lib/pindo/module/android/{androidreshelper.rb → android_res_helper.rb} +0 -0
- /data/lib/pindo/module/appstore/{iap_tier.json → appstore_iap_tier.json} +0 -0
- /data/lib/pindo/module/build/{swarkhelper.rb → swark_helper.rb} +0 -0
- /data/lib/pindo/module/build/{versionhelper.rb → version_helper.rb} +0 -0
- /data/lib/pindo/module/cert/{provisioninghelper.rb → provisioning_helper.rb} +0 -0
- /data/lib/pindo/module/unity/{nugethelper.rb → nuget_helper.rb} +0 -0
- /data/lib/pindo/module/xcode/{xcoderesconstant.rb → res/xcode_res_constant.rb} +0 -0
|
@@ -1,296 +1,565 @@
|
|
|
1
|
-
require_relative '
|
|
1
|
+
require_relative 'android_project_helper'
|
|
2
2
|
require 'net/http'
|
|
3
3
|
require 'uri'
|
|
4
4
|
require 'zip'
|
|
5
|
+
require_relative '../../base/funlog'
|
|
5
6
|
|
|
6
7
|
module Pindo
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
class GradleHelper
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
# Gradle缓存目录
|
|
12
|
+
GRADLE_CACHE_DIR = File.expand_path("~/.pindo/android_tools/gradle-cache")
|
|
13
|
+
|
|
14
|
+
# Gradle 插件版本映射表(AGP版本映射)
|
|
15
|
+
# 仅升级旧版本到 4.2.2,不降级新版本
|
|
16
|
+
GRADLE_PLUGIN_VERSION_MAP = {
|
|
17
|
+
# 旧版本升级到 4.2.2
|
|
18
|
+
'3.4.0' => '4.2.2',
|
|
19
|
+
'3.4.1' => '4.2.2',
|
|
20
|
+
'3.5.0' => '4.2.2',
|
|
21
|
+
'3.5.1' => '4.2.2',
|
|
22
|
+
'3.6.0' => '4.2.2',
|
|
23
|
+
'3.6.1' => '4.2.2',
|
|
24
|
+
'4.0.0' => '4.2.2',
|
|
25
|
+
'4.0.1' => '4.2.2',
|
|
26
|
+
'4.1.0' => '4.2.2',
|
|
27
|
+
'4.2.0' => '4.2.2',
|
|
28
|
+
'4.2.1' => '4.2.2',
|
|
29
|
+
'4.2.2' => '4.2.2' # 保持当前版本
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# =================== 公共方法 ===================
|
|
33
|
+
|
|
34
|
+
# 获取项目的 Gradle 配置路径(统一管理三种工程结构的路径)
|
|
35
|
+
# @param project_path [String] 项目路径
|
|
36
|
+
# @return [Hash] 包含各种路径信息和项目类型
|
|
37
|
+
def get_gradle_paths(project_path)
|
|
38
|
+
paths = {}
|
|
39
|
+
|
|
40
|
+
if Pindo::AndroidProjectHelper.unity_android_project?(project_path)
|
|
41
|
+
# Unity 独立工程
|
|
42
|
+
paths[:type] = :unity_standalone
|
|
43
|
+
paths[:gradle_dir] = project_path
|
|
44
|
+
paths[:wrapper_properties] = File.join(project_path, "gradle/wrapper/gradle-wrapper.properties")
|
|
45
|
+
paths[:build_gradle] = File.join(project_path, "build.gradle")
|
|
46
|
+
paths[:build_gradle_kts] = File.join(project_path, "build.gradle.kts")
|
|
47
|
+
|
|
48
|
+
elsif Pindo::AndroidProjectHelper.unity_as_lib_android_project?(project_path)
|
|
49
|
+
# Unity 作为 lib 的原生工程 - 需要处理两套配置
|
|
50
|
+
paths[:type] = :unity_as_lib
|
|
51
|
+
|
|
52
|
+
# Unity 模块的路径
|
|
53
|
+
paths[:unity_gradle_dir] = File.join(project_path, "Unity")
|
|
54
|
+
paths[:unity_wrapper_properties] = File.join(project_path, "Unity/gradle/wrapper/gradle-wrapper.properties")
|
|
55
|
+
paths[:unity_build_gradle] = File.join(project_path, "Unity/build.gradle")
|
|
56
|
+
paths[:unity_build_gradle_kts] = File.join(project_path, "Unity/build.gradle.kts")
|
|
57
|
+
|
|
58
|
+
# 主工程的路径
|
|
59
|
+
paths[:main_gradle_dir] = project_path
|
|
60
|
+
paths[:main_wrapper_properties] = File.join(project_path, "gradle/wrapper/gradle-wrapper.properties")
|
|
61
|
+
paths[:main_build_gradle] = File.join(project_path, "build.gradle")
|
|
62
|
+
paths[:main_build_gradle_kts] = File.join(project_path, "build.gradle.kts")
|
|
63
|
+
|
|
64
|
+
# 保留原有路径以兼容其他代码
|
|
65
|
+
paths[:gradle_dir] = paths[:unity_gradle_dir]
|
|
66
|
+
paths[:wrapper_properties] = paths[:unity_wrapper_properties]
|
|
67
|
+
paths[:build_gradle] = paths[:unity_build_gradle]
|
|
68
|
+
paths[:build_gradle_kts] = paths[:unity_build_gradle_kts]
|
|
69
|
+
|
|
23
70
|
else
|
|
24
|
-
|
|
25
|
-
|
|
71
|
+
# Android 原生工程
|
|
72
|
+
paths[:type] = :native_android
|
|
73
|
+
paths[:gradle_dir] = project_path
|
|
74
|
+
paths[:wrapper_properties] = File.join(project_path, "gradle/wrapper/gradle-wrapper.properties")
|
|
75
|
+
paths[:build_gradle] = File.join(project_path, "build.gradle")
|
|
76
|
+
paths[:build_gradle_kts] = File.join(project_path, "build.gradle.kts")
|
|
26
77
|
end
|
|
27
|
-
else
|
|
28
|
-
puts "\e[31m✗ 未找到gradle-wrapper.properties文件\e[0m"
|
|
29
|
-
return false
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def update_build_gradle(project_path)
|
|
35
|
-
# 更新build.gradle 或 build.gradle.kts
|
|
36
|
-
build_gradle_path = File.join(project_path, "build.gradle")
|
|
37
|
-
build_gradle_kts_path = File.join(project_path, "build.gradle.kts")
|
|
38
|
-
|
|
39
|
-
# 优先使用 build.gradle.kts,如果不存在则使用 build.gradle
|
|
40
|
-
if File.exist?(build_gradle_kts_path)
|
|
41
|
-
build_gradle_path = build_gradle_kts_path
|
|
42
|
-
elsif !File.exist?(build_gradle_path)
|
|
43
|
-
return
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
content = File.read(build_gradle_path)
|
|
47
|
-
content.gsub!("classpath 'com.android.tools.build:gradle:4.0.1'",
|
|
48
|
-
"classpath 'com.android.tools.build:gradle:4.2.2'")
|
|
49
|
-
File.write(build_gradle_path, content)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def update_gradle_version(project_path)
|
|
53
|
-
# 直接调用setup_gradle_wrapper_from_properties,功能相同
|
|
54
|
-
setup_gradle_wrapper_from_properties(project_path)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# 基于gradle-wrapper.properties自动配置gradle工具
|
|
58
|
-
def setup_gradle_wrapper_from_properties(project_path)
|
|
59
|
-
wrapper_properties_path = File.join(project_path, "gradle/wrapper/gradle-wrapper.properties")
|
|
60
|
-
|
|
61
|
-
unless File.exist?(wrapper_properties_path)
|
|
62
|
-
puts "\e[33m⚠ 未找到gradle-wrapper.properties文件: #{wrapper_properties_path}\e[0m"
|
|
63
|
-
return false
|
|
64
|
-
end
|
|
65
78
|
|
|
66
|
-
|
|
67
|
-
gradle_version = parse_gradle_version(wrapper_properties_path)
|
|
68
|
-
if gradle_version.nil?
|
|
69
|
-
puts "\e[31m✗ 无法解析gradle版本\e[0m"
|
|
70
|
-
return false
|
|
79
|
+
paths
|
|
71
80
|
end
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
# =================== 核心功能 ===================
|
|
83
|
+
|
|
84
|
+
def check_gradle_with_project(project_path, configure_main: false)
|
|
85
|
+
Funlog.fancyinfo_start("检查Gradle Wrapper配置")
|
|
86
|
+
|
|
87
|
+
# 使用统一的路径获取方法
|
|
88
|
+
paths = get_gradle_paths(project_path)
|
|
89
|
+
|
|
90
|
+
if paths[:type] == :unity_as_lib
|
|
91
|
+
if configure_main
|
|
92
|
+
# 配置主工程的 Gradle(在 SO 编译完成后调用)
|
|
93
|
+
Funlog.info("配置主工程的Gradle Wrapper用于编译APK...")
|
|
94
|
+
|
|
95
|
+
unless File.exist?(paths[:main_wrapper_properties])
|
|
96
|
+
Funlog.fancyinfo_error("未找到主工程的gradle-wrapper.properties: #{paths[:main_wrapper_properties]}")
|
|
97
|
+
return false
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
main_gradle_version = extract_gradle_version(paths[:main_wrapper_properties])
|
|
101
|
+
Funlog.info("主工程Gradle版本: #{main_gradle_version}")
|
|
102
|
+
|
|
103
|
+
# 确保主工程的 Gradle 缓存存在
|
|
104
|
+
unless ensure_gradle_available(main_gradle_version)
|
|
105
|
+
Funlog.fancyinfo_error("无法获取主工程的Gradle #{main_gradle_version}")
|
|
106
|
+
return false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# 配置主工程的 Gradle Wrapper
|
|
110
|
+
unless setup_gradle_wrapper(paths[:main_gradle_dir], paths[:main_wrapper_properties])
|
|
111
|
+
Funlog.fancyinfo_error("主工程Gradle Wrapper配置失败")
|
|
112
|
+
return false
|
|
113
|
+
end
|
|
75
114
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
115
|
+
Funlog.fancyinfo_success("主工程Gradle配置完成,准备编译APK")
|
|
116
|
+
true
|
|
117
|
+
else
|
|
118
|
+
# 配置 Unity 模块的 Gradle(默认行为,在 SO 编译前调用)
|
|
119
|
+
Funlog.info("检测到 Unity as lib 工程,配置Unity模块的Gradle")
|
|
120
|
+
|
|
121
|
+
# 1. 配置 Unity 模块的 Gradle(7.5.1 + Java 11,用于编译SO库)
|
|
122
|
+
unless File.exist?(paths[:unity_wrapper_properties])
|
|
123
|
+
Funlog.fancyinfo_error("未找到Unity模块的gradle-wrapper.properties: #{paths[:unity_wrapper_properties]}")
|
|
124
|
+
return false
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
unity_gradle_version = extract_gradle_version(paths[:unity_wrapper_properties])
|
|
128
|
+
Funlog.info("配置Unity模块的Gradle Wrapper (版本: #{unity_gradle_version})...")
|
|
129
|
+
unless setup_gradle_wrapper(paths[:unity_gradle_dir], paths[:unity_wrapper_properties])
|
|
130
|
+
Funlog.fancyinfo_error("Unity模块Gradle Wrapper配置失败")
|
|
131
|
+
return false
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# 2. 检查主工程的 Gradle 配置文件是否存在
|
|
135
|
+
unless File.exist?(paths[:main_wrapper_properties])
|
|
136
|
+
Funlog.fancyinfo_error("未找到主工程的gradle-wrapper.properties: #{paths[:main_wrapper_properties]}")
|
|
137
|
+
return false
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
main_gradle_version = extract_gradle_version(paths[:main_wrapper_properties])
|
|
141
|
+
Funlog.info("主工程Gradle配置 (版本: #{main_gradle_version}),待SO编译完成后配置")
|
|
142
|
+
|
|
143
|
+
# 确保主工程的 Gradle 缓存存在
|
|
144
|
+
unless ensure_gradle_available(main_gradle_version)
|
|
145
|
+
Funlog.info("下载主工程所需的Gradle #{main_gradle_version}...")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
Funlog.info("Unity模块: Gradle #{unity_gradle_version} + Java 11 (编译SO库)")
|
|
149
|
+
Funlog.info("主工程: Gradle #{main_gradle_version} + Java 17 (编译APK)")
|
|
150
|
+
Funlog.fancyinfo_success("Unity模块Gradle配置完成,准备编译SO库")
|
|
151
|
+
true
|
|
152
|
+
end
|
|
153
|
+
else
|
|
154
|
+
# Unity standalone 或原生 Android 工程:只配置一个 Gradle
|
|
155
|
+
unless File.exist?(paths[:wrapper_properties])
|
|
156
|
+
Funlog.fancyinfo_error("未找到gradle-wrapper.properties文件: #{paths[:wrapper_properties]}")
|
|
157
|
+
return false
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if setup_gradle_wrapper(paths[:gradle_dir], paths[:wrapper_properties])
|
|
161
|
+
Funlog.fancyinfo_success("Gradle Wrapper配置成功")
|
|
162
|
+
true
|
|
163
|
+
else
|
|
164
|
+
Funlog.fancyinfo_error("Gradle Wrapper配置失败")
|
|
165
|
+
false
|
|
166
|
+
end
|
|
167
|
+
end
|
|
83
168
|
end
|
|
84
|
-
end
|
|
85
169
|
|
|
86
170
|
|
|
87
|
-
|
|
171
|
+
def update_build_gradle(project_path)
|
|
172
|
+
paths = get_gradle_paths(project_path)
|
|
173
|
+
|
|
174
|
+
if paths[:type] == :unity_as_lib
|
|
175
|
+
# Unity as lib 工程:只更新 Unity 模块的 build.gradle
|
|
176
|
+
# 主工程的 AGP 保持原版本(如 8.8.0),因为它使用独立的 Gradle 8.10.2
|
|
177
|
+
Funlog.info("检测到 Unity as lib 工程,仅更新Unity模块的AGP版本")
|
|
88
178
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
179
|
+
# 更新 Unity 模块的 build.gradle(根据映射表更新旧版本)
|
|
180
|
+
if paths[:unity_build_gradle] || paths[:unity_build_gradle_kts]
|
|
181
|
+
Funlog.info("更新Unity模块的build.gradle...")
|
|
182
|
+
update_single_build_gradle(paths[:unity_build_gradle], paths[:unity_build_gradle_kts])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
Funlog.info("Unity模块的AGP版本更新完成(主工程保持原版本)")
|
|
186
|
+
else
|
|
187
|
+
# Unity standalone 或原生 Android 工程:只更新一个 build.gradle
|
|
188
|
+
update_single_build_gradle(paths[:build_gradle], paths[:build_gradle_kts])
|
|
189
|
+
end
|
|
96
190
|
end
|
|
97
|
-
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
191
|
+
|
|
192
|
+
# 设置 Gradle Wrapper(简化后的核心函数)
|
|
193
|
+
def setup_gradle_wrapper(gradle_dir, wrapper_properties_path)
|
|
194
|
+
# 解析gradle版本
|
|
195
|
+
gradle_version = parse_gradle_version(wrapper_properties_path)
|
|
196
|
+
if gradle_version.nil?
|
|
197
|
+
Funlog.error("无法解析gradle版本")
|
|
198
|
+
return false
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# 下载并设置 Gradle
|
|
202
|
+
unless ensure_gradle_available(gradle_version)
|
|
203
|
+
Funlog.error("无法获取 Gradle #{gradle_version}")
|
|
204
|
+
return false
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# 生成 Wrapper
|
|
208
|
+
generate_gradle_wrapper(gradle_dir, gradle_version)
|
|
101
209
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
210
|
+
|
|
211
|
+
# 解析gradle版本
|
|
212
|
+
def parse_gradle_version(properties_path)
|
|
213
|
+
content = File.read(properties_path)
|
|
214
|
+
|
|
215
|
+
# 匹配distributionUrl中的gradle版本
|
|
216
|
+
if content =~ /distributionUrl=.*gradle-(\d+\.\d+(?:\.\d+)?(?:-.*)?)-bin\.zip/
|
|
217
|
+
return $1
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# 匹配gradleVersion属性
|
|
221
|
+
if content =~ /gradleVersion=(\d+\.\d+(?:\.\d+)?(?:-.*)?)/
|
|
222
|
+
return $1
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
nil
|
|
114
226
|
end
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# 下载并设置Gradle环境
|
|
123
|
-
def download_and_setup_gradle(gradle_version)
|
|
124
|
-
puts "下载并设置Gradle #{gradle_version}环境..."
|
|
125
|
-
|
|
126
|
-
# 确保缓存目录存在
|
|
127
|
-
FileUtils.mkdir_p(GRADLE_CACHE_DIR)
|
|
128
|
-
|
|
129
|
-
# 检查是否已解压
|
|
130
|
-
gradle_home = File.join(GRADLE_CACHE_DIR, "gradle-#{gradle_version}")
|
|
131
|
-
gradle_bin = File.join(gradle_home, "bin/gradle")
|
|
132
|
-
|
|
133
|
-
if File.exist?(gradle_bin)
|
|
134
|
-
puts "✓ 使用已解压的Gradle #{gradle_version}"
|
|
135
|
-
setup_gradle_environment(gradle_home)
|
|
136
|
-
return true
|
|
227
|
+
|
|
228
|
+
# 提取 gradle 版本(parse_gradle_version 的别名)
|
|
229
|
+
def extract_gradle_version(properties_path)
|
|
230
|
+
parse_gradle_version(properties_path)
|
|
137
231
|
end
|
|
138
|
-
|
|
139
|
-
#
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
232
|
+
|
|
233
|
+
# 使用指定版本设置 Gradle Wrapper
|
|
234
|
+
def setup_gradle_wrapper_with_version(gradle_dir, wrapper_properties_path, gradle_version)
|
|
235
|
+
if gradle_version.nil?
|
|
236
|
+
Funlog.error("Gradle版本不能为空")
|
|
237
|
+
return false
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# 下载并设置 Gradle
|
|
241
|
+
unless ensure_gradle_available(gradle_version)
|
|
242
|
+
Funlog.error("无法获取 Gradle #{gradle_version}")
|
|
243
|
+
return false
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# 生成 Wrapper
|
|
247
|
+
generate_gradle_wrapper(gradle_dir, gradle_version)
|
|
143
248
|
end
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
# 如果已存在ZIP文件,先检查完整性
|
|
157
|
-
if File.exist?(cache_file)
|
|
158
|
-
puts "✓ 发现缓存的Gradle分发包"
|
|
159
|
-
if verify_zip_integrity(cache_file)
|
|
160
|
-
puts "✓ 缓存文件完整性验证通过"
|
|
161
|
-
return extract_gradle_distribution(cache_file, extract_dir, gradle_version)
|
|
249
|
+
|
|
250
|
+
# =================== 私有辅助方法 ===================
|
|
251
|
+
|
|
252
|
+
private
|
|
253
|
+
|
|
254
|
+
# 更新单个 build.gradle 文件
|
|
255
|
+
def update_single_build_gradle(gradle_path, gradle_kts_path)
|
|
256
|
+
# 优先使用 .kts 文件
|
|
257
|
+
target_file = if File.exist?(gradle_kts_path)
|
|
258
|
+
gradle_kts_path
|
|
259
|
+
elsif File.exist?(gradle_path)
|
|
260
|
+
gradle_path
|
|
162
261
|
else
|
|
163
|
-
|
|
164
|
-
|
|
262
|
+
Funlog.info("未找到build.gradle文件: #{gradle_path} 或 #{gradle_kts_path}")
|
|
263
|
+
return
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
Funlog.info("检查AGP版本: #{File.basename(target_file)}")
|
|
267
|
+
content = File.read(target_file)
|
|
268
|
+
updated = false
|
|
269
|
+
found_version = nil
|
|
270
|
+
target_version = nil
|
|
271
|
+
|
|
272
|
+
GRADLE_PLUGIN_VERSION_MAP.each do |old_version, new_version|
|
|
273
|
+
next if old_version == new_version
|
|
274
|
+
|
|
275
|
+
# Groovy 格式
|
|
276
|
+
if content.gsub!("classpath 'com.android.tools.build:gradle:#{old_version}'",
|
|
277
|
+
"classpath 'com.android.tools.build:gradle:#{new_version}'")
|
|
278
|
+
updated = true
|
|
279
|
+
found_version = old_version
|
|
280
|
+
target_version = new_version
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Kotlin DSL 格式
|
|
284
|
+
if content.gsub!("classpath(\"com.android.tools.build:gradle:#{old_version}\")",
|
|
285
|
+
"classpath(\"com.android.tools.build:gradle:#{new_version}\")")
|
|
286
|
+
updated = true
|
|
287
|
+
found_version = old_version
|
|
288
|
+
target_version = new_version
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# 新格式(使用 id 和 version)
|
|
292
|
+
if content.gsub!("id 'com.android.application' version '#{old_version}'",
|
|
293
|
+
"id 'com.android.application' version '#{new_version}'")
|
|
294
|
+
updated = true
|
|
295
|
+
found_version = old_version
|
|
296
|
+
target_version = new_version
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
if content.gsub!("id 'com.android.library' version '#{old_version}'",
|
|
300
|
+
"id 'com.android.library' version '#{new_version}'")
|
|
301
|
+
updated = true
|
|
302
|
+
found_version = old_version
|
|
303
|
+
target_version = new_version
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
if updated
|
|
308
|
+
File.write(target_file, content)
|
|
309
|
+
Funlog.info("✓ AGP版本已更新: #{found_version} → #{target_version}")
|
|
310
|
+
else
|
|
311
|
+
Funlog.info("AGP版本无需更新或已是目标版本")
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# 确保 Gradle 可用(下载或使用缓存)
|
|
316
|
+
def ensure_gradle_available(gradle_version)
|
|
317
|
+
gradle_home = File.join(GRADLE_CACHE_DIR, "gradle-#{gradle_version}")
|
|
318
|
+
gradle_bin = File.join(gradle_home, "bin/gradle")
|
|
319
|
+
|
|
320
|
+
# 如果已存在,直接使用
|
|
321
|
+
if File.exist?(gradle_bin)
|
|
322
|
+
setup_gradle_environment(gradle_home)
|
|
323
|
+
return true
|
|
165
324
|
end
|
|
325
|
+
|
|
326
|
+
# 下载并解压
|
|
327
|
+
download_and_setup_gradle(gradle_version)
|
|
166
328
|
end
|
|
167
|
-
|
|
168
|
-
#
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
329
|
+
|
|
330
|
+
# 生成 Gradle Wrapper
|
|
331
|
+
def generate_gradle_wrapper(project_path, gradle_version)
|
|
332
|
+
Dir.chdir(project_path) do
|
|
333
|
+
system("gradle wrapper")
|
|
334
|
+
end
|
|
335
|
+
rescue => e
|
|
336
|
+
false
|
|
173
337
|
end
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return false
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
# 查找主工程的 app 模块 build.gradle
|
|
341
|
+
def find_app_module_gradle(project_path)
|
|
342
|
+
# 常见的 app 模块路径
|
|
343
|
+
possible_paths = [
|
|
344
|
+
File.join(project_path, "app/build.gradle"),
|
|
345
|
+
File.join(project_path, "app/build.gradle.kts"),
|
|
346
|
+
File.join(project_path, "launcher/build.gradle"),
|
|
347
|
+
File.join(project_path, "launcher/build.gradle.kts")
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
possible_paths.find { |path| File.exist?(path) }
|
|
188
351
|
end
|
|
189
|
-
|
|
190
|
-
#
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
352
|
+
|
|
353
|
+
# 从 build.gradle 文件中提取 SDK 版本信息
|
|
354
|
+
def extract_sdk_versions(gradle_file)
|
|
355
|
+
content = File.read(gradle_file)
|
|
356
|
+
versions = {}
|
|
357
|
+
|
|
358
|
+
# 提取 compileSdkVersion
|
|
359
|
+
if content =~ /compileSdkVersion\s+(\d+)/
|
|
360
|
+
versions[:compile_sdk] = $1
|
|
361
|
+
elsif content =~ /compileSdk\s*=?\s*(\d+)/
|
|
362
|
+
versions[:compile_sdk] = $1
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# 提取 targetSdkVersion
|
|
366
|
+
if content =~ /targetSdkVersion\s+(\d+)/
|
|
367
|
+
versions[:target_sdk] = $1
|
|
368
|
+
elsif content =~ /targetSdk\s*=?\s*(\d+)/
|
|
369
|
+
versions[:target_sdk] = $1
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# 提取 minSdkVersion
|
|
373
|
+
if content =~ /minSdkVersion\s+(\d+)/
|
|
374
|
+
versions[:min_sdk] = $1
|
|
375
|
+
elsif content =~ /minSdk\s*=?\s*(\d+)/
|
|
376
|
+
versions[:min_sdk] = $1
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# 提取 buildToolsVersion
|
|
380
|
+
if content =~ /buildToolsVersion\s+["']([^"']+)["']/
|
|
381
|
+
versions[:build_tools] = $1
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
versions
|
|
195
385
|
end
|
|
196
|
-
|
|
197
|
-
#
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
386
|
+
|
|
387
|
+
# 更新模块的 SDK 版本
|
|
388
|
+
def update_module_sdk_versions(gradle_file, versions)
|
|
389
|
+
return if versions.empty?
|
|
390
|
+
|
|
391
|
+
content = File.read(gradle_file)
|
|
392
|
+
updated = false
|
|
393
|
+
|
|
394
|
+
# 更新 compileSdkVersion
|
|
395
|
+
if versions[:compile_sdk]
|
|
396
|
+
if content.gsub!(/compileSdkVersion\s+\d+/, "compileSdkVersion #{versions[:compile_sdk]}")
|
|
397
|
+
updated = true
|
|
398
|
+
elsif content.gsub!(/compileSdk\s*=?\s*\d+/, "compileSdk = #{versions[:compile_sdk]}")
|
|
399
|
+
updated = true
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# 更新 targetSdkVersion
|
|
404
|
+
if versions[:target_sdk]
|
|
405
|
+
if content.gsub!(/targetSdkVersion\s+\d+/, "targetSdkVersion #{versions[:target_sdk]}")
|
|
406
|
+
updated = true
|
|
407
|
+
elsif content.gsub!(/targetSdk\s*=?\s*\d+/, "targetSdk = #{versions[:target_sdk]}")
|
|
408
|
+
updated = true
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# 更新 minSdkVersion
|
|
413
|
+
if versions[:min_sdk]
|
|
414
|
+
if content.gsub!(/minSdkVersion\s+\d+/, "minSdkVersion #{versions[:min_sdk]}")
|
|
415
|
+
updated = true
|
|
416
|
+
elsif content.gsub!(/minSdk\s*=?\s*\d+/, "minSdk = #{versions[:min_sdk]}")
|
|
417
|
+
updated = true
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
# 更新 buildToolsVersion
|
|
422
|
+
if versions[:build_tools]
|
|
423
|
+
if content.gsub!(/buildToolsVersion\s+["'][^"']+["']/, "buildToolsVersion \"#{versions[:build_tools]}\"")
|
|
424
|
+
updated = true
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
File.write(gradle_file, content) if updated
|
|
205
429
|
end
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
# 下载并设置Gradle环境
|
|
433
|
+
def download_and_setup_gradle(gradle_version)
|
|
434
|
+
# 确保缓存目录存在
|
|
435
|
+
FileUtils.mkdir_p(GRADLE_CACHE_DIR)
|
|
436
|
+
|
|
437
|
+
# 检查是否已解压
|
|
438
|
+
gradle_home = File.join(GRADLE_CACHE_DIR, "gradle-#{gradle_version}")
|
|
439
|
+
gradle_bin = File.join(gradle_home, "bin/gradle")
|
|
440
|
+
|
|
441
|
+
if File.exist?(gradle_bin)
|
|
442
|
+
# 使用缓存的Gradle,直接设置环境
|
|
443
|
+
setup_gradle_environment(gradle_home)
|
|
444
|
+
return true
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# 下载Gradle分发包
|
|
448
|
+
if download_gradle_distribution(gradle_version)
|
|
449
|
+
setup_gradle_environment(gradle_home)
|
|
450
|
+
return true
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
false
|
|
224
454
|
end
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
extract_cmd = "cd '#{File.dirname(extract_dir)}' && unzip -q '#{zip_file}'"
|
|
237
|
-
if system(extract_cmd)
|
|
238
|
-
# 设置执行权限
|
|
239
|
-
gradle_script = File.join(extract_dir, "bin/gradle")
|
|
240
|
-
if File.exist?(gradle_script)
|
|
241
|
-
system("chmod", "+x", gradle_script)
|
|
242
|
-
puts "✓ Gradle分发包解压成功"
|
|
243
|
-
return true
|
|
455
|
+
|
|
456
|
+
# 下载Gradle分发包
|
|
457
|
+
def download_gradle_distribution(gradle_version)
|
|
458
|
+
distribution_url = "https://services.gradle.org/distributions/gradle-#{gradle_version}-bin.zip"
|
|
459
|
+
cache_file = File.join(GRADLE_CACHE_DIR, "gradle-#{gradle_version}-bin.zip")
|
|
460
|
+
extract_dir = File.join(GRADLE_CACHE_DIR, "gradle-#{gradle_version}")
|
|
461
|
+
|
|
462
|
+
# 如果已存在ZIP文件,先检查完整性
|
|
463
|
+
if File.exist?(cache_file)
|
|
464
|
+
if verify_zip_integrity(cache_file)
|
|
465
|
+
return extract_gradle_distribution(cache_file, extract_dir, gradle_version)
|
|
244
466
|
else
|
|
245
|
-
|
|
246
|
-
|
|
467
|
+
# 缓存文件损坏,删除并重新下载
|
|
468
|
+
FileUtils.rm_f(cache_file)
|
|
247
469
|
end
|
|
248
|
-
|
|
249
|
-
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
# 下载分发包
|
|
473
|
+
Funlog.fancyinfo_update("下载Gradle #{gradle_version}...")
|
|
474
|
+
if download_with_curl(distribution_url, cache_file)
|
|
475
|
+
return extract_gradle_distribution(cache_file, extract_dir, gradle_version)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
Funlog.error("Gradle分发包下载失败")
|
|
479
|
+
false
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
# 简单的ZIP完整性检查
|
|
484
|
+
def verify_zip_integrity(zip_file)
|
|
485
|
+
# 1. 检查文件是否存在
|
|
486
|
+
unless File.exist?(zip_file)
|
|
250
487
|
return false
|
|
251
488
|
end
|
|
489
|
+
|
|
490
|
+
# 2. 检查文件大小(Gradle分发包通常大于10MB)
|
|
491
|
+
file_size = File.size(zip_file)
|
|
492
|
+
if file_size < 10_000_000 # 10MB
|
|
493
|
+
return false
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
# 3. 使用unzip -t测试ZIP文件完整性
|
|
497
|
+
test_cmd = "unzip -t '#{zip_file}' > /dev/null 2>&1"
|
|
498
|
+
system(test_cmd)
|
|
252
499
|
rescue => e
|
|
253
|
-
puts "✗ Gradle分发包解压异常: #{e.message}"
|
|
254
500
|
false
|
|
255
501
|
end
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
unless File.exist?(gradle_executable)
|
|
265
|
-
puts "✗ Gradle可执行文件不存在: #{gradle_executable}"
|
|
266
|
-
return false
|
|
502
|
+
|
|
503
|
+
# 使用curl下载文件
|
|
504
|
+
def download_with_curl(url, output_path)
|
|
505
|
+
# 简化的curl命令,避免特殊字符问题
|
|
506
|
+
cmd = "curl -L -o '#{output_path}' '#{url}'"
|
|
507
|
+
system(cmd)
|
|
508
|
+
rescue => e
|
|
509
|
+
false
|
|
267
510
|
end
|
|
268
|
-
|
|
269
|
-
#
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
511
|
+
|
|
512
|
+
# 解压Gradle分发包
|
|
513
|
+
def extract_gradle_distribution(zip_file, extract_dir, gradle_version)
|
|
514
|
+
begin
|
|
515
|
+
# 使用unzip命令解压
|
|
516
|
+
extract_cmd = "cd '#{File.dirname(extract_dir)}' && unzip -q '#{zip_file}'"
|
|
517
|
+
if system(extract_cmd)
|
|
518
|
+
# 设置执行权限
|
|
519
|
+
gradle_script = File.join(extract_dir, "bin/gradle")
|
|
520
|
+
if File.exist?(gradle_script)
|
|
521
|
+
system("chmod", "+x", gradle_script)
|
|
522
|
+
return true
|
|
523
|
+
else
|
|
524
|
+
Funlog.error("解压后未找到gradle可执行文件")
|
|
525
|
+
return false
|
|
526
|
+
end
|
|
527
|
+
else
|
|
528
|
+
Funlog.error("Gradle分发包解压失败")
|
|
529
|
+
return false
|
|
530
|
+
end
|
|
531
|
+
rescue => e
|
|
532
|
+
false
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
# 设置Gradle环境变量
|
|
537
|
+
def setup_gradle_environment(gradle_home)
|
|
538
|
+
# 直接检查gradle可执行文件
|
|
539
|
+
gradle_bin_dir = File.join(gradle_home, "bin")
|
|
540
|
+
gradle_executable = File.join(gradle_bin_dir, "gradle")
|
|
541
|
+
|
|
542
|
+
unless File.exist?(gradle_executable)
|
|
288
543
|
return false
|
|
289
544
|
end
|
|
545
|
+
|
|
546
|
+
# 设置环境变量
|
|
547
|
+
ENV['GRADLE_HOME'] = gradle_home
|
|
548
|
+
ENV['PATH'] = "#{gradle_bin_dir}:#{ENV['PATH']}"
|
|
549
|
+
|
|
550
|
+
true
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
# 使用官方Gradle命令生成wrapper
|
|
554
|
+
def generate_gradle_wrapper_official(project_path, gradle_version)
|
|
555
|
+
Dir.chdir(project_path) do
|
|
556
|
+
# 使用gradle wrapper命令
|
|
557
|
+
cmd = "gradle wrapper"
|
|
558
|
+
system(cmd)
|
|
559
|
+
end
|
|
560
|
+
rescue => e
|
|
561
|
+
false
|
|
562
|
+
end
|
|
290
563
|
end
|
|
291
|
-
rescue => e
|
|
292
|
-
puts "✗ 官方Gradle命令执行异常: #{e.message}"
|
|
293
|
-
false
|
|
294
|
-
end
|
|
295
564
|
end
|
|
296
565
|
end
|