Commit 8a7917fc authored by Alain Takoudjou's avatar Alain Takoudjou

NXD: Apply patches for MR with more than one commits will ff_merge

If MR has more than one commit, it's possible to do fast-forward merge when
the MR branch is rebased.
parent 98f4fb67
...@@ -159,6 +159,13 @@ export default { ...@@ -159,6 +159,13 @@ export default {
return this.mr.canRemoveSourceBranch; return this.mr.canRemoveSourceBranch;
}, },
ffMergePossible() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.stateData.ffMergePossible;
}
return this.mr.ffMergePossible;
},
commits() { commits() {
if (this.glFeatures.mergeRequestWidgetGraphql) { if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.commitsWithoutMergeCommits.nodes; return this.state.commitsWithoutMergeCommits.nodes;
...@@ -175,10 +182,16 @@ export default { ...@@ -175,10 +182,16 @@ export default {
}, },
ApplyPatchButtonText() { ApplyPatchButtonText() {
if (this.mr.commitsCount === 1) {
return __('Apply Patch '); return __('Apply Patch ');
}
return __('Fast-forward Merge ');
}, },
isApplyPatchAllowed() { isApplyPatchDisabled() {
return this.mr.commitsCount !== 1 || this.isMergeButtonDisabled; if (this.mr.commitsCount === 1) {
return this.isMergeButtonDisabled;
}
return !this.ffMergePossible || this.isMergeButtonDisabled;
}, },
preferredAutoMergeStrategy() { preferredAutoMergeStrategy() {
if (this.glFeatures.mergeRequestWidgetGraphql) { if (this.glFeatures.mergeRequestWidgetGraphql) {
...@@ -539,7 +552,7 @@ export default { ...@@ -539,7 +552,7 @@ export default {
class="patch-merge-request accept-merge-request" class="patch-merge-request accept-merge-request"
data-testid="apply-button" data-testid="apply-button"
:variant="mergeButtonVariant" :variant="mergeButtonVariant"
:disabled="isApplyPatchAllowed" :disabled="isApplyPatchDisabled"
:loading="isMakingRequest" :loading="isMakingRequest"
data-qa-selector="apply_patch_button" data-qa-selector="apply_patch_button"
@click="handleMergeButtonClick(false, false, true)" @click="handleMergeButtonClick(false, false, true)"
......
...@@ -16,6 +16,7 @@ query getState($projectPath: ID!, $iid: String!) { ...@@ -16,6 +16,7 @@ query getState($projectPath: ID!, $iid: String!) {
status status
warnings warnings
} }
ffMergePossible
shouldBeRebased shouldBeRebased
sourceBranchExists sourceBranchExists
state state
......
...@@ -17,6 +17,7 @@ fragment ReadyToMerge on Project { ...@@ -17,6 +17,7 @@ fragment ReadyToMerge on Project {
mergeWhenPipelineSucceeds mergeWhenPipelineSucceeds
commitCount commitCount
diffHeadSha diffHeadSha
ffMergePossible
userPermissions { userPermissions {
removeSourceBranch removeSourceBranch
} }
......
...@@ -144,6 +144,7 @@ export default class MergeRequestStore { ...@@ -144,6 +144,7 @@ export default class MergeRequestStore {
this.projectArchived = data.project_archived; this.projectArchived = data.project_archived;
this.isSHAMismatch = this.sha !== data.diff_head_sha; this.isSHAMismatch = this.sha !== data.diff_head_sha;
this.shouldBeRebased = Boolean(data.should_be_rebased); this.shouldBeRebased = Boolean(data.should_be_rebased);
this.ffMergePossible = Boolean(data.ff_merge_possible);
this.workInProgress = data.work_in_progress; this.workInProgress = data.work_in_progress;
} }
...@@ -187,6 +188,7 @@ export default class MergeRequestStore { ...@@ -187,6 +188,7 @@ export default class MergeRequestStore {
this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled'; this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
this.isSHAMismatch = this.sha !== mergeRequest.diffHeadSha; this.isSHAMismatch = this.sha !== mergeRequest.diffHeadSha;
this.shouldBeRebased = mergeRequest.shouldBeRebased; this.shouldBeRebased = mergeRequest.shouldBeRebased;
this.ffMergePossible = mergeRequest.ffMergePossible;
this.workInProgress = mergeRequest.workInProgress; this.workInProgress = mergeRequest.workInProgress;
this.mergeRequestState = mergeRequest.state; this.mergeRequestState = mergeRequest.state;
......
...@@ -40,6 +40,9 @@ module Mutations ...@@ -40,6 +40,9 @@ module Mutations
required: false, required: false,
default_value: false, default_value: false,
description: 'Squash commits on the source branch before merge.' description: 'Squash commits on the source branch before merge.'
argument :apply_patch, ::GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Merge with apply patche button enabled.'
def resolve(project_path:, iid:, **args) def resolve(project_path:, iid:, **args)
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/4796') Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/4796')
......
...@@ -91,6 +91,8 @@ module Types ...@@ -91,6 +91,8 @@ module Types
description: 'Indicates if members of the target project can push to the fork.' description: 'Indicates if members of the target project can push to the fork.'
field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true, field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true,
description: 'Indicates if the merge request will be rebased.' description: 'Indicates if the merge request will be rebased.'
field :ff_merge_possible, GraphQL::BOOLEAN_TYPE, method: :ff_merge_possible?, null: false, calls_gitaly: true,
description: 'Indicates if the ff merge is possible.'
field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true, field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true,
description: 'Rebase commit SHA of the merge request.' description: 'Rebase commit SHA of the merge request.'
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true, field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true,
......
...@@ -116,6 +116,7 @@ class MergeRequest < ApplicationRecord ...@@ -116,6 +116,7 @@ class MergeRequest < ApplicationRecord
has_many :reviews, inverse_of: :merge_request has_many :reviews, inverse_of: :merge_request
KNOWN_MERGE_PARAMS = [ KNOWN_MERGE_PARAMS = [
:apply_patch,
:auto_merge_strategy, :auto_merge_strategy,
:should_remove_source_branch, :should_remove_source_branch,
:force_remove_source_branch, :force_remove_source_branch,
......
...@@ -86,21 +86,31 @@ module MergeRequests ...@@ -86,21 +86,31 @@ module MergeRequests
log_info("Git merge started on JID #{merge_jid}") log_info("Git merge started on JID #{merge_jid}")
mr_1patch = merge_request.commits.size == 1 mr_1patch = merge_request.commits.size == 1
do_apply = params[:apply_patches] || mr_1patch ff_merged = false
do_merge = !do_apply
patch = merge_request.commits.reverse.first
commit_id = do_merge ? try_merge \ if params[:apply_patch]
: repository.cherry_pick(current_user, repository.commit(patch.sha), merge_request.target_branch, commit_message, if mr_1patch
start_branch_name: nil, start_project: project, dry_run: false) patch = merge_request.commits.reverse.first
commit_id = repository.cherry_pick(current_user, repository.commit(patch.sha), merge_request.target_branch,
commit_message, start_branch_name: nil, start_project: project, dry_run: false)
else
# ff_merge
ff_merged = true
try_ff_merge
end
else
commit_id = try_merge
end
if commit_id if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}") log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
merge_request.update!(merge_commit_sha: commit_id)
elsif ff_merged
log_info("Git merge finished on JID #{merge_jid}")
else else
raise_error(GENERIC_ERROR_MESSAGE) raise_error(GENERIC_ERROR_MESSAGE)
end end
merge_request.update!(merge_commit_sha: commit_id)
ensure ensure
merge_request.update_and_mark_in_progress_merge_commit_sha(nil) merge_request.update_and_mark_in_progress_merge_commit_sha(nil)
end end
...@@ -117,6 +127,20 @@ module MergeRequests ...@@ -117,6 +127,20 @@ module MergeRequests
raise_error(GENERIC_ERROR_MESSAGE) raise_error(GENERIC_ERROR_MESSAGE)
end end
def try_ff_merge
repository.ff_merge(current_user,
source,
merge_request.target_branch,
merge_request: merge_request)
rescue Gitlab::Git::PreReceiveError => e
raise MergeError,
"Something went wrong during merge pre-receive hook. #{e.message}".strip
rescue StandardError => e
handle_merge_error(log_message: e.message)
raise_error(GENERIC_ERROR_MESSAGE)
end
def after_merge def after_merge
log_info("Post merge started on JID #{merge_jid} with state #{state}") log_info("Post merge started on JID #{merge_jid} with state #{state}")
MergeRequests::PostMergeService.new(project: project, current_user: current_user).execute(merge_request) MergeRequests::PostMergeService.new(project: project, current_user: current_user).execute(merge_request)
......
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