Module: MGit::Utils

Defined in:
lib/m-git/foundation/utils.rb

Class Method Summary collapse

Class Method Details

.branch_exist_on_remote?(branch, git_url) ⇒ Bool

在不拉取仓库的情况下,查询远程仓库是否存在某分支

Returns:

  • (Bool)

    是否存在分支



137
138
139
140
141
142
143
# File 'lib/m-git/foundation/utils.rb', line 137

def branch_exist_on_remote?(branch, git_url)
  return false if branch.nil? || git_url.nil?
  cmd = "git ls-remote --heads #{git_url} | grep \"#{branch}\""
  execute_shell_cmd(cmd) { |stdout, stderr, status|
    return status.success?
  }
end

.change_dir(dir) ⇒ Object

改变当前路径



37
38
39
40
41
42
43
44
# File 'lib/m-git/foundation/utils.rb', line 37

def change_dir(dir)
  return if dir == Dir.pwd
  begin
    Dir.chdir(dir)
  rescue => e
    raise "目录切换失败:#{e.message}"
  end
end

.execute_shell_cmd(cmd) {|stdout, stderr, status| ... } ⇒ Object

执行shell指令

Yields:

  • (stdout, stderr, status)


23
24
25
26
27
28
29
30
31
32
# File 'lib/m-git/foundation/utils.rb', line 23

def execute_shell_cmd(cmd)
  begin
    (stdout, stderr, status) = Open3.capture3(cmd)
  rescue => e
    puts "\n"
    Foundation.help!("指令 \"#{cmd}\" 执行异常:#{e.message}")
  end
  yield(stdout, stderr, status) if block_given?
  self
end

.execute_under_dir(dir) ⇒ Object

在某路径下执行代码



47
48
49
50
51
52
# File 'lib/m-git/foundation/utils.rb', line 47

def execute_under_dir(dir)
  origin_dir = Dir.pwd
  change_dir(dir)
  yield() if block_given?
  change_dir(origin_dir)
end

.expand_path(path, base: nil) ⇒ String

扩展成完整路径

Parameters:

  • path (String)

    路径名

  • base (Type) (defaults to: nil)

    default: nil 基准路径

Returns:

  • (String)

    扩展后的完整路径



78
79
80
81
82
83
84
85
86
# File 'lib/m-git/foundation/utils.rb', line 78

def expand_path(path, base:nil)
  pn = Pathname.new(path)
  if pn.relative?
    base = Dir.pwd if base.nil?
    File.expand_path(File.join(base, path))
  else
    path
  end
end

.generate_git_store(root, url) ⇒ String

根据url生成git实体存放路径

Parameters:

  • url (String)

    仓库url

Returns:

  • (String)

    .git实体存放地址,生成错误返回nil



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/m-git/foundation/utils.rb', line 191

