Class: Pindo::GitRepoHelper

Inherits:
Object
  • Object
show all
Includes:
Githelper, Singleton
Defined in:
lib/pindo/module/build/git_repo_helper.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Githelper

#add_branch, #add_tag, #add_tag_with_check, #clone_clang_repo, #clone_devclang_repo, #clone_pindo_common_config_repo, #clone_pindo_env_config_repo, #clong_buildconfig_repo, #get_repo_base_name, #getcode_to_dir, #git_addpush_repo, #git_latest_commit_id, #git_root_directory, #is_git_directory?, #local_branch_exists?, #local_tag_exists?, #prepare_gitenv, #process_need_add_files, #remote_branch_exists?, #remote_tag_exists?, #remove_branch, #remove_tag

Methods included from Executable

capture_command, #executable, execute_command, which, which!

Instance Attribute Details

#temp_tag_decisionObject

Returns the value of attribute temp_tag_decision.



12
13
14
# File 'lib/pindo/module/build/git_repo_helper.rb', line 12

def temp_tag_decision
  @temp_tag_decision
end

Class Method Details

.share_instanceObject



15
16
17
# File 'lib/pindo/module/build/git_repo_helper.rb', line 15

def share_instance
  instance
end

Instance Method Details

#add_git_cliffconfig(project_path) ⇒ Object

添加 git-cliff 配置

Parameters:

  • project_path (String)

    项目路径



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/pindo/module/build/git_repo_helper.rb', line 142

