Class: MGit::Sync

Inherits:
BaseCommand show all
Defined in:
lib/m-git/command/sync.rb

Overview

可通过 mgit sync –pull 进行同步后pull到最新节点

Constant Summary collapse

OPT_LIST =
{
  :new_repo    =>  '--new-repo',
  :new_repo_s  =>  '-n',
  :all         =>  '--all',
  :all_s       =>  '-a',
  :clone       =>  '--clone',
  :clone_s     =>  '-c',
  :pull        =>  '--pull',
  :pull_s      =>  '-p',
  :url         =>  '--url',
  :url_s       =>  '-u',
}.freeze

Constants inherited from BaseCommand

BaseCommand::HIGH_PRIORITY_OPT_LIST, BaseCommand::SELECTABLE_OPT_LIST

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseCommand

#all_repos, cmd, #exec_light_repos, #generate_config_repo, inherited, #initialize, #locked_repos, #run

Constructor Details

This class inherits a constructor from MGit::BaseCommand

Class Method Details

.descriptionObject



317
318
319
# File 'lib/m-git/command/sync.rb', line 317

def self.description
  "根据配置表(从远端或本地)同步仓库到工作区,包括被锁定仓库,已经在工作的不作处理(默认不执行pull)。"
end

.usageObject



321
322
323
# File 'lib/m-git/command/sync.rb', line 321

def self.usage
  "mgit sync [-a|-n|-c] [<repo>...] [-p] [-o] [-h]"
end

Instance Method Details

#check_valid_repos(repo_names) ⇒ Object



291
292
293
294
295
296
297
298
299
300
# File 'lib/m-git/command/sync.rb', line 291

def check_valid_repos(repo_names)
  specified_repos = repo_names.map { |name| name.downcase }
  all_valid_repos = Workspace.config.light_repos.map { |light_repo| light_repo.name.downcase }
  error_repo_names = specified_repos - all_valid_repos
  valid_repo_names = specified_repos - error_repo_names
  valid_repos = Workspace.config.light_repos.select { |light_repo|
    valid_repo_names.include?(light_repo.name.downcase)
  }
  [valid_repos, error_repo_names]
end

#enable_short_basic_optionObject



313
314
315
# File 'lib/m-git/command/sync.rb', line 313

def enable_short_basic_option
  true
end

#execute(argv) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
# File 'lib/m-git/command/sync.rb', line 70

def execute(argv)
  Output.puts_start_cmd

  if argv.opt_list.did_set_opt?(OPT_LIST[:all])
    setup_all_sync_reops(argv)
  elsif argv.opt_list.did_set_opt?(OPT_LIST[:new_repo])
    setup_new_reops
  elsif argv.opt_list.did_set_opt?(OPT_LIST[:url])
    setup_config_url_repos
  elsif argv.opt_list.did_set_opt?(OPT_LIST[:clone])
    return if !setup_download_reops(argv.opt(OPT_LIST[:clone]).value)
  elsif argv.git_opts.length > 0
    return if !setup_specified_repos(argv)
  else
    setup_normal_reops(argv)
  end

  if (@sync_repos.length + @update_repos.length + @download_repos.length) == 0
    Output.puts_success_message("没有仓库需要同步!")
    return
  end

  error_repos = {}
  if @sync_repos.length > 0
    Workspace.concurrent_enumerate_with_progress_bar(@sync_repos, "正在同步(锁定)以上仓库...") { |light_repo|
      repo = Repo.generate_strictly(Workspace.root, light_repo)
      error_message = Repo::SyncHelper.sync_exist_repo(repo, light_repo)
      if !error_message.nil?
        Lock.mutex_exec { error_repos[light_repo.name] = error_message }
      end
    }
  end

  if @update_repos.length > 0
    Workspace.concurrent_enumerate_with_progress_bar(@update_repos, "正在更新以上仓库...") { |light_repo|
      repo = Repo.generate_strictly(Workspace.root, light_repo)
      success, output = repo.execute_git_cmd('pull', '')
      if !success
        Lock.mutex_exec { error_repos[light_repo.name] = output }
      end
    }
  end

  if @download_repos.length > 0
    Workspace.sync_new_repos(@download_repos)
  end

  if error_repos.length > 0
    Workspace.show_error(error_repos)
  else
    Output.puts_succeed_cmd(argv.absolute_cmd)
  end
end

#optionsObject




40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/m-git/command/sync.rb', line 40

