Class: MGit::Repo::SyncHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/m-git/repo/sync_helper.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.delete_legacy_repo(repo_abs_path) ⇒ Object

删除失效的仓库目录

Parameters:

  • repo_abs_path (String)

    仓库完整路径



287
288
289
# File 'lib/m-git/repo/sync_helper.rb', line 287

def delete_legacy_repo(repo_abs_path)
  FileUtils.remove_dir(repo_abs_path, true) if File.exist?(repo_abs_path)
end

.local_bare_git_url(path) ⇒ String

生成本地裸库路径

Parameters:

  • repo_name (String)

    仓库名

Returns:

  • (String)

    本地裸库路径



275
276
277
278
279
280
281
# File 'lib/m-git/repo/sync_helper.rb', line 275

def local_bare_git_url(path)
  if File.exist?(path)
    return path
  else
    return nil
  end
end

.sync_branch(repo, light_repo) ⇒ string

同步分支

Parameters:

Returns:

  • (string)

    执行结果,成功返回nil,错误返回错误信息



182
183
184
185
186
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
# File 'lib/m-git/repo/sync_helper.rb', line 182

def sync_branch(repo, light_repo)

  current_branch = repo.status_checker.current_branch(strict_mode:false)
  local_branch_exist = repo.status_checker.local_branch_exist?(light_repo.branch)
  remote_branch_exist = repo.status_checker.remote_branch_exist?(light_repo.branch)
  is_dirty = repo.status_checker.status == Status::GIT_REPO_STATUS[:dirty]

  # 当前已在目标切换分支则不操作
  if current_branch == light_repo.branch
    return nil

    # 本地或远程存在目标分支则切换
  elsif local_branch_exist || remote_branch_exist || Utils.branch_exist_on_remote?(light_repo.branch, light_repo.url)

    # 本地无目标分支则先拉取
    if !local_branch_exist && !remote_branch_exist
      success, error = repo.execute_git_cmd('fetch', '')
      return error if !success
    end

    if !is_dirty
      success, output = repo.execute_git_cmd('checkout', light_repo.branch)
      return output if !success
    else
      return "本地有改动, 无法切换到分支\"#{light_repo.branch}\", 请处理后重试!"
    end

  else
    return "仓库分支\"#{light_repo.branch}\"不存在,请检查是否拼写错误!"
  end

end

.sync_change_ref(repo, light_repo) ⇒ Boolean

同步 change ref

Parameters:

Returns:

  • (Boolean)

    执行结果,成功返回nil,错误返回错误信息



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
# File 'lib/m-git/repo/sync_helper.rb', line 223

def sync_change_ref(repo, light_repo)
  current_branch = repo.status_checker.current_branch(strict_mode:false)
  local_branch_exist = repo.status_checker.local_branch_exist?(light_repo.branch)
  remote_branch_exist = repo.status_checker.remote_branch_exist?(light_repo.branch)
  is_dirty = repo.status_checker.status == Status::GIT_REPO_STATUS[:dirty]

  # 当前已在目标切换分支则不操作
  if current_branch == light_repo.branch
    return nil
    # 本地或远程存在目标分支则切换
  # elsif local_branch_exist || remote_branch_exist || Utils.branch_exist_on_remote?(light_repo.branch, light_repo.url)

  else
    # return "仓库change_ref \"#{light_repo.change_ref}\"不存在,请检查是否拼写错误!"
    # 本地无目标分支则先拉取
    if !local_branch_exist && !remote_branch_exist
      success, error = repo.execute_git_cmd('fetch origin', light_repo.change_ref)
      puts error
      return error if !success
    end

    if !is_dirty
      success, output = repo.execute_git_cmd('checkout', 'FETCH_HEAD')
      puts output
      return output if !success
    else
      return "本地有改动, 无法切换到\"#{light_repo.change_ref}\", 请处理后重试!"
    end
  end
end

.sync_commit_id(repo, light_repo) ⇒ string

同步commit id

Parameters:

Returns:

  • (string)

    执行结果,成功返回nil,错误返回错误信息



165
166
167
168
169
170
171
172
# File 'lib/m-git/repo/sync_helper.rb', line 165

def sync_commit_id(repo, light_repo)
  if !light_repo.commit_id.nil?
    success, output = repo.execute_git_cmd('checkout', light_repo.commit_id)
    return output if !success
  else
    return "\"#{repo.path}\"的仓库配置未指定commit id!"
  end
end

.sync_exist_repo(repo, light_repo) ⇒ string

同步已有仓库

Parameters:

Returns:

  • (string)

    执行结果,成功返回nil,错误返回错误信息



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/m-git/repo/sync_helper.rb', line 102

def sync_exist_repo(repo, light_repo)
  msg = ''

  if light_repo.lock
    # 同步锁定点
    error_message = sync_lock_point(repo, light_repo)
    msg += error_message + "\n" if !error_message.nil?
  end

  # 同步remote url
  error_message = sync_remote_url(repo, light_repo)
  msg += error_message + "\n" if !error_message.nil?

  return msg.length > 0 ? msg : nil
end

.sync_lock_point(repo, light_repo) ⇒ string

同步锁定点

Parameters:

Returns:

  • (string)

    执行结果,成功返回nil,错误返回错误信息



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/m-git/repo/sync_helper.rb', line 126

def sync_lock_point(repo, light_repo)
  if repo.status_checker.status == Status::GIT_REPO_STATUS[:dirty]
    return "#{light_repo.name}有本地改动,无法锁定,请自行清空修改后重试!"
  end

  if !light_repo.commit_id.nil?
    return sync_commit_id(repo, light_repo)
  elsif !light_repo.tag.nil?
    return sync_tag(repo, light_repo)
  elsif !light_repo.branch.nil?
    return sync_branch(repo, light_repo)
  elsif !light_repo.change_ref.nil?
    return sync_change_ref(repo, light_repo)
  end
end

.sync_new_repo(light_repo, root, link_git: true) ⇒ String, Repo

同步新仓库

Parameters:

  • repo (MGigClass::Repo)

    Repo对象

  • light_repo (Manifest::LightRepo)

    LightRepo对象

  • link_git (Boolean) (defaults to: true)

    下载新仓库的时候是否托管.git实体并在工作区创建其软链接

Returns:

  • (String, Repo)

    String:执行结果,成功返回nil,错误返回错误信息,Repo:成功返回nil,错误返回新生成的repo对象



20
21
22
23
24
25
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/m-git/repo/sync_helper.rb', line 20

def sync_new_repo(light_repo, root, link_git:true)
  def __sync_local_repo(light_repo, root, link_git:true)
    output, repo = nil, nil
    git_entity = File.join(light_repo.git_store_dir(root), '.git')
    # 先git clone -- local_git_repo,再软链git_entity,再checkout分支
    clone_url = "git clone -- #{git_entity} #{light_repo.abs_dest(root)}"
    Utils.execute_shell_cmd(clone_url) { |stdout, stderr, status|
      if status.success?
        repo = Repo.generate_strictly(root, light_repo)
        repo_git = File.join(repo.path, '.git')
        manage_git = MGitConfig.query_with_key(root, :managegit)
        if manage_git && link_git
          FileUtils.rm_rf(repo_git)
          Utils.link(git_entity, repo_git)
        end
        msg = ''
        # 如果从本地clone的话,remote url是指向本地的,需要更新
        error_message = sync_remote_url(repo, light_repo)
        msg += error_message + "\n" if !error_message.nil?
        # 本地仓库可能太旧,执行pull更新代码和新分支
        success, error_message = repo.execute_git_cmd('fetch', '')
        if !success && !error_message.nil? && error_message.length > 0
          msg += "由于存在本地仓库源,已从本地克隆,但代码更新失败,请自行fetch最新代码。原因:\n" + error_message + "\n"
        end

        # 同步锁定点
        error_message = sync_lock_point(repo, light_repo)
        msg += error_message if !error_message.nil?

        output = msg.length > 0 ? msg : nil
      else
        output = "同步仓库\"#{light_repo.name}\"时clone失败,如果远程仓库不存在,请在配置文件中删除该仓库并重试。原因:\n#{stderr}"
      end
    }
    [output, repo]
  end

  def __sync_remote_repo(light_repo, root, link_git:true)
    #
    output, repo = nil, nil
    clone_url = light_repo.clone_url(root)

    Utils.execute_shell_cmd(clone_url) { |stdout, stderr, status|
      if status.success?
        repo = Repo.generate_strictly(root, light_repo)
        begin
          # 查询配置看是否需要托管.git实体, 根据mgit config -s managegit false配置。
          # 若是,那么.git实体会放在.mgit/source-git/文件夹下
          manage_git = MGitConfig.query_with_key(root, :managegit)
          Utils.link_git(repo.path, light_repo.git_store_dir(root)) if manage_git && link_git
        rescue Error => _
        end
        msg = ''
        # 同步锁定点
        error_message = sync_lock_point(repo, light_repo)
        msg += error_message if !error_message.nil?

        output = msg.length > 0 ? msg : nil
      else
        output = "同步仓库\"#{light_repo.name}\"时clone失败,如果远程仓库不存在,请在配置文件中删除该仓库并重试。原因:\n#{stderr}"
      end
    }

    [output, repo]
  end

  git_entity = File.join(light_repo.git_store_dir(root), '.git')
  if File.exist?(git_entity)
    __sync_local_repo(light_repo, root, link_git: link_git)
  else
    __sync_remote_repo(light_repo, root, link_git: link_git)
  end