def add_git_cliffconfig(project_path)
  temp_dir = Dir.pwd
  Funlog.instance.fancyinfo_start("添加日志变更git-cliff配置...")
  if is_git_directory?(local_repo_dir: project_path)
    current_git_root_path = git_root_directory(local_repo_dir: project_path)
    Dir.chdir(current_git_root_path)
    pindo_common_dir = clone_pindo_common_config_repo(force_delete:false)
    if File.exist?(File.join(pindo_common_dir, 'cliff.toml'))
      FileUtils.cp_r(File.join(pindo_common_dir, 'cliff.toml'), File.join(current_git_root_path, 'cliff.toml'))
    end
    Funlog.instance.fancyinfo_update("仓库添加git-cliff配置")
    write_gitignore(current_git_root_path)
    Funlog.instance.fancyinfo_update("仓库添加.gitignore")
    Dir.chdir(current_git_root_path)
    current_branch = git!(%W(-C #{current_git_root_path} rev-parse --abbrev-ref HEAD)).strip
    git!(%W(-C #{current_git_root_path} add cliff.toml))
    git!(%W(-C #{current_git_root_path} add .gitignore))
    commit_message = "docs: 添加日志变更配置".encode('UTF-8')
    git!(%W(-C #{current_git_root_path} commit -m #{commit_message}))
    git!(%W(-C #{current_git_root_path} push origin #{current_branch}))
  else
    Funlog.instance.fancyinfo_error("当前目录不是git仓库,请在git仓库根目录下执行此命令")
    Dir.chdir(temp_dir)
    return
  end
  Funlog.instance.fancyinfo_success("日志变更git-cliff配置完成!")
  Dir.chdir(temp_dir)
end

#check_check_and_install_cliff(project_path) ⇒ Object

检查并安装 git-cliff

Parameters:

  • project_path (String)

    项目路径



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/pindo/module/build/git_repo_helper.rb', line 68

def check_check_and_install_cliff(project_path)
  if is_git_directory?(local_repo_dir: project_path)
    current_git_root_path = git_root_directory(local_repo_dir: project_path)
    unless File.exist?(File.join(current_git_root_path, 'cliff.toml'))
      add_git_cliffconfig(current_git_root_path)
    end
  end

  begin
    if !system('which git-cliff > /dev/null 2>&1')
      puts "安装git-cliff..."
      install_gitcliff()
    end
  rescue
    Funlog.instance.fancyinfo_error("安装git-cliff出现错误")
    return
  end
end

#check_is_need_add_tag?(project_path, auto_mode: false) ⇒ Array<Boolean, Array>

检查是否需要添加 Git 标签

Parameters:

  • project_path (String)

    项目路径

  • auto_mode (Boolean) (defaults to: false)

    是否自动模式

Returns:

  • (Array<Boolean, Array>)
    是否需要添加tag, tag参数


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/pindo/module/build/git_repo_helper.rb', line 187

def check_is_need_add_tag?(project_path, auto_mode: false)
  tag_action_parms = nil
  is_need_add_tag = false

  if is_git_directory?(local_repo_dir: project_path)
    current_git_root_path = git_root_directory(local_repo_dir: project_path)
    latest_tag = get_latest_version_tag(project_dir: current_git_root_path)

    # 检查是否需要打 tag:
    # 1. 最新 tag 不在 HEAD 上,或者
    # 2. 仓库有未提交的更改
    tag_not_at_head = !is_tag_at_head?(git_root_dir: current_git_root_path, tag_name: latest_tag)
    has_uncommitted = has_uncommitted_changes?(git_root_dir: current_git_root_path)

    if tag_not_at_head || has_uncommitted
      # 提示用户需要打 tag 的原因
      if has_uncommitted && !tag_not_at_head
        puts "\n注意:仓库有未提交的更改,建议提交后再打 Tag"
      end
      # 检查环境变量
      env_tag_decision = ENV['PINDO_TAG_DECISION']
      if env_tag_decision && !env_tag_decision.empty?
        case env_tag_decision.downcase
        when 'new', 'new_tag', '1'
          puts "\n环境变量指定:新增版本号,打新Tag"
          puts
          tag_action_parms = []
          is_need_add_tag = true
          # 保存到缓存
          context = PindoContext.instance
          decision = {
            tag_action_parms: tag_action_parms,
            is_need_add_tag: is_need_add_tag,
            action: :new_tag,
            description: "新增版本号,打新Tag"
          }
          context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
          return is_need_add_tag, tag_action_parms
        when 'retag', 'recreate', '2'
          puts "\n环境变量指定:将上次的Tag删除重新打Tag"
          puts
          tag_action_parms = ['--retag']
          is_need_add_tag = true
          # 保存到缓存
          context = PindoContext.instance
          decision = {
            tag_action_parms: tag_action_parms,
            is_need_add_tag: is_need_add_tag,
            action: :recreate_tag,
            description: "将上次的Tag删除重新打Tag"
          }
          context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
          return is_need_add_tag, tag_action_parms
        when 'skip', 'no', 'none', '3'
          puts "\n环境变量指定:不需要Tag继续编译"
          puts
          tag_action_parms = nil
          is_need_add_tag = false
          # 保存到缓存
          context = PindoContext.instance
          decision = {
            tag_action_parms: tag_action_parms,
            is_need_add_tag: is_need_add_tag,
            action: :continue_without_tag,
            description: "不需要Tag继续编译且上传"
          }
          context.set_selection(PindoContext::SelectionKey::TAG_DECISION, decision)
          return is_need_add_tag, tag_action_parms
        when 'exit', 'quit', '4'
          Funlog.instance.fancyinfo_error("环境变量指定:终止退出编译!")
          return false, nil
        end
      end

      if auto_mode
        # 在自动化模式或没有交互式终端时,默认选择新增版本号打新Tag
        puts "检测到当前代码没有打Tag,在自动模式下将自动新增版本号并打新Tag"
        tag_action_parms = []
        is_need_add_tag = true
      else
        # 检查是否已有用户选择
        context = PindoContext.instance
        # 优先从持久化缓存读取,如果没有则从内存临时缓存读取
        cached_decision = context.get_selection(PindoContext::SelectionKey::TAG_DECISION)

        # 只有当持久化缓存中确实不存在该键时,才从临时缓存读取
        if cached_decision.nil? && !context.has_selection?(PindoContext::SelectionKey::TAG_DECISION)
          # 从 GitRepoHelper 的临时缓存读取
          cached_decision = self.temp_tag_decision
        end

        if cached_decision && cached_decision.is_a?(Hash)
          # 使用之前的选择
          puts "\n使用之前的选择:#{cached_decision[:description]}"
          tag_action_parms = cached_decision[:tag_action_parms]
          is_need_add_tag = cached_decision[:is_need_add_tag]

          # 如果是退出选择,则返回
          if cached_decision[:action] == :exit
            Funlog.instance.fancyinfo_error("终止退出编译!")
            return false, nil
          end
        else
          # 第一次询问
          cli = HighLine.new
          selected_action = nil
          selected_description = nil

          menu_options = {
            "新增版本号,打新Tag" => -> {
              tag_action_parms = []
              selected_action = :new_tag
              selected_description = "新增版本号,打新Tag"
              is_need_add_tag = true
              :new_tag
            },
            "将上次的Tag删除重新打Tag" => -> {
              tag_action_parms = []
              tag_action_parms << "--retag"
              selected_action = :recreate_tag
              selected_description = "将上次的Tag删除重新打Tag"
              is_need_add_tag = true
              :recreate_tag
            },
            "不需要Tag继续编译且上传,手动修改上传备注" => -> {
              puts ""
              tag_action_parms = nil
              selected_action = :continue_without_tag
              selected_description = "不需要Tag继续编译且上传"
              is_need_add_tag = false
              :continue_without_tag
            },
            "终止退出编译" => -> {
              tag_action_parms = nil
              selected_action = :exit
              selected_description = "终止退出编译"
              is_need_add_tag = false
              Funlog.instance.fancyinfo_error("终止退出编译!")
              :exit
            }
          }

          result = cli.choose do |menu|
            menu.header = "当前代码并没有打Tag,上传的Changelog需要Tag"
            menu.prompt = "请选中打Tag的方式, 请输入选项(1/2/3...):"
            menu_options.each do |option, action|
              menu.choice(option) { action.call }
            end
          end

          # 如果选择退出,直接返回
          return false, nil if selected_action == :exit

          # 保存用户选择
          # 只有选择"新增版本号,打新Tag"时才保存到持久化缓存
          if selected_action == :new_tag
            # 保存到持久化缓存(文件)
            context.set_selection(PindoContext::SelectionKey::TAG_DECISION, {
              action: selected_action,
              description: selected_description,
              tag_action_parms: tag_action_parms,
              is_need_add_tag: is_need_add_tag
            })
            # 清除临时缓存
            self.temp_tag_decision = nil
          else
            # 不清空持久化缓存(避免将 nil 写入文件)
            # 只使用临时缓存(仅在内存中,不会写入文件)
            self.temp_tag_decision = {
              action: selected_action,
              description: selected_description,
              tag_action_parms: tag_action_parms,
              is_need_add_tag: is_need_add_tag
            }
          end
        end
      end
    end
  end

  return [is_need_add_tag, tag_action_parms]
end

#create_and_push_tag(project_dir:, mode: 'minor', force_retag: false, custom_tag: nil, release_branch: 'master') ⇒ Object

主入口函数 - 创建并推送 Git 标签

Parameters:

  • project_dir (String)

    项目目录

  • mode (String) (defaults to: 'minor')

    版本号增加模式 (major/minor/patch)

  • force_retag (Boolean) (defaults to: false)

    是否强制重新打tag

  • custom_tag (String) (defaults to: nil)

    自定义tag版本号

  • release_branch (String) (defaults to: 'master')

    发布分支名称,默认为 ‘master’



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/pindo/module/build/git_repo_helper.rb', line 26

def create_and_push_tag(project_dir:, mode: 'minor', force_retag: false, custom_tag: nil, release_branch: 'master')
  puts project_dir

  # 1. 验证 Git 仓库
  unless is_git_directory?(local_repo_dir: project_dir)
    raise Informative, "当前目录不是git仓库,请在git仓库目录下执行此命令"
  end

  # 获取git仓库根目录
  root_dir = git_root_directory(local_repo_dir: project_dir)
  if root_dir.nil?
    raise Informative, "无法获取git仓库根目录"
  end

  # 2. 处理未提交的文件
  process_need_add_files(project_dir: root_dir)

  # 3. 获取当前分支
  current_branch = git!(%W(-C #{root_dir} rev-parse --abbrev-ref HEAD)).strip
  coding_branch = current_branch

  # 4. 合并到发布分支
  Funlog.instance.fancyinfo_start("开始合并到#{release_branch}分支")
  merge_to_release_branch(
    project_dir: root_dir,
    release_branch: release_branch,
    coding_branch: coding_branch
  )

  # 5. 添加版本标签并返回 tag 名称
  new_tag = add_release_tag(
    project_dir: root_dir,
    increment_mode: mode,
    force_retag: force_retag,
    custom_tag: custom_tag
  )

  new_tag
end

#install_gitcliffObject

安装 git-cliff



172
173
174
175
176
177
178
179
180
181
# File 'lib/pindo/module/build/git_repo_helper.rb', line 172

def install_gitcliff
  puts "\n检查git-cliff命令是否安装"
  begin
    if !system('which git-cliff > /dev/null 2>&1')
      system('bash -c "$(curl -fsSL https://gitee.com/goodtools/env/raw/master/gitcliff_install.sh)"')
    end
  rescue
    Funlog.instance.fancyinfo_error("安装git-cliff出现错误")
  end
end

#write_gitignore(git_root_dir) ⇒ Object

写入 .gitignore 文件

Parameters:

  • git_root_dir (String)

    Git 根目录



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/pindo/module/build/git_repo_helper.rb', line 89

def write_gitignore(git_root_dir)
  gitignore_path = File.join(git_root_dir, '.gitignore')

  # 定义要添加的gitignore规则数组
  ignore_rules = [
    'Temp',
    'Logs',
    'build_ios.log',
    'feishu.json',
    'CHANGELOG.md',
    'GoodPlatform/iOS/*',
    'GoodPlatform/Android/*',
    'GoodPlatform/BaseiOS/Unity/*',
    'GoodPlatform/BaseiOS/Pods/',
    'GoodPlatform/BaseiOS/build',
    'GoodPlatform/BaseiOS/config.json',
    'GoodPlatform/BaseiOS/Podfile.lock',
    'GoodPlatform/BaseAndroid/Unity/*',
    'GoodPlatform/BaseAndroid/build',
    'GoodPlatform/WebGL',
    'config.json',
    'Assets/Packages',
    'Assets/WebGLTemplates.meta',
    'Assets/WebGLTemplates/',
    'Packages/packages-lock.json'
  ]

  # 读取现有的gitignore内容
  existing_lines = []
  if File.exist?(gitignore_path)
    existing_lines = File.readlines(gitignore_path).map(&:strip)
  end

  # 过滤出需要添加的规则(不存在的)
  rules_to_add = ignore_rules.reject { |rule| existing_lines.include?(rule) }

  # 如果有需要添加的规则,则添加
  unless rules_to_add.empty?
    File.open(gitignore_path, 'a') do |f|
      # 检查是否已有Pindo标记,如果没有则添加
      pindo_marker = '# Added by Pindo (pindo_common_ignore_1.0.0)'
      f.puts("\n#{pindo_marker}") unless existing_lines.include?(pindo_marker.strip)

      # 添加每条新规则
      rules_to_add.each do |rule|
        f.puts(rule)
      end
    end
  end
end