def options
  return [
      ARGV::Opt.new(OPT_LIST[:new_repo],
                    short_key:OPT_LIST[:new_repo_s],
                    info:"下载配置表中指定被mgit管理,但本地不存在的仓库,已有仓库不做任何处理,使用:mgit sync -n。",
                    type: :boolean),
      ARGV::Opt.new(OPT_LIST[:all],
                    short_key:OPT_LIST[:all_s],
                    info:'对所有(包含不被mgit管理的)仓库操作:1.如果本地缺失则下载。2.如果本地存在且被锁定则同步到锁定状态。注意,如果需要下载代码,需要配置仓库URL,否则跳过,使用:mgit sync -a。',
                    type: :boolean),
      ARGV::Opt.new(OPT_LIST[:clone], short_key:OPT_LIST[:clone_s], info:'下载一组仓库(包含不被mgit管理的仓库),如: mgit sync -c repo1 repo2。'),
      ARGV::Opt.new(OPT_LIST[:pull],
                    short_key:OPT_LIST[:pull_s],
                    info:'同步本地仓库后执行pull操作更新,配合其他指令使用,如: mgit sync -a -p。',
                    type: :boolean),
      ARGV::Opt.new(OPT_LIST[:url],
                    short_key:OPT_LIST[:url_s],
                    info:'校验并同步URL与配置不一致的仓库,如: mgit sync -u。',
                    type: :boolean)
  ].concat(super)
end

#parse_repo_name(argv) ⇒ Object



303
304
305
306
307
308
309
310
311
# File 'lib/m-git/command/sync.rb', line 303

def parse_repo_name(argv)
  return if argv.git_opts.nil?

  repos = argv.git_opts.split(' ')
  extra_opts = repos.select { |e| argv.is_option?(e) }
  Foundation.help!("输入非法参数:#{extra_opts.join('')}。请通过\"mgit #{argv.cmd} --help\"查看用法。") if extra_opts.length > 0
  Foundation.help!("未输入查询仓库名!请使用这种形式查询:mgit info repo1 repo2 ...") if repos.length == 0
  repos.map { |e| e.downcase }
end

#post_execObject



33
34
35
36
37
# File 'lib/m-git/command/sync.rb', line 33

def post_exec
  # 打点结束
  duration = MGit::DurationRecorder.end
  MGit::Loger.info("~~~ #{@argv.absolute_cmd}, 耗时:#{duration} s ~~~")
end

#pre_execObject

— 覆写前后hook,不需要预设操作 —



24
25
26
27
28
29
30
31
# File 'lib/m-git/command/sync.rb', line 24

def pre_exec
  MGit::DurationRecorder.start
  Workspace.setup_multi_repo_root
  # 配置log
  MGit::Loger.config(Workspace.root)
  MGit::Loger.info("~~~ #{@argv.absolute_cmd} ~~~")
  Workspace.setup_config
end

#prepare_repo_categoryObject



124
125
126
127
128
# File 'lib/m-git/command/sync.rb', line 124

def prepare_repo_category
  @sync_repos = []
  @update_repos = []
  @download_repos = []
end

#setup_all_sync_reops(argv) ⇒ Object

mgit sync –all [–pull] 下载仓库:NE|U,同步仓库:E|L,更新仓库: E|NL|U(可选)



211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/m-git/command/sync.rb', line 211

def setup_all_sync_reops(argv)
  prepare_repo_category
  Workspace.config.light_repos.each { |light_repo|
    repo_exist = Dir.exist?(light_repo.abs_dest(Workspace.root))
    if !repo_exist && !light_repo.url.nil?
      @download_repos.push(light_repo)
    elsif repo_exist && light_repo.lock
      @sync_repos.push(light_repo)
    elsif repo_exist && !light_repo.url.nil? && argv.opt_list.did_set_opt?(OPT_LIST[:pull])
      @update_repos.push(light_repo)
    end
  }
end

#setup_config_url_reposObject

mgit sync -u 同步仓库:E | url不一致



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
# File 'lib/m-git/command/sync.rb', line 261

def setup_config_url_repos()
  prepare_repo_category

  warning_repos = []
  missing_repos = []
  Workspace.config.light_repos.each { |light_repo|
    if !light_repo.mgit_excluded
      repo, _ = Repo.generate_softly(Workspace.root, light_repo)
      if !repo.nil?
        original_url = repo.status_checker.default_url
        target_url = light_repo.url
        warning_repos.push(light_repo) if !Utils.url_consist?(original_url, target_url)
      else
        missing_repos.push(light_repo)
      end
    end
  }

  Output.puts_remind_block(missing_repos.map { |repo| repo.name }, "以上仓库本地缺失,无法校验URL,请执行\"mgit sync -n\"重新下载后重试!") if missing_repos.length > 0

  if warning_repos.length > 0
    if Output.continue_with_interact_repos?(warning_repos.map { |repo| repo.name }, "以上仓库的当前URL(origin)和配置表指定URL不一致,建议\n     1. 执行\"mgit delete repo1 repo2...\"删除仓库.\n     2. 执行\"mgit sync -n\"重新下载。\n    继续强制设置可能导致仓库出错,是否继续?")
      @sync_repos = warning_repos
    else
      Output.puts_cancel_message
      exit
    end
  end
end

#setup_download_reops(repo_names) ⇒ Object

