Commit 55805d1d authored by Georges Racinet's avatar Georges Racinet 🦑
Browse files

Merge Request detection for closed (named) branches

Closes #207

If a Mercurial branch is merged and closed in the same push,
this makes proper detection for the corresponding Merge Request(s).

The detection works if the closing happens before or after the merge,
that's why we needed to have both the closing changeset and its
parents.

--HG--
branch : heptapod-stable
parent 14e024b32d5b
......@@ -3,7 +3,8 @@
module MergeRequests
# Service for manually merged Mercurial Merge Requests
#
# - update the MR to the latest relevant changeset
# - update the MR to the latest relevant changeset (can be `nil` if caller
# cannot find it)
# - mark it as merged
# - execute all hooks and notifications
#
......@@ -18,6 +19,8 @@ def execute(merge_request, latest_sha)
# Typically, with topics publication, the source branch has already vanished
# reloading everything would not understand that.
def refresh(merge_request, real_source_sha)
return if real_source_sha.nil?
recorded_source_sha = merge_request.diff_head_sha
return if recorded_source_sha == real_source_sha
......
......@@ -96,6 +96,58 @@ def hg_process_project_prunes(post_received, prunes)
end
end
end
closed_branches = prunes['branch_closed']
unless closed_branches.nil?
merged_with_sha = []
closed_branches.each_pair do |gl_branch, info|
next if info.nil?
gl_branch = base64_to_utf8(gl_branch)
info.each do |closing_sha, parent_shas|
merged_with_sha.concat(merged_for_closing_changeset(
project, gl_branch,
closing_sha, parent_shas))
end
end
merged_with_sha.each do |merge_request, latest_sha|
MergeRequests::HgManuallyMergedService.new(project, user).execute(merge_request, latest_sha)
end
end
end
# Given a closing commit SHA and the SHAs of its parents, find the
# Merge Requests that have to be updated and merged.
def merged_for_closing_changeset(project, gl_branch, closing_sha, parent_shas)
logprefix = "PostReceive analyzing Merge Requests for changeset "\
"#{closing_sha}, that closes '#{gl_branch}'"
repo = project.repository
merged = []
project.merge_requests.opened
.where(source_branch: gl_branch, source_project: project)
.each do |merge_request|
real_target_sha = merge_request.target_branch_sha
if repo.ancestor?(closing_sha, real_target_sha)
merged << [merge_request, closing_sha]
Rails.logger.info("#{logprefix}: it is a direct ancestor "\
"of MR iid=#{merge_request.iid}, targeting "\
"'#{merge_request.target_branch}'. "\
"Marking as merged.")
else
if parent_shas.all? {|psha| repo.ancestor?(psha, real_target_sha)}
Rails.logger.info("#{logprefix}: all its parents #{parent_shas} "\
"are ancestors of MR iid=#{merge_request.iid}, "\
"targeting '#{merge_request.target_branch}'. "\
"Marking as merged.")
# if the closing commit has several parents, since we have to update
# the MR with a single head, let's put in the closing commit to see
# all of them and be faithful to what happened.
merged << [merge_request,
parent_shas.length == 1? parent_shas[0] : closing_sha]
end
end
end
merged
end
# Deserialize a binary string from Base64, then guess and convert to UTF-8
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment