Class: MGit::OpenApi

Inherits:
Object
  • Object
show all
Defined in:
lib/m-git/open_api.rb,
lib/m-git/open_api/script_download_info.rb

Overview

— Ruby环境调用 —

Defined Under Namespace

Modules: DownloadResult Classes: ScriptDownloadInfo

Class Method Summary collapse

Class Method Details

.check_extra_repos(path_dict) ⇒ Hash

检查给定仓库是否工作区脏,工作区的.git是否是软链接

Parameters:

  • path_dict (Hash)

    待校验的冗余仓库地址:{ “name”: “abs_path” }

Returns:

  • (Hash)

    冗余仓库状态信息:{ “name”: { “clean”: true, “git_linked”: true , “error”: “error_msg”} }

    • “clean”: 为true,表示工作区干净,否则脏。

    • “git_linked”: 为true,表示.git实体放在.mgit/source-git下,工作区.git仅为软链接,否则为实体。

    • “error”: 如果校验成功则无该字段,否则校验失败,值为错误信息。注意,若出错则无“clean”和“git_linked”字段。



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/m-git/open_api.rb', line 267

def check_extra_repos(path_dict)

  # 空值校验
  error = self.validate_argv(__method__, {"path_dict" => path_dict})
  return {} if !error.nil?

  output = {}
  path_dict.each { |name, path|
    output[name] = {}
    # 生成仓库对象
    if Repo.is_git_repo?(path)
      repo = Repo.new(name, path)
      output[name]['clean'] = repo.status_checker.status == Repo::Status::GIT_REPO_STATUS[:clean]
      output[name]['git_linked'] = File.symlink?(File.join(path, '.git'))
    else
      output[name]['error'] = "路径位置\"#{repo_path}\"不是git仓库!"
    end
  }
  return output
end

.check_permission(url, root: nil) ⇒ Boolean

在不拉仓库的情况下,查询当前用户是否有权限拉取代码

用法 ===========

url = ‘github.com/baidu/baiduapp-platform/a’ result = MGit::OpenApi.check_permission(url)

Parameters:

  • root (String) (defaults to: nil)

    工程根目录

  • url (String)

    远程仓库url

Returns:

  • (Boolean)

    是否有权限



345
346
347
348
349
350
351
352
353
354
# File 'lib/m-git/open_api.rb', line 345

def check_permission(url, root:nil)
  if !root.nil?
    git_store = Utils.generate_git_store(root, url)
    if !git_store.nil? && Dir.exist?(git_store)
      return true
    end
  end

  return Utils.has_permission_of_remote?(url)
end

.check_permission_batch(root, url_list) ⇒ Object

在不拉仓库的情况下,批量查询当前用户是否有权限拉取代码

用法 ===========

url_list = [

'https://github.com/baidu/baiduapp-platform/a',
'https://github.com/baidu/baiduapp-platform/b'

] MGit::OpenApi.check_permission_batch(arr) { |url, has_permission, progress|

do something...

}

Parameters:

  • root (String)

    工程根目录

  • url_list (Array<String>)

    一组远程仓库url



320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/m-git/open_api.rb', line 320

def check_permission_batch(root, url_list)
  mutex = Mutex.new
  task_count = 0
  total_task = url_list.length
  concurrent_enumerate(url_list) { |url|
    has_permission = self.check_permission(url, root:root)
    mutex.lock
    task_count += 1
    progress = Float(task_count) / total_task
    yield(url, has_permission, progress) if block_given?
    mutex.unlock
  }
end

.checkout(repo_name, repo_path, create_branch: false, branch: nil, base_commit: nil, allow_fetch: false) ⇒ (String, Boolean)

将仓库切到特定的分支或commit

用法 ===========

自信切commit MGit::OpenApi.checkout(name, abs_path, base_commit:‘4922620’)

自信切分支,分支确定存在 MGit::OpenApi.checkout(name, abs_path, branch:‘master’)

尝试切分支,没有就创建 MGit::OpenApi.checkout(name, abs_path, create_branch:true, branch:‘master’, base_commit:‘4922620’)