mgit sync –clone repo1 repo2 … 下载仓库:NE|U(指定)



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
# File 'lib/m-git/command/sync.rb', line 227

def setup_download_reops(repo_names)
  prepare_repo_category
  existing_repos = []
  valid_repos, error_repo_names = check_valid_repos(repo_names)

  valid_repos.each { |light_repo|
    repo_exist = Dir.exist?(light_repo.abs_dest(Workspace.root))
    if !repo_exist
      if !light_repo.url.nil?
        @download_repos.push(light_repo)
      else
        error_repo_names.push(light_repo.name)
      end
    else
      error_repo_names.push(light_repo.name) if light_repo.url.nil?
      existing_repos.push(light_repo.name)
    end
  }

  should_continue = true
  error_repos = []
  error_repos.push(['配置表中未定义(或未指定"remote-path")', error_repo_names]) if error_repo_names.length > 0
  error_repos.push(['本地已经存在', existing_repos]) if existing_repos.length > 0
  Output.interact_with_multi_selection_combined_repos(error_repos, "以上仓库状态异常", ['a: 跳过并继续', 'b: 终止']) { |input|
    if input == 'b'
      Output.puts_cancel_message
      should_continue = false
    end
  } if error_repos.length > 0
  return should_continue
end

#setup_new_reopsObject

mgit sync –new 下载仓库:M|NE|U



199
200
201
202
203
204
205
206
207
# File 'lib/m-git/command/sync.rb', line 199

def setup_new_reops
  prepare_repo_category
  Workspace.config.light_repos.each { |light_repo|
    if !light_repo.mgit_excluded
      repo_exist = Dir.exist?(light_repo.abs_dest(Workspace.root))
      @download_repos.push(light_repo) if !repo_exist && !light_repo.url.nil?
    end
  }
end

#setup_normal_reops(argv) ⇒ Object

mgit sync [–pull] 下载仓库:M|NE|U, 同步仓库:M|E|L, 更新仓库:M|E|U(可选)



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/m-git/command/sync.rb', line 178

def setup_normal_reops(argv)
  prepare_repo_category
  should_pull = argv.opt_list.did_set_opt?(OPT_LIST[:pull])
  Workspace.config.light_repos.each { |light_repo|
    if !light_repo.mgit_excluded
      repo_exist = Dir.exist?(light_repo.abs_dest(Workspace.root))
      if !repo_exist && !light_repo.url.nil?
        @download_repos.push(light_repo)
      elsif repo_exist && light_repo.lock
        @sync_repos.push(light_repo)
      end

      if repo_exist && should_pull && !light_repo.url.nil?
          @update_repos.push(light_repo)
      end
    end
  }
end

#setup_specified_repos(argv) ⇒ Object

mgit sync repo1 repo2 … [–pull] 针对一组指定仓库进行:下载仓库:NE|U,同步仓库:E|L,更新仓库: E|U(可选)



137
138
139
140
141
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
170
171
172
173
174
# File 'lib/m-git/command/sync.rb', line 137

def setup_specified_repos(argv)
  prepare_repo_category
  should_pull = argv.opt_list.did_set_opt?(OPT_LIST[:pull])
  valid_repos, error_repo_names = check_valid_repos(parse_repo_name(argv))
  valid_repos.each { |light_repo|
    repo_exist = Dir.exist?(light_repo.abs_dest(Workspace.root))
    if !repo_exist
      if !light_repo.url.nil?
        @download_repos.push(light_repo)
      else
        error_repo_names.push(light_repo.name)
      end
    else
      if light_repo.lock
        @sync_repos.push(light_repo)
      end

      if should_pull
        if !light_repo.url.nil?
          @update_repos.push(light_repo)
        else
          error_repo_names.push(light_repo.name)
        end
      end
    end
  }

  should_continue = true
  error_repos = []
  error_repos.push(['配置表中未定义(或未指定"remote-path")', error_repo_names]) if error_repo_names.length > 0
  Output.interact_with_multi_selection_combined_repos(error_repos, "以上仓库状态异常", ['a: 跳过并继续', 'b: 终止']) { |input|
    if input == 'b'
      Output.puts_cancel_message
      should_continue = false
    end
  } if error_repos.length > 0
  return should_continue
end

#validate(argv) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/m-git/command/sync.rb', line 62

def validate(argv)
  opt_all = argv.opt(OPT_LIST[:all])
  opt_clone = argv.opt(OPT_LIST[:clone])
  opt_new = argv.opt(OPT_LIST[:new_repo])
  invalid = [opt_all, opt_clone, opt_new].select { |e| !e.nil? }.length > 1
  Foundation.help!("请勿同时指定[#{OPT_LIST[:all]}|#{OPT_LIST[:all_s]}],[#{OPT_LIST[:clone]}|#{OPT_LIST[:clone_s]}]和[#{OPT_LIST[:new_repo]}|#{OPT_LIST[:new_repo_s]}]。") if invalid
end