summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--routers/web/repo/pull.go45
-rw-r--r--tests/integration/pull_merge_test.go9
-rw-r--r--web_src/js/components/PullRequestMergeForm.vue74
3 files changed, 65 insertions, 63 deletions
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 29d17d2e65..81fb1fb51e 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -1133,30 +1133,28 @@ func MergePullRequest(ctx *context.Context) {
switch {
case errors.Is(err, pull_service.ErrIsClosed):
if issue.IsPull {
- ctx.Flash.Error(ctx.Tr("repo.pulls.is_closed"))
+ ctx.JSONError(ctx.Tr("repo.pulls.is_closed"))
} else {
- ctx.Flash.Error(ctx.Tr("repo.issues.closed_title"))
+ ctx.JSONError(ctx.Tr("repo.issues.closed_title"))
}
case errors.Is(err, pull_service.ErrUserNotAllowedToMerge):
- ctx.Flash.Error(ctx.Tr("repo.pulls.update_not_allowed"))
+ ctx.JSONError(ctx.Tr("repo.pulls.update_not_allowed"))
case errors.Is(err, pull_service.ErrHasMerged):
- ctx.Flash.Error(ctx.Tr("repo.pulls.has_merged"))
+ ctx.JSONError(ctx.Tr("repo.pulls.has_merged"))
case errors.Is(err, pull_service.ErrIsWorkInProgress):
- ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_wip"))
+ ctx.JSONError(ctx.Tr("repo.pulls.no_merge_wip"))
case errors.Is(err, pull_service.ErrNotMergableState):
- ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
+ ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
case models.IsErrDisallowedToMerge(err):
- ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
+ ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
case asymkey_service.IsErrWontSign(err):
- ctx.Flash.Error(err.Error()) // has no translation ...
+ ctx.JSONError(err.Error()) // has no translation ...
case errors.Is(err, pull_service.ErrDependenciesLeft):
- ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
+ ctx.JSONError(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
default:
ctx.ServerError("WebCheck", err)
- return
}
- ctx.Redirect(issue.Link())
return
}
@@ -1164,18 +1162,18 @@ func MergePullRequest(ctx *context.Context) {
if manuallyMerged {
if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
switch {
-
case models.IsErrInvalidMergeStyle(err):
- ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
+ ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
case strings.Contains(err.Error(), "Wrong commit ID"):
- ctx.Flash.Error(ctx.Tr("repo.pulls.wrong_commit_id"))
+ ctx.JSONError(ctx.Tr("repo.pulls.wrong_commit_id"))
default:
ctx.ServerError("MergedManually", err)
- return
}
+
+ return
}
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
return
}
@@ -1205,15 +1203,14 @@ func MergePullRequest(ctx *context.Context) {
} else if scheduled {
// nothing more to do ...
ctx.Flash.Success(ctx.Tr("repo.pulls.auto_merge_newly_scheduled"))
- ctx.Redirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, pr.Index))
+ ctx.JSONRedirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, pr.Index))
return
}
}
if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil {
if models.IsErrInvalidMergeStyle(err) {
- ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
- ctx.Redirect(issue.Link())
+ ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
} else if models.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts)
flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
@@ -1226,7 +1223,7 @@ func MergePullRequest(ctx *context.Context) {
return
}
ctx.Flash.Error(flashError)
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else if models.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts)
flashError, err := ctx.RenderToString(tplAlertDetails, map[string]any{
@@ -1270,7 +1267,7 @@ func MergePullRequest(ctx *context.Context) {
}
ctx.Flash.Error(flashError)
}
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else {
ctx.ServerError("Merge", err)
}
@@ -1279,7 +1276,7 @@ func MergePullRequest(ctx *context.Context) {
log.Trace("Pull request merged: %d", pr.ID)
if err := stopTimerIfAvailable(ctx, ctx.Doer, issue); err != nil {
- ctx.ServerError("CreateOrStopIssueStopwatch", err)
+ ctx.ServerError("stopTimerIfAvailable", err)
return
}
@@ -1293,7 +1290,7 @@ func MergePullRequest(ctx *context.Context) {
return
}
if exist {
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
return
}
@@ -1311,7 +1308,7 @@ func MergePullRequest(ctx *context.Context) {
deleteBranch(ctx, pr, headRepo)
}
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
}
// CancelAutoMergePullRequest cancels a scheduled pr
diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go
index adb0e982c0..42bf584f58 100644
--- a/tests/integration/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -45,7 +45,14 @@ func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum strin
"_csrf": htmlDoc.GetCSRF(),
"do": string(mergeStyle),
})
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ resp = session.MakeRequest(t, req, http.StatusOK)
+
+ respJSON := struct {
+ Redirect string
+ }{}
+ DecodeJSON(t, resp, &respJSON)
+
+ assert.EqualValues(t, fmt.Sprintf("/%s/%s/pulls/%s", user, repo, pullnum), respJSON.Redirect)
return resp
}
diff --git a/web_src/js/components/PullRequestMergeForm.vue b/web_src/js/components/PullRequestMergeForm.vue
index 03d1f99683..aef4c8b5ac 100644
--- a/web_src/js/components/PullRequestMergeForm.vue
+++ b/web_src/js/components/PullRequestMergeForm.vue
@@ -90,48 +90,46 @@ export default {
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-if="mergeForm.hasPendingPullRequestMerge" v-html="mergeForm.hasPendingPullRequestMergeTip" class="ui info message"/>
- <div class="ui form" v-if="showActionForm">
- <form :action="mergeForm.baseLink+'/merge'" method="post">
- <input type="hidden" name="_csrf" :value="csrfToken">
- <input type="hidden" name="head_commit_id" v-model="mergeForm.pullHeadCommitID">
- <input type="hidden" name="merge_when_checks_succeed" v-model="autoMergeWhenSucceed">
- <input type="hidden" name="force_merge" v-model="forceMerge">
-
- <template v-if="!mergeStyleDetail.hideMergeMessageTexts">
- <div class="field">
- <input type="text" name="merge_title_field" v-model="mergeTitleFieldValue">
- </div>
- <div class="field">
- <textarea name="merge_message_field" rows="5" :placeholder="mergeForm.mergeMessageFieldPlaceHolder" v-model="mergeMessageFieldValue"/>
- <template v-if="mergeMessageFieldValue !== mergeForm.defaultMergeMessage">
- <button @click.prevent="clearMergeMessage" class="btn gt-mt-2 gt-p-2 interact-fg" :data-tooltip-content="mergeForm.textClearMergeMessageHint">
- {{ mergeForm.textClearMergeMessage }}
- </button>
- </template>
- </div>
- </template>
-
- <div class="field" v-if="mergeStyle === 'manually-merged'">
- <input type="text" name="merge_commit_id" :placeholder="mergeForm.textMergeCommitId">
+ <form class="ui form form-fetch-action" v-if="showActionForm" :action="mergeForm.baseLink+'/merge'" method="post">
+ <input type="hidden" name="_csrf" :value="csrfToken">
+ <input type="hidden" name="head_commit_id" v-model="mergeForm.pullHeadCommitID">
+ <input type="hidden" name="merge_when_checks_succeed" v-model="autoMergeWhenSucceed">
+ <input type="hidden" name="force_merge" v-model="forceMerge">
+
+ <template v-if="!mergeStyleDetail.hideMergeMessageTexts">
+ <div class="field">
+ <input type="text" name="merge_title_field" v-model="mergeTitleFieldValue">
</div>
-
- <button class="ui button" :class="mergeButtonStyleClass" type="submit" name="do" :value="mergeStyle">
- {{ mergeStyleDetail.textDoMerge }}
- <template v-if="autoMergeWhenSucceed">
- {{ mergeForm.textAutoMergeButtonWhenSucceed }}
+ <div class="field">
+ <textarea name="merge_message_field" rows="5" :placeholder="mergeForm.mergeMessageFieldPlaceHolder" v-model="mergeMessageFieldValue"/>
+ <template v-if="mergeMessageFieldValue !== mergeForm.defaultMergeMessage">
+ <button @click.prevent="clearMergeMessage" class="btn gt-mt-2 gt-p-2 interact-fg" :data-tooltip-content="mergeForm.textClearMergeMessageHint">
+ {{ mergeForm.textClearMergeMessage }}
+ </button>
</template>
- </button>
+ </div>
+ </template>
- <button class="ui button merge-cancel" @click="toggleActionForm(false)">
- {{ mergeForm.textCancel }}
- </button>
+ <div class="field" v-if="mergeStyle === 'manually-merged'">
+ <input type="text" name="merge_commit_id" :placeholder="mergeForm.textMergeCommitId">
+ </div>
- <div class="ui checkbox gt-ml-2" v-if="mergeForm.isPullBranchDeletable && !autoMergeWhenSucceed">
- <input name="delete_branch_after_merge" type="checkbox" v-model="deleteBranchAfterMerge" id="delete-branch-after-merge">
- <label for="delete-branch-after-merge">{{ mergeForm.textDeleteBranch }}</label>
- </div>
- </form>
- </div>
+ <button class="ui button" :class="mergeButtonStyleClass" type="submit" name="do" :value="mergeStyle">
+ {{ mergeStyleDetail.textDoMerge }}
+ <template v-if="autoMergeWhenSucceed">
+ {{ mergeForm.textAutoMergeButtonWhenSucceed }}
+ </template>
+ </button>
+
+ <button class="ui button merge-cancel" @click="toggleActionForm(false)">
+ {{ mergeForm.textCancel }}
+ </button>
+
+ <div class="ui checkbox gt-ml-2" v-if="mergeForm.isPullBranchDeletable && !autoMergeWhenSucceed">
+ <input name="delete_branch_after_merge" type="checkbox" v-model="deleteBranchAfterMerge" id="delete-branch-after-merge">
+ <label for="delete-branch-after-merge">{{ mergeForm.textDeleteBranch }}</label>
+ </div>
+ </form>
<div v-if="!showActionForm" class="gt-df">
<!-- the merge button -->