Parameters:

  • repo_name (String)

    仓库名,不可为nil。

  • repo_path (String)

    仓库本地地址,不可为nil。

  • create_branch (String) (defaults to: false)

    是否创建新分支。

  • branch (String) (defaults to: nil)

    需要切换的分支,可为nil。。 如果非nil,若仓库有该分支则直接切换,没有则在指定commit上创建。 如果为nil,则直接切换到指定commit。

  • commit_id (String)

    需要切换的commit id,不可为nil。

  • allow_fetch (String) (defaults to: false)

    指定在本地无指定分支或commit时是否fetch后重试。

Returns:

  • ((String, Boolean))

    (error, did_create_new_branch)

    • error: 错误信息,若无错误,返回nile

    • did_create_new_branch: 本次checkout是否创建新分支



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
175
176
177
178
179
180
181
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
# File 'lib/m-git/open_api.rb', line 119

def checkout(repo_name, repo_path, create_branch:false, branch:nil, base_commit:nil, allow_fetch:false)

  # 空值校验
  error = self.validate_argv(__method__, {"repo_name" => repo_name, "repo_path" => repo_path})
  return error, false if !error.nil?
  return 'branch和base_commit必须传入一个值!', false if branch.nil? && base_commit.nil?

  # 生成仓库对象
  if Repo.is_git_repo?(repo_path)
    repo = Repo.new(repo_name, repo_path)
  else
    return "路径位置\"#{repo_path}\"不是git仓库!", false
  end

  error = nil
  did_create_new_branch = false

  # 如果指定可fetch,那么在本地缺失信息时执行fetch
  if allow_fetch

    # 查询分支和commit
    should_fetch = !branch.nil? && !repo.status_checker.local_branch_exist?(branch) ||
                    !base_commit.nil? && !repo.status_checker.commit_exist?(base_commit)

    error = fetch(repo.name, repo.path) if should_fetch

    return error, did_create_new_branch if !error.nil?
  end

  if !branch.nil?

    # 已在指定分支则不操作
    if repo.status_checker.current_branch(strict_mode:false) != branch

      # 有本地改动禁止新建/切换分支
      if repo.status_checker.status == Repo::Status::GIT_REPO_STATUS[:dirty]
        error = "仓库#{repo_name}有改动,无法切换/创建分支!"

      # 有本地或对应远程分支,直接切换
      elsif repo.status_checker.local_branch_exist?(branch) || repo.status_checker.remote_branch_exist?(branch)
        success, output = repo.execute_git_cmd('checkout', branch)
        error = output if !success

      # 无分支,在指定commit上创建
      elsif create_branch

        if !base_commit.nil?
          if repo.status_checker.commit_exist?(base_commit)
            success, output = repo.execute_git_cmd('checkout', "-b #{branch} #{base_commit}")
            if !success
              error = output
            else
              did_create_new_branch = true
            end
          else
            error = "仓库#{repo_name}创建新分支时,未找到指定基点commit!"
          end
        else
          error = "仓库#{repo_name}创建新分支时,没有指定基点commit!"
        end

      else
        error = "仓库#{repo_name}无分支#{branch},且未指定创建!"
      end

    end

  elsif !base_commit.nil?

    # 已在指定commit则不操作
    if !repo.status_checker.current_branch(strict_mode:false).nil? ||
      repo.status_checker.current_head(strict_mode:false) != base_commit


      # 有本地改动禁止新建/切换分支
      if repo.status_checker.status == Repo::Status::GIT_REPO_STATUS[:dirty]
        error = "仓库#{repo_name}有改动,无法切换HEAD!"

      # 未指定branch,直接切到指定commit
      elsif repo.status_checker.commit_exist?(base_commit)
        success, output = repo.execute_git_cmd('checkout', base_commit)
        error = output if !success

      # 指定commit不存在报错
      else
        error = "仓库#{repo_name}切换操作失败,指定commit不存在!"
      end

    end

  end

  return error, did_create_new_branch
end

.concurrent_enumerate(array, max_concurrent_count: 5) ⇒ Object

