gitlab-org--gitlab-foss/app/services/git/branch_hooks_service.rb
2019-04-05 18:26:53 +01:00

144 lines
3.9 KiB
Ruby

# frozen_string_literal: true
module Git
class BranchHooksService < ::Git::BaseHooksService
def execute
execute_branch_hooks
super.tap do
enqueue_update_gpg_signatures
end
end
private
def hook_name
:push_hooks
end
def commits
strong_memoize(:commits) do
if creating_default_branch?
# The most recent PROCESS_COMMIT_LIMIT commits in the default branch
offset = [count_commits_in_branch - PROCESS_COMMIT_LIMIT, 0].max
project.repository.commits(params[:newrev], offset: offset, limit: PROCESS_COMMIT_LIMIT)
elsif creating_branch?
# Use the pushed commits that aren't reachable by the default branch
# as a heuristic. This may include more commits than are actually
# pushed, but that shouldn't matter because we check for existing
# cross-references later.
project.repository.commits_between(project.default_branch, params[:newrev])
elsif updating_branch?
project.repository.commits_between(params[:oldrev], params[:newrev])
else # removing branch
[]
end
end
end
def commits_count
return count_commits_in_branch if creating_default_branch?
super
end
def invalidated_file_types
return super unless default_branch? && !creating_branch?
paths = limited_commits.each_with_object(Set.new) do |commit, set|
commit.raw_deltas.each do |diff|
set << diff.new_path
end
end
Gitlab::FileDetector.types_in_paths(paths)
end
def execute_branch_hooks
project.repository.after_push_commit(branch_name)
branch_create_hooks if creating_branch?
branch_update_hooks if updating_branch?
branch_change_hooks if creating_branch? || updating_branch?
branch_remove_hooks if removing_branch?
end
def branch_create_hooks
project.repository.after_create_branch
project.after_create_default_branch if default_branch?
end
def branch_update_hooks
# Update the bare repositories info/attributes file using the contents of
# the default branch's .gitattributes file
project.repository.copy_gitattributes(params[:ref]) if default_branch?
end
def branch_change_hooks
enqueue_process_commit_messages
end
def branch_remove_hooks
project.repository.after_remove_branch
end
# Schedules processing of commit messages
def enqueue_process_commit_messages
# don't process commits for the initial push to the default branch
return if creating_default_branch?
limited_commits.each do |commit|
next unless commit.matches_cross_reference_regex?
ProcessCommitWorker.perform_async(
project.id,
current_user.id,
commit.to_hash,
default_branch?
)
end
end
def enqueue_update_gpg_signatures
unsigned = GpgSignature.unsigned_commit_shas(limited_commits.map(&:sha))
return if unsigned.empty?
signable = Gitlab::Git::Commit.shas_with_signatures(project.repository, unsigned)
return if signable.empty?
CreateGpgSignatureWorker.perform_async(signable, project.id)
end
def creating_branch?
Gitlab::Git.blank_ref?(params[:oldrev])
end
def updating_branch?
!creating_branch? && !removing_branch?
end
def removing_branch?
Gitlab::Git.blank_ref?(params[:newrev])
end
def creating_default_branch?
creating_branch? && default_branch?
end
def count_commits_in_branch
strong_memoize(:count_commits_in_branch) do
project.repository.commit_count_for_ref(params[:ref])
end
end
def default_branch?
strong_memoize(:default_branch) do
[nil, branch_name].include?(project.default_branch)
end
end
def branch_name
strong_memoize(:branch_name) { Gitlab::Git.ref_name(params[:ref]) }
end
end
end