pindo 5.13.7 → 5.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/git_handler.rb +247 -42
  3. data/lib/pindo/command/android/autobuild.rb +104 -31
  4. data/lib/pindo/command/android/autoresign.rb +23 -322
  5. data/lib/pindo/command/android/keystore.rb +7 -130
  6. data/lib/pindo/command/appstore/adhocbuild.rb +52 -15
  7. data/lib/pindo/command/appstore/autobuild.rb +104 -8
  8. data/lib/pindo/command/appstore/autoresign.rb +3 -5
  9. data/lib/pindo/command/ios/autobuild.rb +96 -32
  10. data/lib/pindo/command/ios/build.rb +8 -186
  11. data/lib/pindo/command/jps/media.rb +146 -0
  12. data/lib/pindo/command/jps/upload.rb +49 -21
  13. data/lib/pindo/command/jps.rb +1 -0
  14. data/lib/pindo/command/unity/autobuild.rb +141 -32
  15. data/lib/pindo/command/unity/packpush.rb +5 -8
  16. data/lib/pindo/command/utils/repoinit.rb +0 -2
  17. data/lib/pindo/command/utils/tag.rb +58 -26
  18. data/lib/pindo/command/utils.rb +0 -1
  19. data/lib/pindo/command/web/autobuild.rb +98 -34
  20. data/lib/pindo/command.rb +0 -56
  21. data/lib/pindo/config/build_info_manager.rb +7 -8
  22. data/lib/pindo/module/android/android_config_helper.rb +2 -11
  23. data/lib/pindo/module/appselect.rb +15 -41
  24. data/lib/pindo/module/appstore/itcapp_helper.rb +3 -6
  25. data/lib/pindo/module/build/build_helper.rb +28 -18
  26. data/lib/pindo/module/build/git_repo_helper.rb +284 -405
  27. data/lib/pindo/module/cert/pem_helper.rb +3 -6
  28. data/lib/pindo/module/pgyer/pgyerhelper.rb +193 -25
  29. data/lib/pindo/module/task/model/appstore/appstore_task.rb +5 -0
  30. data/lib/pindo/module/task/model/build/android_build_adhoc_task.rb +13 -187
  31. data/lib/pindo/module/task/model/build/android_build_dev_task.rb +36 -34
  32. data/lib/pindo/module/task/model/build/android_build_gplay_task.rb +13 -187
  33. data/lib/pindo/module/task/model/build/ios_build_adhoc_task.rb +9 -6
  34. data/lib/pindo/module/task/model/build/ios_build_appstore_task.rb +9 -6
  35. data/lib/pindo/module/task/model/build/ios_build_dev_task.rb +37 -32
  36. data/lib/pindo/module/task/model/build/web_build_dev_task.rb +7 -5
  37. data/lib/pindo/module/task/model/build_task.rb +8 -11
  38. data/lib/pindo/module/task/model/git/git_commit_task.rb +118 -0
  39. data/lib/pindo/module/task/model/git/git_tag_task.rb +125 -0
  40. data/lib/pindo/module/task/model/git_task.rb +75 -0
  41. data/lib/pindo/module/task/model/jps/jps_message_task.rb +178 -0
  42. data/lib/pindo/module/task/model/{jps_resign_task.rb → jps/jps_resign_task.rb} +14 -23
  43. data/lib/pindo/module/task/model/jps/jps_upload_media_task.rb +248 -0
  44. data/lib/pindo/module/task/model/{jps_upload_task.rb → jps/jps_upload_task.rb} +39 -94
  45. data/lib/pindo/module/task/model/jps_task.rb +43 -0
  46. data/lib/pindo/module/task/model/{ipa_local_resign_task.rb → resign/ipa_local_resign_task.rb} +7 -2
  47. data/lib/pindo/module/task/model/unity/unity_config_task.rb +103 -0
  48. data/lib/pindo/module/task/model/{unity_export_task.rb → unity/unity_export_task.rb} +76 -78
  49. data/lib/pindo/module/task/model/unity/unity_update_task.rb +95 -0
  50. data/lib/pindo/module/task/model/unity/unity_yoo_asset_task.rb +156 -0
  51. data/lib/pindo/module/task/model/unity_task.rb +118 -0
  52. data/lib/pindo/module/task/pindo_task.rb +101 -1
  53. data/lib/pindo/module/task/task_manager.rb +29 -24
  54. data/lib/pindo/module/unity/nuget_helper.rb +7 -7
  55. data/lib/pindo/module/unity/unity_command_helper.rb +188 -0
  56. data/lib/pindo/module/unity/unity_env_helper.rb +208 -0
  57. data/lib/pindo/module/unity/unity_helper.rb +189 -746
  58. data/lib/pindo/module/unity/unity_proc_helper.rb +390 -0
  59. data/lib/pindo/options/core/global_options_state.rb +96 -26
  60. data/lib/pindo/options/core/option_configuration.rb +3 -0
  61. data/lib/pindo/options/core/option_item.rb +36 -0
  62. data/lib/pindo/options/groups/build_options.rb +23 -6
  63. data/lib/pindo/options/groups/git_options.rb +115 -0
  64. data/lib/pindo/options/groups/jps_options.rb +7 -0
  65. data/lib/pindo/options/groups/option_group.rb +15 -0
  66. data/lib/pindo/options/groups/unity_options.rb +49 -0
  67. data/lib/pindo/options/options.rb +2 -0
  68. data/lib/pindo/version.rb +2 -2
  69. metadata +25 -14
  70. data/lib/pindo/base/githelper.rb +0 -686
  71. data/lib/pindo/base/pindocontext.rb +0 -602
  72. data/lib/pindo/command/utils/feishu.rb +0 -134
  73. data/lib/pindo/module/build/version_helper.rb +0 -146
  74. data/lib/pindo/module/task/model/git_tag_task.rb +0 -80
