class GitClient

Constants

COMMIT_REGEX
TREE_PERMISSION

Attributes

notification_url[RW]

Public Class Methods

new(config) click to toggle source
# File lib/integrations/git_client.rb, line 16
def initialize(config)
  @git_dir = config["git_dir"]
  @default_branch = config["default_branch"]
  @notification_url = config["notification_url"]
end

Public Instance Methods

commits(branch) click to toggle source
# File lib/integrations/git_client.rb, line 22
def commits(branch)
  commit_ids = short_log(branch)
  cache, index = commits_to_index(branch, commit_ids)
  return [] if index == 0

  commits = full_log(branch, index)
    .reduce([], &fold_reducer(COMMIT_REGEX))
    .map { |commit_lines| Commit.from_git(commit_lines, self) }

  commits = SourceTree
    .new()
    .merge_collapse(commits)

  commits.last.set_cached(cache)
  cache_commits(commits)

  commits.reverse()
end
diff(commit_id_a, commit_id_b) click to toggle source
# File lib/integrations/git_client.rb, line 85
def diff(commit_id_a, commit_id_b)
  exec("diff --full-index -l 10000 -U0 #{commit_id_a} #{commit_id_b}")
end
diff_tree(commit_id) click to toggle source
# File lib/integrations/git_client.rb, line 41
def diff_tree(commit_id)
  exec("diff-tree -t -r #{commit_id}")
end
file_tree(commit_id) click to toggle source
# File lib/integrations/git_client.rb, line 66
def file_tree(commit_id)
  exec("ls-tree -r #{commit_id}")
end
ls_tree(commit_id) click to toggle source
# File lib/integrations/git_client.rb, line 62
def ls_tree(commit_id)
  exec("ls-tree -r -t #{commit_id}")
end
parse_diff_tree(tree) click to toggle source
# File lib/integrations/git_client.rb, line 45
def parse_diff_tree(tree)
  tree
    .reduce([]) do |acc, object|
      a_perm, b_perm, a_id, b_id, operation, path = object[1..-1].split(" ")
      if a_perm == TREE_PERMISSION || b_perm == TREE_PERMISSION
        acc << {
          a_tree_id: a_id,
          b_tree_id: b_id,
          path: path,
          operation: operation == "D" ? :delete : :change
        }
      end
      acc
    end
    .sort_by { |tree| tree[:path].split(File::SEPARATOR).length }
end
parse_ls_tree(tree) click to toggle source
# File lib/integrations/git_client.rb, line 70
def parse_ls_tree(tree)
  tree.reduce([]) do |acc, object|
    perm, type, tree_id, path = object.split(" ")
    if type == "tree"
      acc << {
        a_tree_id: "0"*40,
        b_tree_id: tree_id,
        path: path,
        operation: :change
      }
    end
    acc
  end
end
remote_branches() click to toggle source
# File lib/integrations/git_client.rb, line 89
def remote_branches()
  exec("branch -r")
    .map { |branch| branch.split(" -> ").last.strip() }
    .select { |branch| branch.index("origin/") == 0 }
    .map { |branch| "remotes/#{branch}" }
end

Private Instance Methods

cache_commits(commits) click to toggle source
# File lib/integrations/git_client.rb, line 173
def cache_commits(commits)
  commits.each { |commit| Store::Commit.index(commit.as_json()) }
  Store::Commit.cache()
end
commits_to_index(branch, commit_ids) click to toggle source
# File lib/integrations/git_client.rb, line 148
def commits_to_index(branch, commit_ids)
  last_indexed_commit = Cache.last_indexed_commit(branch, commit_ids)

  # Maybe use default_branch, also git merge-base.
  if last_indexed_commit == nil && branch != "master"
    last_indexed_commit = Cache.last_indexed_commit("master", commit_ids)
  end

  index = commit_ids.index(last_indexed_commit)

  if sync?(index, commit_ids)
    index = 1
    last_indexed_commit = commit_ids[index]
  end

  # When switching to new branch, save all previously indexed commits.
  if not index.nil?
    Cache.index_commits(branch, commit_ids[index..-1].reverse())
  end

  cache = index.nil? ? [] : parse_tree(tree(last_indexed_commit))

  [cache, index]
end
exec(cmd) click to toggle source
# File lib/integrations/git_client.rb, line 98
def exec(cmd)
  `git --git-dir=#{@git_dir || ".git"} #{cmd}`
    .encode("UTF-8", {invalid: :replace})
    .lines
    .map(&:chomp)
end
full_log(branch, count) click to toggle source
# File lib/integrations/git_client.rb, line 105
def full_log(branch, count)
  Loggr.instance.info("SHOW COMMITS")
  count_option = count.nil? ? "" : "-n #{count}"
  exec("log \
    --topo-order \
    --oneline \
    -U0 \
    --diff-algorithm=histogram \
    --full-history \
    --full-index \
    --date=rfc \
    --pretty=format:'%H|||%P|||%an <%aE>|||%cd|||%s' \
    #{count_option} #{branch}"
  )
end
parse_tree(tree) click to toggle source
# File lib/integrations/git_client.rb, line 135
def parse_tree(tree)
  tree
    .map do |object|
      permission, type, object_id, path = object.split(" ")
      {
        object_id: object_id,
        type: type == "tree" ? :tree : :file,
        path: path.strip()
      }
    end
    .sort_by { |object| object[:path].split(File::SEPARATOR).length }
end
short_log(branch) click to toggle source
# File lib/integrations/git_client.rb, line 121
def short_log(branch)
  exec("log \
    --graph \
    --topo-order \
    --oneline \
    --pretty=format:%H #{branch} \
    | grep '^\*'")
    .map { |line| line.split(" ").last.to_sym }
end
sync?(index, commit_ids) click to toggle source
# File lib/integrations/git_client.rb, line 178
def sync?(index, commit_ids)
  index == 0 &&
    commit_ids.length > 1 &&
    ENV["GITOLEMY_SYNC"] == "true"
end
tree(commit_id) click to toggle source
# File lib/integrations/git_client.rb, line 131
def tree(commit_id)
  exec("ls-tree -r -t #{commit_id}")
end