end

.sync_remote_url(repo, light_repo) ⇒ Boolean

同步remote url

Parameters:

Returns:

  • (Boolean)

    执行结果,成功返回nil,错误返回错误信息



262
263
264
265
266
267
# File 'lib/m-git/repo/sync_helper.rb', line 262

def sync_remote_url(repo, light_repo)
  return nil if light_repo.url.nil?

  success, output = repo.execute_git_cmd('remote', "set-url origin #{light_repo.url}")
  return success ? nil : output
end

.sync_tag(repo, light_repo) ⇒ string

同步tag

Parameters:

Returns:

  • (string)

    执行结果,成功返回nil,错误返回错误信息



149
150
151
152
153
154
155
156
# File 'lib/m-git/repo/sync_helper.rb', line 149

def sync_tag(repo, light_repo)
  if !light_repo.tag.nil?
    success, output = repo.execute_git_cmd('checkout', light_repo.tag)
    return output if !success
  else
    return "\"#{repo.path}\"的仓库配置未指定tag!"
  end
end

Instance Method Details

#__sync_local_repo(light_repo, root, link_git: true) ⇒ Object



21
22
23
24
25
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
# File 'lib/m-git/repo/sync_helper.rb', line 21

def __sync_local_repo(light_repo, root, link_git:true)
  output, repo = nil, nil
  git_entity = File.join(light_repo.git_store_dir(root), '.git')
  # 先git clone -- local_git_repo,再软链git_entity,再checkout分支
  clone_url = "git clone -- #{git_entity} #{light_repo.abs_dest(root)}"
  Utils.execute_shell_cmd(clone_url) { |stdout, stderr, status|
    if status.success?
      repo = Repo.generate_strictly(root, light_repo)
      repo_git = File.join(repo.path, '.git')
      manage_git = MGitConfig.query_with_key(root, :managegit)
      if manage_git && link_git
        FileUtils.rm_rf(repo_git)
        Utils.link(git_entity, repo_git)
      end
      msg = ''
      # 如果从本地clone的话,remote url是指向本地的,需要更新
      error_message = sync_remote_url(repo, light_repo)
      msg += error_message + "\n" if !error_message.nil?
      # 本地仓库可能太旧,执行pull更新代码和新分支
      success, error_message = repo.execute_git_cmd('fetch', '')
      if !success && !error_message.nil? && error_message.length > 0
        msg += "由于存在本地仓库源,已从本地克隆,但代码更新失败,请自行fetch最新代码。原因:\n" + error_message + "\n"
      end

      # 同步锁定点
      error_message = sync_lock_point(repo, light_repo)
      msg += error_message if !error_message.nil?

      output = msg.length > 0 ? msg : nil
    else
      output = "同步仓库\"#{light_repo.name}\"时clone失败,如果远程仓库不存在,请在配置文件中删除该仓库并重试。原因:\n#{stderr}"
    end
  }
  [output, repo]
end

#__sync_remote_repo(light_repo, root, link_git: true) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/m-git/repo/sync_helper.rb', line 57

def __sync_remote_repo(light_repo, root, link_git:true)
  #
  output, repo = nil, nil
  clone_url = light_repo.clone_url(root)

  Utils.execute_shell_cmd(clone_url) { |stdout, stderr, status|
    if status.success?
      repo = Repo.generate_strictly(root, light_repo)
      begin
        # 查询配置看是否需要托管.git实体, 根据mgit config -s managegit false配置。
        # 若是,那么.git实体会放在.mgit/source-git/文件夹下
        manage_git = MGitConfig.query_with_key(root, :managegit)
        Utils.link_git(repo.path, light_repo.git_store_dir(root)) if manage_git && link_git
      rescue Error => _
      end
      msg = ''
      # 同步锁定点
      error_message = sync_lock_point(repo, light_repo)
      msg += error_message if !error_message.nil?

      output = msg.length > 0 ? msg : nil
    else
      output = "同步仓库\"#{light_repo.name}\"时clone失败,如果远程仓库不存在,请在配置文件中删除该仓库并重试。原因:\n#{stderr}"
    end
  }

  [output, repo]
end