@@ -1,13 +1,25 @@
1
1
  require 'singleton'
2
- require 'pindo/base/githelper'
2
+ require 'pindo/base/git_handler'
3
3
  require 'pindo/base/executable'
4
- require 'pindo/base/pindocontext'
5
4
  require 'highline/import'
6
5
 
7
6
  module Pindo
7
+ # 版本号增加类型常量(与 GitOptions::VERSION_INCREASE_TYPES 一致)
8
+ module VersionIncreaseType
9
+ MAIN = :main # 大版本号增加1 (x.0.0)
10
+ MINI = :mini # 小版本号增加1 (0.x.0)
11
+ PATCH = :patch # patch版本号增加1 (0.0.x)
12
+ end
13
+
14
+ # 创建Tag类型常量(与 GitOptions::CREATE_TAG_TYPES 一致)
15
+ module CreateTagType
16
+ NEW = :new # 创建新的tag,新的版本号
17
+ RECREATE = :recreate # 重新创建当前版本号
18
+ NONE = :none # 不创建版本号
19
+ end
20
+
8
21
  class GitRepoHelper
9
22
  include Singleton
10
- include Pindo::Githelper
11
23
 
12
24
  attr_accessor :temp_tag_decision
13
25
 
@@ -17,57 +29,11 @@ module Pindo
17
29
  end
18
30
  end
19
31
 
