Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle push rejection message in Merge & Web Editor #10373

Merged
merged 11 commits into from
Feb 22, 2020
43 changes: 43 additions & 0 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package models

import (
"fmt"
"strings"

"code.gitea.io/gitea/modules/git"
)
Expand Down Expand Up @@ -1371,6 +1372,48 @@ func (err ErrMergePushOutOfDate) Error() string {
return fmt.Sprintf("Merge PushOutOfDate Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}

// ErrPushRejected represents an error if merging fails due to unrelated histories
zeripath marked this conversation as resolved.
Show resolved Hide resolved
type ErrPushRejected struct {
Style MergeStyle
StdOut string
StdErr string
Err error
}

// IsErrPushRejected checks if an error is a ErrPushRejected.
func IsErrPushRejected(err error) bool {
_, ok := err.(ErrPushRejected)
return ok
}

func (err ErrPushRejected) Error() string {
return fmt.Sprintf("Merge PushRejected Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}

// Message returns the cleaned message from Error
func (err ErrPushRejected) Message() string {
messageBuilder := &strings.Builder{}
i := 0
for {
if len(err.StdErr) <= i+8 {
break
}
if err.StdErr[i:i+8] != "remote: " {
break
guillep2k marked this conversation as resolved.
Show resolved Hide resolved
}
i = i + 8
nl := strings.IndexByte(err.StdErr[i:], '\n')
guillep2k marked this conversation as resolved.
Show resolved Hide resolved
if nl > 0 {
messageBuilder.WriteString(err.StdErr[i : i+nl+1])
i = i + nl + 1
} else {
messageBuilder.WriteString(err.StdErr[i:])
i = len(err.StdErr)
}
}
return messageBuilder.String()
}

// ErrRebaseConflicts represents an error if rebase fails with a conflict
type ErrRebaseConflicts struct {
Style MergeStyle
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,7 @@ pulls.merge_conflict = Merge Failed: There was a conflict whilst merging: %[1]s<
pulls.rebase_conflict = Merge Failed: There was a conflict whilst rebasing commit: %[1]s<br>%[2]s<br>%[3]s<br>Hint:Try a different strategy
pulls.unrelated_histories = Merge Failed: The merge head and base do not share a common history. Hint: Try a different strategy
pulls.merge_out_of_date = Merge Failed: Whilst generating the merge, the base was updated. Hint: Try again.
pulls.push_rejected = Merge Failed: The push was rejected with the following message:<br>%s
zeripath marked this conversation as resolved.
Show resolved Hide resolved
pulls.open_unmerged_pull_exists = `You cannot perform a reopen operation because there is a pending pull request (#%d) with identical properties.`
pulls.status_checking = Some checks are pending
pulls.status_checks_success = All checks were successful
Expand Down
4 changes: 4 additions & 0 deletions routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,10 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) {
} else if models.IsErrMergePushOutOfDate(err) {
ctx.Error(http.StatusConflict, "Merge", "merge push out of date")
return
} else if models.IsErrPushRejected(err) {
errPushRej := err.(models.ErrPushRejected)
ctx.Error(http.StatusConflict, "Merge", errPushRej.Message())
return
}
ctx.Error(http.StatusInternalServerError, "Merge", err)
return
Expand Down
6 changes: 6 additions & 0 deletions routers/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,12 @@ func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) {
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date"))
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
return
} else if models.IsErrPushRejected(err) {
log.Debug("MergePushRejected error: %v", err)
pushrejErr := err.(models.ErrPushRejected)
ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected", pushrejErr.Message))
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
return
}
ctx.ServerError("Merge", err)
return
Expand Down
7 changes: 7 additions & 0 deletions services/pull/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,13 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge
StdErr: errbuf.String(),
Err: err,
}
} else if strings.Contains(errbuf.String(), "! [remote rejected]") {
return "", models.ErrPushRejected{
Style: mergeStyle,
StdOut: outbuf.String(),
StdErr: errbuf.String(),
Err: err,
}
}
return "", fmt.Errorf("git push: %s", errbuf.String())
}
Expand Down