Skip to content

Commit c52f81e

Browse files
authored
Ensure rejected push to refs/pull/index/head fails nicely (#11724) (#11809)
Backport #11724 A pre-receive hook that rejects pushes to refs/pull/index/head will cause a broken PR which causes an internal server error whenever it is viewed. This PR handles prevents the internal server error by handling non-existent pr heads and sends a flash error informing the creator there was a problem. Signed-off-by: Andrew Thornton <[email protected]>
1 parent 9749c35 commit c52f81e

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

routers/repo/pull.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,20 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
428428

429429
sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName())
430430
if err != nil {
431+
if git.IsErrNotExist(err) {
432+
ctx.Data["IsPullRequestBroken"] = true
433+
if pull.IsSameRepo() {
434+
ctx.Data["HeadTarget"] = pull.HeadBranch
435+
} else if pull.HeadRepo == nil {
436+
ctx.Data["HeadTarget"] = "<deleted>:" + pull.HeadBranch
437+
} else {
438+
ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch
439+
}
440+
ctx.Data["BaseTarget"] = pull.BaseBranch
441+
ctx.Data["NumCommits"] = 0
442+
ctx.Data["NumFiles"] = 0
443+
return nil
444+
}
431445
ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), err)
432446
return nil
433447
}
@@ -462,12 +476,10 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
462476
ctx.Data["IsPullRequestBroken"] = true
463477
if pull.IsSameRepo() {
464478
ctx.Data["HeadTarget"] = pull.HeadBranch
479+
} else if pull.HeadRepo == nil {
480+
ctx.Data["HeadTarget"] = "<deleted>:" + pull.HeadBranch
465481
} else {
466-
if pull.HeadRepo == nil {
467-
ctx.Data["HeadTarget"] = "<deleted>:" + pull.HeadBranch
468-
} else {
469-
ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch
470-
}
482+
ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch
471483
}
472484
}
473485

@@ -950,6 +962,16 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
950962
if models.IsErrUserDoesNotHaveAccessToRepo(err) {
951963
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error())
952964
return
965+
} else if git.IsErrPushRejected(err) {
966+
pushrejErr := err.(*git.ErrPushRejected)
967+
message := pushrejErr.Message
968+
if len(message) == 0 {
969+
ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message"))
970+
} else {
971+
ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected", utils.SanitizeFlashErrorString(pushrejErr.Message)))
972+
}
973+
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index))
974+
return
953975
}
954976
ctx.ServerError("NewPullRequest", err)
955977
return

services/pull/pull.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,16 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) {
399399
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
400400
Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo),
401401
}); err != nil {
402+
if git.IsErrPushOutOfDate(err) {
403+
// This should not happen as we're using force!
404+
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, err)
405+
return err
406+
} else if git.IsErrPushRejected(err) {
407+
rejectErr := err.(*git.ErrPushRejected)
408+
log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err)
409+
return err
410+
}
411+
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, headFile, err)
402412
return fmt.Errorf("Push: %s:%s %s:%s %v", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), headFile, err)
403413
}
404414

0 commit comments

Comments
 (0)