并发遍历

用法 ===========

concurrent_enumerate([item1, item2…]) { |item|

do something with item...

}

Parameters:

  • array (<Object>)

    遍历数组

  • max_concurrent_count (Integer) (defaults to: 5)

    最大并发数



298
299
300
301
302
303
304
# File 'lib/m-git/open_api.rb', line 298

def concurrent_enumerate(array, max_concurrent_count:5)
  if array.is_a?(Array) && array.length > 0
    array.peach(max_concurrent_count) { |item|
      yield(item) if block_given?
    }
  end
end

.download(config, download_root, manage_git: true, sync_exist: false) ⇒ Object

根据配置对象下载仓库

用法 ===========

self.download(config, download_root) { |download_info|

do something with download_info....

}

Parameters:

  • config_content (String/Hash)

    配置表json字符串或字典(key值需为String),不可为nil。

  • download_root (String)

    仓库下载的根目录,不可为nil。

  • manage_git (Boolean) (defaults to: true)

    新下载的仓库是否托管.git,若为false,则在工作区保留新克隆仓库的.git,否则将.git托管到.mgit/sourct-git中,并在工作区创建其软链接



386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/m-git/open_api.rb', line 386

def download(config, download_root, manage_git:true, sync_exist: false)
  task_count = 0
  total_task = config.light_repos.length
  mutex = Mutex.new
  concurrent_enumerate(config.light_repos) { |light_repo|
    name = light_repo.name
    path = light_repo.abs_dest(download_root)
    result = nil
    output = nil
    progress = 0

    if Dir.exist?(path) && Repo.is_git_repo?(path)
      if sync_exist
        repo, error = Repo.generate_softly(download_root, light_repo)
        error = Repo::SyncHelper.sync_exist_repo(repo, repo.config) if !repo.nil?
      end
      result = DownloadResult::EXIST
    elsif Utils.has_permission_of_remote?(light_repo.url)
      error, repo = Repo::SyncHelper.sync_new_repo(light_repo, download_root, link_git:manage_git)
      if !error.nil?
        result = DownloadResult::FAIL
        output = error
      else
        result = DownloadResult::SUCCESS
      end
    else
      result = DownloadResult::FAIL
      output = "当前用户没有该仓库的克隆权限:#{light_repo.name}(#{light_repo.url})!"
    end

    mutex.lock
    task_count += 1
    progress = Float(task_count) / total_task
    yield(ScriptDownloadInfo.new(name, path, result, output, progress)) if block_given?
    mutex.unlock
  }
end

.download_repos(config_content, download_root, manage_git: true) {|ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, error, 0)| ... } ⇒ Object

根据配置表下载仓库

Block: (OpenApi::ScriptDownloadInfo) 下载结果对象

用法 ===========

info对象: MGit::OpenApi.download_repos(json,root) { |info|

puts "name:#{info.repo_name} \n path:#{info.repo_path}\n result:#{info.result}\n error:#{info.output}\n progress:#{info.progress}"
if info.result == OpenApi::DOWNLOAD_RESULT::EXIST
elsif info.result == OpenApi::DOWNLOAD_RESULT::SUCCESS
elsif info.result == OpenApi::DOWNLOAD_RESULT::FAIL
end

}

Parameters:

  • config_content (String/Hash)

    配置表json字符串或字典(key值需为String),不可为nil。

  • download_root (String)

    仓库下载的根目录,不可为nil。

  • manage_git (Boolean) (defaults to: true)

    新下载的仓库是否托管.git,若为false,则在工作区保留新克隆仓库的.git,否则将.git托管到.mgit/sourct-git中,并在工作区创建其软链接

Yields:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/m-git/open_api.rb', line 72

def download_repos(config_content, download_root, manage_git:true)

  # 空值校验
  error = self.validate_argv(__method__, {"config_content" => config_content, "download_root" => config_content})
  yield(ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, error, 0)) if block_given? && !error.nil?

  begin
    config = Manifest.simple_parse(config_content, strict_mode:false)
  rescue Error => e
    yield(ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, e.msg, 0)) if block_given?
    return
  end

  self.download(config, download_root, manage_git:manage_git) { |download_info|
    yield(download_info) if block_given?
  }