20
- # 主入口函数 - 创建并推送 Git 标签
21
- # @param project_dir [String] 项目目录
22
- # @param mode [String] 版本号增加模式 (major/minor/patch)
23
- # @param force_retag [Boolean] 是否强制重新打tag
24
- # @param custom_tag [String] 自定义tag版本号
25
- # @param release_branch [String] 发布分支名称,默认为 'master'
26
- def create_and_push_tag(project_dir:, mode: 'minor', force_retag: false, custom_tag: nil, release_branch: 'master')
27
- puts project_dir
28
-
29
- # 1. 验证 Git 仓库
30
- unless is_git_directory?(local_repo_dir: project_dir)
31
- raise Informative, "当前目录不是git仓库,请在git仓库目录下执行此命令"
32
- end
33
-
34
- # 获取git仓库根目录
35
- root_dir = git_root_directory(local_repo_dir: project_dir)
36
- if root_dir.nil?
37
- raise Informative, "无法获取git仓库根目录"
38
- end
39
-
40
- # 2. 处理未提交的文件
41
- process_need_add_files(project_dir: root_dir)
42
-
43
- # 3. 获取当前分支
44
- current_branch = git!(%W(-C #{root_dir} rev-parse --abbrev-ref HEAD)).strip
45
- coding_branch = current_branch
46
-
47
- # 4. 合并到发布分支
48
- Funlog.instance.fancyinfo_start("开始合并到#{release_branch}分支")
49
- merge_to_release_branch(
50
- project_dir: root_dir,
51
- release_branch: release_branch,
52
- coding_branch: coding_branch
53
- )
54
-
55
- # 5. 添加版本标签并返回 tag 名称
56
- new_tag = add_release_tag(
57
- project_dir: root_dir,
58
- increment_mode: mode,
59
- force_retag: force_retag,
60
- custom_tag: custom_tag
61
- )
62
-
63
- new_tag
64
- end
65
-
66
32
  # 检查并安装 git-cliff
67
33
  # @param project_path [String] 项目路径
68
34
  def check_check_and_install_cliff(project_path)
69
- if is_git_directory?(local_repo_dir: project_path)
70
- current_git_root_path = git_root_directory(local_repo_dir: project_path)
35
+ if Pindo::GitHandler.is_git_directory?(local_repo_dir: project_path)
36
+ current_git_root_path = Pindo::GitHandler.git_root_directory(local_repo_dir: project_path)
71
37
  unless File.exist?(File.join(current_git_root_path, 'cliff.toml'))
72
38
  add_git_cliffconfig(current_git_root_path)
73
39
  end
@@ -84,10 +50,59 @@ module Pindo
84
50
  end
85
51
  end
86
52
 
87
- # 写入 .gitignore 文件
53
+ # 添加 git-cliff 配置
54
+ # @param project_path [String] 项目路径
55
+ def add_git_cliffconfig(project_path)
56
+ temp_dir = Dir.pwd
57
+ Funlog.instance.fancyinfo_start("添加日志变更git-cliff配置...")
58
+ if Pindo::GitHandler.is_git_directory?(local_repo_dir: project_path)
59
+ current_git_root_path = Pindo::GitHandler.git_root_directory(local_repo_dir: project_path)
60
+ Dir.chdir(current_git_root_path)
61
+ pindo_common_dir = clone_pindo_common_config_repo(force_delete:false)
62
+ if File.exist?(File.join(pindo_common_dir, 'cliff.toml'))
63
+ FileUtils.cp_r(File.join(pindo_common_dir, 'cliff.toml'), File.join(current_git_root_path, 'cliff.toml'))
64
+ end
65
+ Funlog.instance.fancyinfo_update("仓库添加git-cliff配置")
66
+ # 不自动提交推送,因为后续会将 cliff.toml 和 .gitignore 一起提交
67
+ check_gitignore(current_git_root_path, auto_commit_push: false)
68
+ Funlog.instance.fancyinfo_update("仓库检查并添加.gitignore规则")
69
+ Dir.chdir(current_git_root_path)
70
+ current_branch = Pindo::GitHandler.git!(%W(-C #{current_git_root_path} rev-parse --abbrev-ref HEAD)).strip
71
+ Pindo::GitHandler.git!(%W(-C #{current_git_root_path} add cliff.toml))
72
+ # .gitignore 已由 check_gitignore 自动添加到暂存区,无需重复添加
73
+ commit_message = "docs: 添加日志变更配置".encode('UTF-8')
74
+ Pindo::GitHandler.git!(%W(-C #{current_git_root_path} commit -m #{commit_message}))
75
+ Pindo::GitHandler.git!(%W(-C #{current_git_root_path} push origin #{current_branch}))
76
+ else
77
+ Funlog.instance.fancyinfo_error("当前目录不是git仓库,请在git仓库根目录下执行此命令")
78
+ Dir.chdir(temp_dir)
79
+ return
80
+ end
81
+ Funlog.instance.fancyinfo_success("日志变更git-cliff配置完成!")
82
+ Dir.chdir(temp_dir)
83
+ end
84
+
85
+ # 安装 git-cliff
86
+ def install_gitcliff
87
+ puts "\n检查git-cliff命令是否安装"
88
+ begin
89
+ if !system('which git-cliff > /dev/null 2>&1')
90
+ system('bash -c "$(curl -fsSL https://gitee.com/goodtools/env/raw/master/gitcliff_install.sh)"')
91
+ end
92
+ rescue
93
+ Funlog.instance.fancyinfo_error("安装git-cliff出现错误")
94
+ end
95
+ end
96
+
97
+
98
+ # 检查并写入 .gitignore 文件(不会重复添加规则)
99
+ # 如果修改了文件,会自动执行 git add、commit 和 push
88
100
  # @param git_root_dir [String] Git 根目录
89
- def write_gitignore(git_root_dir)
101
+ # @param auto_commit_push [Boolean] 是否自动提交并推送,默认 true
102
+ # @return [Boolean] 返回是否修改了 .gitignore 文件
103
+ def check_gitignore(git_root_dir, auto_commit_push: true)
90
104
  gitignore_path = File.join(git_root_dir, '.gitignore')
105
+ file_modified = false
91
106
 
92
107
  # 定义要添加的gitignore规则数组
93
108
  ignore_rules = [
@@ -110,6 +125,7 @@ module Pindo
110
125
  'Assets/Packages',
111
126
  'Assets/WebGLTemplates.meta',
112
127
  'Assets/WebGLTemplates/',
128
+ 'JPSMedia',
113
129
  'Packages/packages-lock.json'
114
130
  ]
115
131
 
@@ -134,397 +150,260 @@ module Pindo
134
150
  f.puts(rule)
135
151
  end
136
152
  end
137
- end
138
- end
139
153
 
140
- # 添加 git-cliff 配置
141
- # @param project_path [String] 项目路径
142
- def add_git_cliffconfig(project_path)
143
- temp_dir = Dir.pwd
144
- Funlog.instance.fancyinfo_start("添加日志变更git-cliff配置...")
145
- if is_git_directory?(local_repo_dir: project_path)
146
- current_git_root_path = git_root_directory(local_repo_dir: project_path)
147
- Dir.chdir(current_git_root_path)
148
- pindo_common_dir = clone_pindo_common_config_repo(force_delete:false)
149
- if File.exist?(File.join(pindo_common_dir, 'cliff.toml'))
150
- FileUtils.cp_r(File.join(pindo_common_dir, 'cliff.toml'), File.join(current_git_root_path, 'cliff.toml'))
154
+ # 标记文件已修改
155
+ file_modified = true
156
+
157
+ # 自动添加到 Git 暂存区、提交并推送
158
+ if Pindo::GitHandler.is_git_directory?(local_repo_dir: git_root_dir)
159
+ begin
160
+ # 1. 添加到暂存区
161
+ Pindo::GitHandler.git!(%W(-C #{git_root_dir} add .gitignore))
162
+ Funlog.instance.fancyinfo_success("已自动添加 .gitignore 到 Git 暂存区")
163
+
164
+ # 2. 如果需要,自动提交并推送
165
+ if auto_commit_push
166
+ # 获取当前分支
167
+ current_branch = Pindo::GitHandler.git!(%W(-C #{git_root_dir} rev-parse --abbrev-ref HEAD)).strip
168
+
169
+ # 提交
170
+ commit_message = "chore: 更新 .gitignore 规则"
171
+ Pindo::GitHandler.git!(%W(-C #{git_root_dir} commit -m #{commit_message}))
172
+ Funlog.instance.fancyinfo_success("已自动提交 .gitignore 更改")
173
+
174
+ # 推送到远程
175
+ Pindo::GitHandler.git!(%W(-C #{git_root_dir} push origin #{current_branch}))
176
+ Funlog.instance.fancyinfo_success("已自动推送 .gitignore 到远程仓库")
177
+ end
178
+ rescue => e
179
+ Funlog.instance.fancyinfo_error("Git 操作失败: #{e.message}")
180
+ end
151
181
  end
152
- Funlog.instance.fancyinfo_update("仓库添加git-cliff配置")
153
- write_gitignore(current_git_root_path)
154
- Funlog.instance.fancyinfo_update("仓库添加.gitignore")
155
- Dir.chdir(current_git_root_path)
156
- current_branch = git!(%W(-C #{current_git_root_path} rev-parse --abbrev-ref HEAD)).strip
157
- git!(%W(-C #{current_git_root_path} add cliff.toml))
158
- git!(%W(-C #{current_git_root_path} add .gitignore))
159
- commit_message = "docs: 添加日志变更配置".encode('UTF-8')
160
- git!(%W(-C #{current_git_root_path} commit -m #{commit_message}))
161
- git!(%W(-C #{current_git_root_path} push origin #{current_branch}))
162
- else
163
- Funlog.instance.fancyinfo_error("当前目录不是git仓库,请在git仓库根目录下执行此命令")
164
- Dir.chdir(temp_dir)
165
- return
166
182
  end
167
- Funlog.instance.fancyinfo_success("日志变更git-cliff配置完成!")
168
- Dir.chdir(temp_dir)
183
+
184
+ file_modified
169
185
  end
170
186
 
171
- # 安装 git-cliff
172
- def install_gitcliff
173
- puts "\n检查git-cliff命令是否安装"
174
- begin
175
- if !system('which git-cliff > /dev/null 2>&1')
176
- system('bash -c "$(curl -fsSL https://gitee.com/goodtools/env/raw/master/gitcliff_install.sh)"')
187
+ # 从Git tag获取当前版本号
188
+ # @param project_dir [String] 项目目录路径
189
+ # @param tag_prefixes [Array<String>] 可能的tag前缀列表,默认为 ["v", "release", ""]
190
+ # @return [String] 版本号(例如:1.2.0),如果没有tag则返回0.0.1
191
+ def get_current_version_from_tag(project_dir: nil, tag_prefixes: nil)
192
+ raise ArgumentError, "项目目录不能为空" if project_dir.nil?
193
+
194
+ # 获取git根目录
195
+ git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: project_dir)
196
+ return "0.0.1" unless git_root
197
+
198
+ # 如果传入的前缀为空或nil,使用默认值
199
+ prefixes = (tag_prefixes.nil? || tag_prefixes.empty?) ? ["v", "release", ""] : tag_prefixes
200
+
201
+ # 尝试不同的tag前缀
202
+ latest_tag = nil
203
+ matched_prefix = nil
204
+ prefixes.each do |prefix|
205
+ latest_tag = Pindo::GitHandler.get_latest_version_tag(project_dir: git_root, tag_prefix: prefix)
206
+ if latest_tag
207
+ matched_prefix = prefix
208
+ break
177
209
  end
178
- rescue
179
- Funlog.instance.fancyinfo_error("安装git-cliff出现错误")
180
210
  end
181
- end
182
211
 
183
- # 检查是否需要添加 Git 标签
184
- # @param project_path [String] 项目路径
185
- # @param auto_mode [Boolean] 是否自动模式
186
- # @return [Array<Boolean, Array>] [是否需要添加tag, tag参数]
187
- def check_is_need_add_tag?(project_path, auto_mode: false)
188
- tag_action_parms = nil
189
- is_need_add_tag = false
190
-
191
- if is_git_directory?(local_repo_dir: project_path)
192
- current_git_root_path = git_root_directory(local_repo_dir: project_path)
193
- latest_tag = get_latest_version_tag(project_dir: current_git_root_path)
194
-
195
- # 检查是否需要打 tag:
196
- # 1. 最新 tag 不在 HEAD 上,或者
197
- # 2. 仓库有未提交的更改
198
- tag_not_at_head = !is_tag_at_head?(git_root_dir: current_git_root_path, tag_name: latest_tag)
199
- has_uncommitted = has_uncommitted_changes?(git_root_dir: current_git_root_path)
200
-
201
- if tag_not_at_head || has_uncommitted
202
- # 提示用户需要打 tag 的原因
203
- if has_uncommitted && !tag_not_at_head
204
- puts "\n注意:仓库有未提交的更改,建议提交后再打 Tag"
205
- end
206
- # 检查环境变量
207
- env_tag_decision = ENV['PINDO_TAG_DECISION']
208
- if env_tag_decision && !env_tag_decision.empty?
209
- case env_tag_decision.downcase
210
- when 'new', 'new_tag', '1'
211
- puts "\n环境变量指定:新增版本号,打新Tag"
212
- puts
213
- tag_action_parms = []
214
- is_need_add_tag = true
215
- # 保存到缓存
216
- context = PindoContext.instance
217
- decision = {
218
- tag_action_parms: tag_action_parms,
219
- is_need_add_tag: is_need_add_tag,
220
- action: :new_tag,
221
- description: "新增版本号,打新Tag"
222
- }
223
- context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
224
- return is_need_add_tag, tag_action_parms
225
- when 'retag', 'recreate', '2'
226
- puts "\n环境变量指定:将上次的Tag删除重新打Tag"
227
- puts
228
- tag_action_parms = ['--retag']
229
- is_need_add_tag = true
230
- # 保存到缓存
231
- context = PindoContext.instance
232
- decision = {
233
- tag_action_parms: tag_action_parms,
234
- is_need_add_tag: is_need_add_tag,
235
- action: :recreate_tag,
236
- description: "将上次的Tag删除重新打Tag"
237
- }
238
- context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
239
- return is_need_add_tag, tag_action_parms
240
- when 'skip', 'no', 'none', '3'
241
- puts "\n环境变量指定:不需要Tag继续编译"
242
- puts
243
- tag_action_parms = nil
244
- is_need_add_tag = false
245
- # 保存到缓存
246
- context = PindoContext.instance
247
- decision = {
248
- tag_action_parms: tag_action_parms,
249
- is_need_add_tag: is_need_add_tag,
250
- action: :continue_without_tag,
251
- description: "不需要Tag继续编译且上传"
252
- }
253
- context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
254
- return is_need_add_tag, tag_action_parms
255
- when 'exit', 'quit', '4'
256
- Funlog.instance.fancyinfo_error("环境变量指定:终止退出编译!")
257
- return false, nil
258
- end
259
- end
212
+ return "0.0.1" if latest_tag.nil?
260
213
 
261
- if auto_mode
262
- # 在自动化模式或没有交互式终端时,默认选择新增版本号打新Tag
263
- puts "检测到当前代码没有打Tag,在自动模式下将自动新增版本号并打新Tag"
264
- tag_action_parms = []
265
- is_need_add_tag = true
266
- else
267
- # 检查是否已有用户选择
268
- context = PindoContext.instance
269
- # 优先从持久化缓存读取,如果没有则从内存临时缓存读取
270
- cached_decision = context.get_selection(PindoContext::SelectionKey::TAG_DECISION)
271
-
272
- # 只有当持久化缓存中确实不存在该键时,才从临时缓存读取
273
- if cached_decision.nil? && !context.has_selection?(PindoContext::SelectionKey::TAG_DECISION)
274
- # 从 GitRepoHelper 的临时缓存读取
275
- cached_decision = self.temp_tag_decision
276
- end
277
-
278
- if cached_decision && cached_decision.is_a?(Hash)
279
- # 使用之前的选择
280
- puts "\n使用之前的选择:#{cached_decision[:description]}"
281
- tag_action_parms = cached_decision[:tag_action_parms]
282
- is_need_add_tag = cached_decision[:is_need_add_tag]
283
-
284
- # 如果是退出选择,则返回
285
- if cached_decision[:action] == :exit
286
- Funlog.instance.fancyinfo_error("终止退出编译!")
287
- return false, nil
288
- end
289
- else
290
- # 第一次询问
291
- cli = HighLine.new
292
- selected_action = nil
293
- selected_description = nil
294
-
295
- menu_options = {
296
- "新增版本号,打新Tag" => -> {
297
- tag_action_parms = []
298
- selected_action = :new_tag
299
- selected_description = "新增版本号,打新Tag"
300
- is_need_add_tag = true
301
- :new_tag
302
- },
303
- "将上次的Tag删除重新打Tag" => -> {
304
- tag_action_parms = []
305
- tag_action_parms << "--retag"
306
- selected_action = :recreate_tag
307
- selected_description = "将上次的Tag删除重新打Tag"
308
- is_need_add_tag = true
309
- :recreate_tag
310
- },
311
- "不需要Tag继续编译且上传,手动修改上传备注" => -> {
312
- puts ""
313
- tag_action_parms = nil
314
- selected_action = :continue_without_tag
315
- selected_description = "不需要Tag继续编译且上传"
316
- is_need_add_tag = false
317
- :continue_without_tag
318
- },
319
- "终止退出编译" => -> {
320
- tag_action_parms = nil
321
- selected_action = :exit
322
- selected_description = "终止退出编译"
323
- is_need_add_tag = false
324
- Funlog.instance.fancyinfo_error("终止退出编译!")
325
- :exit
326
- }
327
- }
328
-
329
- result = cli.choose do |menu|
330
- menu.header = "当前代码并没有打Tag,上传的Changelog需要Tag"
331
- menu.prompt = "请选中打Tag的方式, 请输入选项(1/2/3...):"
332
- menu_options.each do |option, action|
333
- menu.choice(option) { action.call }
334
- end
335
- end
336
-
337
- # 如果选择退出,直接返回
338
- return false, nil if selected_action == :exit
339
-
340
- # 保存用户选择
341
- # 只有选择"新增版本号,打新Tag"时才保存到持久化缓存
342
- if selected_action == :new_tag
343
- # 保存到持久化缓存(文件)
344
- context.set_selection(PindoContext::SelectionKey::TAG_DECISION, {
345
- action: selected_action,
346
- description: selected_description,
347
- tag_action_parms: tag_action_parms,
348
- is_need_add_tag: is_need_add_tag
349
- })
350
- # 清除临时缓存
351
- self.temp_tag_decision = nil
352
- else
353
- # 不清空持久化缓存(避免将 nil 写入文件)
354
- # 只使用临时缓存(仅在内存中,不会写入文件)
355
- self.temp_tag_decision = {
356
- action: selected_action,
357
- description: selected_description,
358
- tag_action_parms: tag_action_parms,
359
- is_need_add_tag: is_need_add_tag
360
- }
361
- end
362
- end
363
- end
364
- end
214
+ # 从tag中提取版本号,移除匹配到的前缀
215
+ version = if matched_prefix && !matched_prefix.empty?
216
+ latest_tag.sub(/^#{Regexp.escape(matched_prefix)}/, '')
217
+ else
218
+ latest_tag
365
219
  end
366
220
 
367
- return [is_need_add_tag, tag_action_parms]
221
+ # 确保版本号格式正确(x.y.z)
222
+ if version =~ /^\d+\.\d+\.\d+$/
223
+ version
224
+ elsif version =~ /^\d+\.\d+$/
225
+ "#{version}.0"
226
+ elsif version =~ /^\d+$/
227
+ "#{version}.0.0"
228
+ else
229
+ "0.0.1"
230
+ end
368
231
  end
369
232
 
370
- private
371
-
372
- # 添加版本标签
373
- # @param project_dir [String] 项目目录
374
- # @param increment_mode [String] 版本号增加模式 (major/minor/patch)
375
- # @param force_retag [Boolean] 是否强制重新打tag
376
- # @param custom_tag [String] 自定义tag版本号
377
- def add_release_tag(project_dir:, increment_mode: "minor", force_retag: false, custom_tag: nil)
233
+ # 获取Build号(从commit hash转换而来)
234
+ # @param project_dir [String] 项目目录路径
235
+ # @return [Integer] Build号(6位16进制转10进制)
236
+ def get_build_number_from_commit(project_dir: nil)
378
237
  raise ArgumentError, "项目目录不能为空" if project_dir.nil?
379
238
 
380
- # 如果指定了自定义tag,直接使用
381
- if custom_tag && !custom_tag.empty?
382
- Funlog.instance.fancyinfo_start("使用指定的tag版本: #{custom_tag}")
383
-
384
- # 确保tag有v前缀
385
- new_tag = custom_tag.start_with?('v') ? custom_tag : "v#{custom_tag}"
239
+ # 获取git根目录
240
+ git_root = Pindo::GitHandler.git_root_directory(local_repo_dir: project_dir)
241
+ return 1 unless git_root
386
242
 
387
- # 检查tag是否已存在
388
- existing_tags = git!(%W(-C #{project_dir} tag -l)).split("\n")
389
- if existing_tags.include?(new_tag)
390
- if force_retag
391
- Funlog.instance.fancyinfo_update("tag #{new_tag} 已存在,强制重新打tag")
392
- git!(%W(-C #{project_dir} tag -d #{new_tag}))
393
- git!(%W(-C #{project_dir} push origin :refs/tags/#{new_tag}))
394
- else
395
- Funlog.instance.fancyinfo_success("tag #{new_tag} 已存在")
396
- Funlog.instance.fancyinfo_success("仓库路径: #{project_dir}")
397
- return new_tag # 返回已存在的 tag
398
- end
399
- end
243
+ begin
244
+ # 获取当前HEAD的commit hash前6位
245
+ commit_hash = Pindo::GitHandler.git!(%W(-C #{git_root} rev-parse HEAD)).strip[0..5]
400
246
 
401
- # 创建tag并推送
402
- git!(%W(-C #{project_dir} tag #{new_tag}))
403
- git!(%W(-C #{project_dir} push origin #{new_tag}))
247
+ # 将16进制转换为10进制
248
+ build_number = commit_hash.to_i(16)
404
249
 
405
- Funlog.instance.fancyinfo_success("创建tag: #{new_tag}")
406
- Funlog.instance.fancyinfo_success("仓库路径: #{project_dir}")
407
- return new_tag # 返回新创建的 tag
408
- end
250
+ # 确保在Android versionCode安全范围内(最大值为2^31-1)
251
+ max_value = 2**31 - 1
252
+ build_number = build_number % max_value if build_number > max_value
409
253
 
410
- # 原有的自动递增逻辑
411
- Funlog.instance.fancyinfo_start("开始创建初tag")
412
- latest_tag = get_latest_version_tag(project_dir: project_dir)
413
- if latest_tag.nil?
414
- new_tag = create_next_version_tag(
415
- project_dir: project_dir,
416
- tag_prefix: "v",
417
- increment_mode: increment_mode,
418
- force_retag: false
419
- )
420
- Funlog.instance.fancyinfo_success("创建初始tag: #{new_tag}")
421
- Funlog.instance.fancyinfo_success("仓库路径: #{project_dir}")
422
- return new_tag # 返回初始 tag
423
- end
254
+ # 确保build_number不为0
255
+ build_number = 1 if build_number == 0
424
256
 
425
- if is_tag_at_head?(git_root_dir: project_dir, tag_name: latest_tag)
426
- Funlog.instance.fancyinfo_success("当前commit已有tag: #{latest_tag},无需重新打tag")
427
- Funlog.instance.fancyinfo_success("仓库路径: #{project_dir}")
428
- return latest_tag # 返回已存在的 tag
257
+ build_number
258
+ rescue StandardError => e
259
+ Funlog.instance.fancyinfo_error("获取commit hash失败: #{e.message}")
260
+ # 如果获取失败,返回基于时间戳的默认值
261
+ Time.now.to_i % 1000000 + 1
429
262
  end
263
+ end
430
264
 
431
- Funlog.instance.fancyinfo_success("最近的上次tag是: #{latest_tag} ")
432
- new_tag = create_next_version_tag(
433
- project_dir: project_dir,
434
- tag_prefix: "v",
435
- increment_mode: increment_mode,
436
- force_retag: force_retag
437
- )
265
+
438
266
 
439
- Funlog.instance.fancyinfo_success("当前仓库的tag: #{new_tag}")
440
- Funlog.instance.fancyinfo_success("仓库路径: #{project_dir}")
267
+ # 验证Build号是否在有效范围内
268
+ # @param build_number [Integer] Build号
269
+ # @return [Boolean] 是否有效
270
+ def valid_build_number?(build_number)
271
+ return false if build_number.nil?
441
272
 
442
- new_tag # 返回新创建的 tag
273
+ # Android versionCode的有效范围是1到2^31-1
274
+ build_number >= 1 && build_number <= 2**31 - 1
443
275
  end
444
276
 
445
- # 合并到发布分支
277
+ # 计算构建版本号
446
278
  # @param project_dir [String] 项目目录
447
- # @param release_branch [String] 发布分支名称
448
- # @param coding_branch [String] 当前开发分支名称
449
- def merge_to_release_branch(project_dir:, release_branch:, coding_branch:)
450
- current_project_dir = project_dir
451
- Funlog.instance.fancyinfo_start("开始合并到#{release_branch}分支")
452
- if !coding_branch.eql?(release_branch)
453
- coding_branch_commit_id = git!(%W(-C #{current_project_dir} rev-parse #{coding_branch})).strip
454
- release_branch_commit_id = nil
455
-
456
- if remote_branch_exists?(local_repo_dir: current_project_dir, branch: release_branch)
457
- Funlog.instance.fancyinfo_update("存在#{release_branch}远程分支")
458
- if local_branch_exists?(local_repo_dir: current_project_dir, branch: release_branch)
459
- Funlog.instance.fancyinfo_update("存在#{release_branch}本地分支")
460
- git!(%W(-C #{current_project_dir} checkout #{release_branch}))
461
- else
462
- Funlog.instance.fancyinfo_update("不存在#{release_branch}本地分支")
463
- git!(%W(-C #{current_project_dir} checkout -b #{release_branch} origin/#{release_branch}))
464
- end
465
-
466
- git!(%W(-C #{current_project_dir} branch --set-upstream-to=origin/#{release_branch} #{release_branch}))
467
- git!(%W(-C #{current_project_dir} fetch origin #{release_branch}))
468
- git!(%W(-C #{current_project_dir} merge origin/#{release_branch}))
279
+ # @param tag_prefix [String] tag前缀,默认 'v'
280
+ # @param create_tag_type [Symbol] 创建tag类型
281
+ # @param version_increase_type [Symbol] 版本号增加类型
282
+ # @return [String] 构建版本号
283
+ def calculate_build_version(project_dir:, tag_prefix: 'v', create_tag_type: nil, version_increase_type: nil)
284
+ raise ArgumentError, "项目目录不能为空" if project_dir.nil?
469
285
 
470
- # 执行合并操作,捕获输出以便后续检查冲突
471
- stdout, exit_status = Executable.capture_command('git', %W(-C #{current_project_dir} merge #{coding_branch}), :capture => :out)
286
+ # 设置默认值
287
+ create_tag_type ||= Pindo::CreateTagType::NEW
288
+ version_increase_type ||= Pindo::VersionIncreaseType::MINI
472
289
 
473
- # 检查是否有冲突(git merge 在有冲突时返回非0状态)
474
- conflict_filelist = git!(%W(-C #{current_project_dir} diff --name-only --diff-filter=U --relative))
475
- if !conflict_filelist.nil? && conflict_filelist.size > 0
476
- puts "合并代码冲突, 冲突文件如下:"
477
- raise Informative, "请手动处理冲突的文件!!!"
478
- else
479
- git!(%W(-C #{current_project_dir} push))
480
- Funlog.instance.fancyinfo_success("代码已经合并到#{release_branch}分支")
481
- # 获取 release_branch 的 commit ID(处理空分支情况)
482
- begin
483
- release_branch_commit_id = git!(%W(-C #{current_project_dir} rev-parse #{release_branch})).strip
484
- rescue => e
485
- # 分支可能存在但没有提交(空分支),此时使用 coding_branch 的 commit
486
- Funlog.instance.fancyinfo_update("#{release_branch}分支为空或获取commit失败,将使用当前分支commit")
487
- release_branch_commit_id = coding_branch_commit_id
488
- end
489
- end
290
+ # 获取当前版本号
291
+ current_version = get_current_version_from_tag(
292
+ project_dir: project_dir,
293
+ tag_prefixes: [tag_prefix]
294
+ )
490
295
 
296
+ # 根据 create_tag_type 计算 build_version
297
+ case create_tag_type
298
+ when Pindo::CreateTagType::NONE, Pindo::CreateTagType::RECREATE
299
+ # 不创建tag或重新创建当前tag,使用当前版本号
300
+ current_version
301
+ when Pindo::CreateTagType::NEW
302
+ # 创建新tag,需要检查HEAD是否已有tag
303
+ if head_has_version_tag?(project_dir: project_dir, tag_prefix: tag_prefix)
304
+ # HEAD已有tag,不需要创建新tag,使用当前版本号
305
+ Funlog.instance.fancyinfo_success("HEAD已存在tag,使用当前版本号: #{current_version}")
306
+ current_version
491
307
  else
492
- if local_branch_exists?(local_repo_dir: current_project_dir, branch: release_branch)
493
- Funlog.instance.fancyinfo_update("不存在#{release_branch}远程分支")
494
- Funlog.instance.fancyinfo_update("存在#{release_branch}本地分支")
495
- git!(%W(-C #{current_project_dir} checkout #{release_branch}))
496
- git!(%W(-C #{current_project_dir} checkout -b #{release_branch}_temp))
497
- git!(%W(-C #{current_project_dir} checkout #{coding_branch}))
498
- git!(%W(-C #{current_project_dir} branch -D #{release_branch}))
499
- else
500
- Funlog.instance.fancyinfo_update("不存在#{release_branch}远程分支")
501
- Funlog.instance.fancyinfo_update("不存在#{release_branch}本地分支")
308
+ # HEAD没有tag,根据 version_increase_type 计算新版本号
309
+ # 解析版本号
310
+ parts = current_version.split('.').map(&:to_i)
311
+ major = parts[0] || 0
312
+ minor = parts[1] || 0
313
+ patch = parts[2] || 0
314
+
315
+ case version_increase_type
316
+ when Pindo::VersionIncreaseType::MAIN
317
+ major += 1
318
+ minor = 0
319
+ patch = 0
320
+ when Pindo::VersionIncreaseType::MINI
321
+ minor += 1
322
+ patch = 0
323
+ when Pindo::VersionIncreaseType::PATCH
324
+ patch += 1
502
325
  end
503
326
 
504
- git!(%W(-C #{current_project_dir} checkout -b #{release_branch}))
505
- git!(%W(-C #{current_project_dir} push origin #{release_branch}))
506
- git!(%W(-C #{current_project_dir} branch --set-upstream-to=origin/#{release_branch} #{release_branch}))
327
+ new_version = "#{major}.#{minor}.#{patch}"
328
+ Funlog.instance.fancyinfo_success("新的版本号是: #{new_version}")
329
+ new_version
330
+ end
331
+ else
332
+ current_version
333
+ end
334
+ end
507
335
 
508
- Funlog.instance.fancyinfo_success("代码已经合并到#{release_branch}分支")
509
- # 获取 release_branch commit ID(处理空分支情况)
510
- begin
511
- release_branch_commit_id = git!(%W(-C #{current_project_dir} rev-parse #{release_branch})).strip
512
- rescue => e
513
- # 新创建的分支,commit ID 应该与 coding_branch 相同
514
- release_branch_commit_id = coding_branch_commit_id
336
+ # 检查HEAD是否已有版本tag
337
+ # @param project_dir [String] 项目目录
338
+ # @param tag_prefix [String] tag前缀
339
+ # @return [Boolean] HEAD是否有tag
340
+ def head_has_version_tag?(project_dir:, tag_prefix: 'v')
341
+ latest_tag = Pindo::GitHandler.get_latest_version_tag(
342
+ project_dir: project_dir,
343
+ tag_prefix: tag_prefix
344
+ )
345
+ return false if latest_tag.nil?
346
+
347
+ Pindo::GitHandler.is_tag_at_head?(git_root_dir: project_dir, tag_name: latest_tag)
348
+ end
349
+
350
+ # 创建并推送 Tag
351
+ # @param project_dir [String] 项目目录
352
+ # @param tag_name [String] tag 名称(如 v1.2.0)
353
+ # @param tag_type [Symbol] 创建类型 (:new, :recreate, :none)
354
+ # @return [String, nil] 创建的 tag 名称,或 nil(跳过时)
355
+ def create_and_push_tag(project_dir:, tag_name:, tag_type:)
356
+ raise ArgumentError, "项目目录不能为空" if project_dir.nil?
357
+ raise ArgumentError, "tag名称不能为空" if tag_name.nil? || tag_name.empty?
358
+
359
+ case tag_type
360
+ when Pindo::CreateTagType::NONE
361
+ Funlog.instance.fancyinfo_success("跳过创建 Tag")
362
+ return nil
363
+ when Pindo::CreateTagType::RECREATE
364
+ # 删除旧 tag(本地和远程)
365
+ if Pindo::GitHandler.remote_tag_exists?(local_repo_dir: project_dir, tag_name: tag_name)
366
+ Funlog.instance.fancyinfo_update("删除远程 Tag: #{tag_name}")
367
+ Pindo::GitHandler.git!(%W(-C #{project_dir} push origin :refs/tags/#{tag_name}))
368
+ end
369
+ if Pindo::GitHandler.local_tag_exists?(local_repo_dir: project_dir, tag_name: tag_name)
370
+ Funlog.instance.fancyinfo_update("删除本地 Tag: #{tag_name}")
371
+ Pindo::GitHandler.git!(%W(-C #{project_dir} tag -d #{tag_name}))
372
+ end
373
+ when Pindo::CreateTagType::NEW
374
+ local_exists = Pindo::GitHandler.local_tag_exists?(local_repo_dir: project_dir, tag_name: tag_name)
375
+ remote_exists = Pindo::GitHandler.remote_tag_exists?(local_repo_dir: project_dir, tag_name: tag_name)
376
+
377
+ # 如果 tag 在 HEAD 上,不需要重新创建
378
+ if local_exists && Pindo::GitHandler.is_tag_at_head?(git_root_dir: project_dir, tag_name: tag_name)
379
+ if !remote_exists
380
+ # 本地存在且在 HEAD,但远程不存在,推送到远程
381
+ Pindo::GitHandler.git!(%W(-C #{project_dir} push origin #{tag_name}))
382
+ Funlog.instance.fancyinfo_success("推送 Tag 到远程: #{tag_name}")
383
+ else
384
+ Funlog.instance.fancyinfo_success("Tag 已存在且在 HEAD: #{tag_name}")
515
385
  end
386
+ return tag_name
516
387
  end
517
388
 
518
- git!(%W(-C #{current_project_dir} checkout #{coding_branch}))
519
- if release_branch_commit_id && !release_branch_commit_id.eql?(coding_branch_commit_id)
520
- git!(%W(-C #{current_project_dir} merge #{release_branch}))
521
- Funlog.instance.fancyinfo_success("已将#{release_branch}合并到#{coding_branch}")
389
+ # tag 不在 HEAD 上,需要删除后重新创建
390
+ if remote_exists
391
+ Funlog.instance.fancyinfo_update("删除远程 Tag: #{tag_name}")
392
+ Pindo::GitHandler.git!(%W(-C #{project_dir} push origin :refs/tags/#{tag_name}))
522
393
  end
523
- git!(%W(-C #{current_project_dir} push origin #{coding_branch}))
524
- Funlog.instance.fancyinfo_success("已推送#{coding_branch}分支到远程")
525
- else
526
- Funlog.instance.fancyinfo_success("代码处于#{coding_branch}分支,无需合并")
394
+ if local_exists
395
+ Funlog.instance.fancyinfo_update("删除本地 Tag: #{tag_name}")
396
+ Pindo::GitHandler.git!(%W(-C #{project_dir} tag -d #{tag_name}))
397
+ end
398
+ # 继续创建新 tag
527
399
  end
400
+
401
+ # 创建并推送 tag
402
+ Pindo::GitHandler.git!(%W(-C #{project_dir} tag #{tag_name}))
403
+ Pindo::GitHandler.git!(%W(-C #{project_dir} push origin #{tag_name}))
404
+ Funlog.instance.fancyinfo_success("创建并推送 Tag: #{tag_name}")
405
+ tag_name
528
406
  end
407
+
529
408
  end
530
409
  end