class Danger::GitRepo
Attributes
diff[RW]
folder[RW]
log[RW]
Public Instance Methods
diff_for_folder(folder, from: "master", to: "HEAD", lookup_top_level: false)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 9 def diff_for_folder(folder, from: "master", to: "HEAD", lookup_top_level: false) self.folder = folder git_top_level = find_git_top_level_if_needed!(folder, lookup_top_level) repo = Git.open(git_top_level) ensure_commitish_exists!(from) ensure_commitish_exists!(to) merge_base = find_merge_base(repo, from, to) commits_in_branch_count = commits_in_branch_count(from, to) self.diff = repo.diff(merge_base, to) self.log = repo.log(commits_in_branch_count).between(from, to) end
ensure_commitish_exists!(commitish)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 73 def ensure_commitish_exists!(commitish) return ensure_commitish_exists_on_branch!(commitish, commitish) if commit_is_ref?(commitish) return if commit_exists?(commitish) git_in_depth_fetch raise_if_we_cannot_find_the_commit(commitish) if commit_not_exists?(commitish) end
ensure_commitish_exists_on_branch!(branch, commitish)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 81 def ensure_commitish_exists_on_branch!(branch, commitish) return if commit_exists?(commitish) depth = 0 success = (3..6).any? do |factor| depth += Math.exp(factor).to_i git_fetch_branch_to_depth(branch, depth) commit_exists?(commitish) end return if success git_in_depth_fetch raise_if_we_cannot_find_the_commit(commitish) if commit_not_exists?(commitish) end
exec(string)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 51 def exec(string) require "open3" Dir.chdir(self.folder || ".") do git_command = string.split(" ").dup.unshift("git") Open3.popen2(default_env, *git_command) do |_stdin, stdout, _wait_thr| stdout.read.rstrip end end end
head_commit()
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 61 def head_commit exec("rev-parse HEAD") end
origins()
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 69 def origins exec("remote show origin -n").lines.grep(/Fetch URL/)[0].split(": ", 2)[1].chomp end
renamed_files()
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 25 def renamed_files # Get raw diff with --find-renames --diff-filter # We need to pass --find-renames cause # older versions of git don't use this flag as default diff = exec( "diff #{self.diff.from} #{self.diff.to} --find-renames --diff-filter=R" ).lines.map { |line| line.tr("\n", "") } before_name_regexp = /^rename from (.*)$/ after_name_regexp = /^rename to (.*)$/ # Extract old and new paths via regexp diff.each_with_index.map do |line, index| before_match = line.match(before_name_regexp) next unless before_match after_match = diff.fetch(index + 1, "").match(after_name_regexp) next unless after_match { before: before_match.captures.first, after: after_match.captures.first } end.compact end
Private Instance Methods
commit_exists?(sha1)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 117 def commit_exists?(sha1) !commit_not_exists?(sha1) end
commit_is_ref?(commit)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 167 def commit_is_ref?(commit) /[a-f0-9]{5,40}/ !~ commit end
commit_not_exists?(sha1)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 121 def commit_not_exists?(sha1) exec("rev-parse --quiet --verify #{sha1}^{commit}").empty? end
commits_in_branch_count(from, to)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 163 def commits_in_branch_count(from, to) exec("rev-list #{from}..#{to} --count").to_i end
compare_path(path1, path2)
click to toggle source
Compare given paths as realpath. Return true if both are same. ‘git rev-parse –show-toplevel` returns a path resolving symlink. In rspec, given path can be a temporary directory’s path created under a symlinked directory ‘/var`.
# File lib/danger/scm_source/git_repo.rb, line 187 def compare_path(path1, path2) Pathname.new(path1).realdirpath == Pathname.new(path2).realdirpath end
default_env()
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 109 def default_env { "LANG" => "en_US.UTF-8" } end
find_git_top_level_if_needed!(folder, lookup_top_level)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 171 def find_git_top_level_if_needed!(folder, lookup_top_level) git_top_level = Dir.chdir(folder) { exec("rev-parse --show-toplevel") } return git_top_level if lookup_top_level # To keep backward compatibility, `GitRepo#diff_for_folder` expects folder # to be top level git directory or requires `true` to `lookup_top_level`. # https://github.com/danger/danger/pull/1178 return folder if compare_path(git_top_level, folder) message = "#{folder} is not the top level git directory. Pass correct path or `true` to `lookup_top_level` option for `diff_for_folder`" raise ArgumentError, message end
find_merge_base(repo, from, to)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 125 def find_merge_base(repo, from, to) possible_merge_base = possible_merge_base(repo, from, to) return possible_merge_base if possible_merge_base possible_merge_base = find_merge_base_with_incremental_fetch(repo, from, to) return possible_merge_base if possible_merge_base git_in_depth_fetch possible_merge_base = possible_merge_base(repo, from, to) raise "Cannot find a merge base between #{from} and #{to}. If you are using shallow clone/fetch, try increasing the --depth" unless possible_merge_base possible_merge_base end
find_merge_base_with_incremental_fetch(repo, from, to)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 140 def find_merge_base_with_incremental_fetch(repo, from, to) from_is_ref = commit_is_ref?(from) to_is_ref = commit_is_ref?(to) return unless from_is_ref || to_is_ref depth = 0 (3..6).each do |factor| depth += Math.exp(factor).to_i git_fetch_branch_to_depth(from, depth) if from_is_ref git_fetch_branch_to_depth(to, depth) if to_is_ref merge_base = possible_merge_base(repo, from, to) return merge_base if merge_base end nil end
git_fetch_branch_to_depth(branch, depth)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 105 def git_fetch_branch_to_depth(branch, depth) exec("fetch --depth=#{depth} --prune origin +refs/heads/#{branch}:refs/remotes/origin/#{branch}") end
git_in_depth_fetch()
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 101 def git_in_depth_fetch exec("fetch --depth 1000000") end
possible_merge_base(repo, from, to)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 159 def possible_merge_base(repo, from, to) [repo.merge_base(from, to)].find { |base| commit_exists?(base) } end
raise_if_we_cannot_find_the_commit(commitish)
click to toggle source
# File lib/danger/scm_source/git_repo.rb, line 113 def raise_if_we_cannot_find_the_commit(commitish) raise "Commit #{commitish[0..7]} doesn't exist. Are you running `danger local/pr` against the correct repository? Also this usually happens when you rebase/reset and force-pushed." end