def generate_git_store(root, url)
  return if url.nil?
  git_dir = File.join(root, Constants::PROJECT_DIR[:source_git])
  begin
    url_obj = URI(url)
    # 去除shceme
    url_path = File.join("#{url_obj.host}#{url_obj.port.nil? ? '' : ":#{url_obj.port}"}", url_obj.path)
    # 去除后缀名
    git_relative_dir = File.join(File.dirname(url_path), File.basename(url_path, File.extname(url_path)))

    File.join(git_dir, git_relative_dir)
  rescue
  end
end

.generate_init_cache_path(root) ⇒ String

初始化缓存目录

Returns:

  • (String)

    目录地址



92
93
94
95
# File 'lib/m-git/foundation/utils.rb', line 92

def generate_init_cache_path(root)
  temp_dir = ".#{Constants::INIT_CACHE_DIR_NAME}__#{Process.pid}__#{Time.new.to_i.to_s}"
  File.join(root,temp_dir)
end

.has_permission_of_remote?(git_url) ⇒ Bool

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

Returns:

  • (Bool)

    是否有权限



149
150
151
152
153
154
155
# File 'lib/m-git/foundation/utils.rb', line 149

def has_permission_of_remote?(git_url)
  return false if git_url.nil?
  cmd = "git ls-remote --heads #{git_url}"
  execute_shell_cmd(cmd) { |stdout, stderr, status|
    return status.success?
  }
end

创建软连接

Parameters:

  • target_path (String)

    目标文件(文件夹)的绝对路径

  • link_path (String)

    软连接所在绝对路径



103
104
105
106
# File 'lib/m-git/foundation/utils.rb', line 103

def link(target_path, link_path)
  target_relative_path = File.join(relative_dir(File.dirname(target_path), File.dirname(link_path)), File.basename(target_path))
  FileUtils.symlink(target_relative_path, link_path, force:true)
end

链接.git仓库实体 1、如果git实体存在,则删除,以当前仓库的.git为主 2、移动仓库的.git到git实体 3、软链仓库的.git为git实体

Parameters:

  • source_dir (String)

    源码路径

  • source_git_dir (String)

    存放git实体的路径



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/m-git/foundation/utils.rb', line 168

def link_git(source_dir, source_git_dir)

  # 工作区.git
  origin_git = File.join(source_dir, '.git')

  # 本地缓存的.git
  target_git = File.join(source_git_dir, '.git')

  FileUtils.remove_dir(target_git, true) if File.exist?(target_git)
  FileUtils.mkdir_p(source_git_dir) unless File.exist?(source_git_dir)

  FileUtils.mv(origin_git, source_git_dir)

  # 创建.git软链接
  link(target_git, origin_git)
end

.logical_cpu_numObject



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/m-git/foundation/utils.rb', line 7

def logical_cpu_num
  if @logical_cpu_num.nil?
    begin
      num = `sysctl -n hw.logicalcpu`
      num = `cat /proc/cpuinfo | grep "processor" | wc -l` unless $?.success?
      @logical_cpu_num = num
    rescue Exception => _
      @logical_cpu_num = "5"
    end
  end
  @logical_cpu_num.to_i
end

.normalize_url(url) ⇒ String

规范化url,删除冗余字符

Parameters:

  • url (String)

    url字符串

Returns:

  • (String)

    规范化后的url



331
332
333
334
335
336
337
338
339
340
# File 'lib/m-git/foundation/utils.rb', line 331

def normalize_url(url)
  return if url.nil?
  refined_url = url.strip.sub(/(\/)+$/,'')
  return refined_url if refined_url.length == 0
  begin
    uri = URI(refined_url)
    return "#{uri.scheme}://#{uri.host}#{uri.port.nil? ? '' : ":#{uri.port}"}#{uri.path}"
  rescue  => _
  end
end

.pop_git_entity(root, config) ⇒ Object



285
286
287
288
289
290
# File 'lib/m-git/foundation/utils.rb', line 285

def pop_git_entity(root, config)
  config.light_repos.each { |light_repo|
    # 将托管的.git弹出到工作区
    Workspace.pop_git_entity(root, light_repo)
  }
end

.push_git_entity(root, config) ⇒ Object



292
293
294
295
296
297
# File 'lib/m-git/foundation/utils.rb', line 292

def push_git_entity(root, config)
  config.light_repos.each { |light_repo|
    # 将工作区的.git托管给mgit
    Workspace.push_git_entity(root, light_repo)
  }
end

.relative_dir(dir_a, dir_b, realpath: true) ⇒ String

计算相对目录

Parameters:

  • dir_a (String)

    目录A,如‘/a/b/A’

  • dir_b (String)

    目录B,如‘/a/c/B’

Returns:

  • (String)

    A目录下文件相对B目录的路径,如‘../../c/B’



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

def relative_dir(dir_a, dir_b, realpath: true)
  if realpath
    (Pathname.new(dir_a).realpath.relative_path_from(Pathname.new(dir_b).realpath)).to_s
  else
    (Pathname.new(dir_a).relative_path_from(Pathname.new(dir_b))).to_s
  end
end

.safe_join(path_a, path_b) ⇒ String

安全的路径拼接

Parameters:

  • path_a (String)

    路径a

  • path_b (String)

    路径b

Returns:

  • (String)

    完整路径



350
351
352
353
354
355
356
357
358
# File 'lib/m-git/foundation/utils.rb', line 350

def safe_join(path_a, path_b)
  if !path_a.nil? && path_a.length > 0 && !path_b.nil? && path_b.length > 0
    File.join(path_a, path_b)
  elsif !path_a.nil? && path_a.length > 0
    path_a
  elsif !path_b.nil? && path_b.length > 0
    path_b
  end
end

.show_clone_info(root, missing_light_repos) ⇒ Object

显示下载仓库信息

Parameters:

  • missing_light_repos (Array<LightRepo>)

    缺失仓库配置对象



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/m-git/foundation/utils.rb', line 112

def show_clone_info(root, missing_light_repos)
  notice_repo = []
  clone_from_local = []
  clone_from_remote = []
  missing_light_repos.each { |light_repo|
    if Dir.exist?(File.join(light_repo.git_store_dir(root), '.git'))
      clone_from_local += [light_repo.name]
    else
      clone_from_remote += [light_repo.name]
    end
  }

  notice_repo.push(['从本地导出', clone_from_local]) if clone_from_local.length > 0
  notice_repo.push(['从远程下载', clone_from_remote]) if clone_from_remote.length > 0

  puts Output.generate_table_combination(notice_repo, separator: "|")
  Output.puts_processing_message('以上仓库本地缺失,处理中...')
end

.sync_workspace(root, config, recover_cache_if_cancelled: true) ⇒ Object

同步工作区(缓存或弹出)

Parameters:

  • root (String)

    mgit管理工程根目录

  • config (Manifest)

    配置对象

  • recover_cache_if_cancelled (Boolean) (defaults to: true)

    如果回收过程中取消操作,是否恢复缓存 (需要自行判断,如果方法调用前缓存已经覆盖,那么需要恢复以保障下次同步操作正常执行

    如果调用前缓存未被覆盖,则无需恢复,此时若强行恢复会干扰下次同步操作)
    


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
# File 'lib/m-git/foundation/utils.rb', line 218

def sync_workspace(root, config, recover_cache_if_cancelled:true)

  # 若有缓存仓库,则移到工作区
  config.light_repos.each { |light_repo|
    #【注意】url不一致会认为是不同仓库,将缓存当前仓库,并弹出url对应缓存(若对应缓存则不弹出)
    Workspace.sync_workspace(root, light_repo)
  }

  # 更新冗余仓库数据
  if config.previous_extra_light_repos.nil? || config.previous_extra_light_repos.length == 0
    config.update_previous_extra_light_repos(root)
  end

  # 若工作区有多余仓库,则缓存
  if !config.previous_extra_light_repos.nil? && config.previous_extra_light_repos.length > 0

    dirty_repos = []
    do_repos = []
    config.previous_extra_light_repos.each { |light_repo|

      # 如果仓库是主仓库,则不操作
      next if light_repo.is_config_repo

      repo, error = Repo.generate_softly(root, light_repo)
      if error.nil?
        if repo.status_checker.status == Repo::Status::GIT_REPO_STATUS[:dirty]
          dirty_repos.push(repo)
        else
          do_repos.push(repo)
        end
      end
    }

    if dirty_repos.length > 0
      if Output.continue_with_interact_repos?(dirty_repos.map { |e| e.name }, '即将回收以上仓库,但存在本地改动,继续操作将丢失改动,是否取消?') ||
          Output.continue_with_user_remind?("即将丢失改动,是否取消?")
        # 用上次配置覆盖以恢复缓存,否则若此次缓存已被覆盖,取消后下次操作同步将失效
        config.update_cache_with_content(root, config.previous_config) if recover_cache_if_cancelled
        Foundation.help!('操作取消')
      end
    end

    current_time = Time.new.strftime("%Y%m%d%H%M%S")
    (dirty_repos + do_repos).each { |repo|
      if dirty_repos.include?(repo)
        repo.execute_git_cmd('add', '.')
        repo.execute_git_cmd('stash', "save -u #{current_time}_MGit回收仓库自动stash")
      end

      begin
        save_to_cache = MGitConfig.query_with_key(root, :savecache)
      rescue Error => _
        save_to_cache = false
      end

      # 如果仓库没有被管理,则不删除,直接缓存
      is_git_managed = Dir.exist?(File.join(repo.config.git_store_dir(root), '.git'))
      if save_to_cache || !is_git_managed
        Workspace.push(root, repo.config)
      else
        FileUtils.rm_rf(repo.path) if Dir.exist?(repo.path)
      end
    }

  end
end

.url_consist?(url_a, url_b) ⇒ Boolean

判断url是否一致

Parameters:

  • url_a (String)

    url

  • url_b (String)

    url

Returns:

  • (Boolean)

    是否一致



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/m-git/foundation/utils.rb', line 307

def url_consist?(url_a, url_b)
  # 删除冗余字符
  temp_a = normalize_url(url_a)
  temp_b = normalize_url(url_b)

  # 同时不为nil判断内容是否相等
  return temp_a == temp_b if !temp_a.nil? && !temp_b.nil?
  # reutrn | temp_a | temp_b
  # ----------------------
  #  true  |   nil  |   nil
  #  true  |   ''   |   nil
  #  true  |   nil  |   ''
  # ----------------------
  #  false |   nil  |   xxx
  #  false |   xxx  |   nil
  (temp_a.nil? && temp_b.nil?) || (!temp_a.nil? && temp_a.length == 0) || (!temp_b.nil? && temp_b.length == 0)
end