module MGit::Utils

Public Class Methods

branch_exist_on_remote?(branch, git_url) click to toggle source

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

@return [Bool] 是否存在分支

# 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) click to toggle source

改变当前路径

# 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| ... } click to toggle source

执行shell指令

# 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) { || ... } click to toggle source

在某路径下执行代码

# 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) click to toggle source

扩展成完整路径

@param path [String] 路径名

@param base [Type] default: nil 基准路径

@return [String] 扩展后的完整路径

# 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) click to toggle source

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

@param url [String] 仓库url

@return [String] .git实体存放地址,生成错误返回nil

# 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) click to toggle source

初始化缓存目录

@return [String] 目录地址

# 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) click to toggle source

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

@return [Bool] 是否有权限

# 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
logical_cpu_num() click to toggle source
# 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) click to toggle source

规范化url,删除冗余字符

@param url [String] url字符串

@return [String] 规范化后的url

# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source

计算相对目录

@param dir_a [String] 目录A,如‘/a/b/A’

@param dir_b [String] 目录B,如‘/a/c/B’

@return [String] A目录下文件相对B目录的路径,如‘../../c/B’

# 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) click to toggle source

安全的路径拼接

@param path_a [String] 路径a

@param path_b [String] 路径b

@return [String] 完整路径

# 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) click to toggle source

显示下载仓库信息

@param missing_light_repos [Array<LightRepo>] 缺失仓库配置对象

# 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) click to toggle source

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

@param root [String] mgit管理工程根目录

@param config [Manifest] 配置对象

@param recover_cache_if_cancelled [Boolean] 如果回收过程中取消操作,是否恢复缓存

(需要自行判断,如果方法调用前缓存已经覆盖,那么需要恢复以保障下次同步操作正常执行
  如果调用前缓存未被覆盖,则无需恢复,此时若强行恢复会干扰下次同步操作)
# 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) click to toggle source

判断url是否一致

@param url_a [String] url

@param url_b [String] url

@return [Boolean] 是否一致

# 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