end

.fetch(repo_name, repo_path) ⇒ String

执行fetch操作

Parameters:

  • repo_name (Stirng)

    仓库名

  • repo_path (String)

    仓库路径

Returns:

  • (String)

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



222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/m-git/open_api.rb', line 222

def fetch(repo_name, repo_path)
  # 空值校验
  error = self.validate_argv(__method__, {"repo_name" => repo_name, "repo_path" => repo_path})
  return error if !error.nil?

  if Dir.exist?(repo_path) && Repo.is_git_repo?(repo_path)
    repo = Repo.new(repo_name, repo_path)
    success, output = repo.execute_git_cmd('fetch', '')
    return output if !success
  else
    return '指定路径不存在或不是git仓库!'
  end
end

.pull(repo_name, repo_path) ⇒ String

执行pull操作

Parameters:

  • repo_name (Stirng)

    仓库名

  • repo_path (String)

    仓库路径

Returns:

  • (String)

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



244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/m-git/open_api.rb', line 244

def pull(repo_name, repo_path)
  # 空值校验
  error = self.validate_argv(__method__, {"repo_name" => repo_name, "repo_path" => repo_path})
  return error if !error.nil?

  if Dir.exist?(repo_path) && Repo.is_git_repo?(repo_path)
    repo = Repo.new(repo_name, repo_path)
    success, output = repo.execute_git_cmd('pull', '')
    return output if !success
  else
    return '指定路径不存在或不是git仓库!'
  end
end

.sync_repos(config_content, download_root) {|ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, error, 0)| ... } ⇒ Object

根据配置表下载仓库,并同步工作区

Block: (OpenApi::ScriptDownloadInfo) 下载结果对象

用法 ===========

info对象: MGit::OpenApi.sync_repos(json,root) { |info|

puts "name:#{info.repo_name} \n path:#{info.repo_path}\n result:#{info.result}\n error:#{info.output}\n progress:#{info.progress}"
if info.result == OpenApi::DOWNLOAD_RESULT::EXIST
elsif info.result == OpenApi::DOWNLOAD_RESULT::SUCCESS
elsif info.result == OpenApi::DOWNLOAD_RESULT::FAIL
end

}

Parameters:

  • config_content (String/Hash)

    配置表json字符串或字典(key值需为String),不可为nil。

  • download_root (String)

    仓库下载的根目录,不可为nil。

Yields:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/m-git/open_api.rb', line 28

def sync_repos(config_content, download_root)
  # 空值校验
  error = self.validate_argv(__method__, {"config_content" => config_content, "download_root" => config_content})
  yield(ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, error, 0)) if block_given? && !error.nil?

  begin
    config = Manifest.simple_parse(config_content, strict_mode:false)
  rescue Error => e
    yield(ScriptDownloadInfo.new(nil, nil, DownloadResult::FAIL, e.msg, 0)) if block_given?
    return
  end

  # 同步工作区仓库(压入或弹出),此时配置表缓存未覆盖,同步操作若取消无需恢复缓存。
  Utils.sync_workspace(download_root, config, recover_cache_if_cancelled:false)

  # 更新配置缓存
  config.update_cache_with_content(download_root, config.config)

  # 下载
  self.download(config, download_root, sync_exist:true) { |download_info|
    yield(download_info) if block_given?
  }

end

.validate_argv(method_name, args) ⇒ String

—– Util —– 校验参数合法性

Parameters:

  • method_name (String)

    方法名

  • args (Hash)

    参数数组

Returns:

  • (String)

    错误信息,正常返回nil



365
366
367
368
369
370
371
372
# File 'lib/m-git/open_api.rb', line 365

def validate_argv(method_name, args)
  args.each { |k,v|
    if v.nil?
      return "MGit API调用错误: MGit::OpenApi.#{method_name}()的#{k}参数不能为空!"
    end
  }
  return nil
end