mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Handle push rejection in branch and upload (#10854)
* Handle push rejections and push out-of-date in branch creation and file upload. * Remove the duplicated sanitize from services/pull/merge * Move the errors Err(Merge)PushOutOfDate and ErrPushRejected to modules/git * Handle errors better in the upload file dialogs Fix #10460 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
This commit is contained in:
@@ -678,11 +678,11 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) {
|
||||
} else if models.IsErrMergeUnrelatedHistories(err) {
|
||||
conflictError := err.(models.ErrMergeUnrelatedHistories)
|
||||
ctx.JSON(http.StatusConflict, conflictError)
|
||||
} else if models.IsErrMergePushOutOfDate(err) {
|
||||
} else if git.IsErrPushOutOfDate(err) {
|
||||
ctx.Error(http.StatusConflict, "Merge", "merge push out of date")
|
||||
return
|
||||
} else if models.IsErrPushRejected(err) {
|
||||
errPushRej := err.(models.ErrPushRejected)
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
errPushRej := err.(*git.ErrPushRejected)
|
||||
if len(errPushRej.Message) == 0 {
|
||||
ctx.Error(http.StatusConflict, "Merge", "PushRejected without remote error message")
|
||||
return
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/repofiles"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -335,9 +336,8 @@ func CreateBranch(ctx *context.Context, form auth.NewBranchForm) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
|
||||
return
|
||||
}
|
||||
if models.IsErrBranchAlreadyExists(err) {
|
||||
e := err.(models.ErrBranchAlreadyExists)
|
||||
ctx.Flash.Error(ctx.Tr("repo.branch.branch_already_exists", e.BranchName))
|
||||
if models.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.branch.branch_already_exists", form.NewBranchName))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
|
||||
return
|
||||
}
|
||||
@@ -347,6 +347,16 @@ func CreateBranch(ctx *context.Context, form auth.NewBranchForm) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
|
||||
return
|
||||
}
|
||||
if git.IsErrPushRejected(err) {
|
||||
e := err.(*git.ErrPushRejected)
|
||||
if len(e.Message) == 0 {
|
||||
ctx.Flash.Error(ctx.Tr("repo.editor.push_rejected_no_message"))
|
||||
} else {
|
||||
ctx.Flash.Error(ctx.Tr("repo.editor.push_rejected", utils.SanitizeFlashErrorString(e.Message)))
|
||||
}
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
|
||||
return
|
||||
}
|
||||
|
||||
ctx.ServerError("CreateNewBranch", err)
|
||||
return
|
||||
|
@@ -228,6 +228,9 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
// This is where we handle all the errors thrown by repofiles.CreateOrUpdateRepoFile
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", ctx.Repo.TreePath), tplEditFile, &form)
|
||||
} else if models.IsErrLFSFileLocked(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(models.ErrLFSFileLocked).Path, err.(models.ErrLFSFileLocked).UserName), tplEditFile, &form)
|
||||
} else if models.IsErrFilenameInvalid(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplEditFile, &form)
|
||||
@@ -265,10 +268,12 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
} else {
|
||||
ctx.Error(500, err.Error())
|
||||
}
|
||||
} else if models.IsErrCommitIDDoesNotMatch(err) || models.IsErrMergePushOutOfDate(err) {
|
||||
} else if models.IsErrCommitIDDoesNotMatch(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplEditFile, &form)
|
||||
} else if models.IsErrPushRejected(err) {
|
||||
errPushRej := err.(models.ErrPushRejected)
|
||||
} else if git.IsErrPushOutOfDate(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+form.NewBranchName), tplEditFile, &form)
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
errPushRej := err.(*git.ErrPushRejected)
|
||||
if len(errPushRej.Message) == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplEditFile, &form)
|
||||
} else {
|
||||
@@ -436,10 +441,10 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
} else {
|
||||
ctx.Error(500, err.Error())
|
||||
}
|
||||
} else if models.IsErrCommitIDDoesNotMatch(err) || models.IsErrMergePushOutOfDate(err) {
|
||||
} else if models.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplDeleteFile, &form)
|
||||
} else if models.IsErrPushRejected(err) {
|
||||
errPushRej := err.(models.ErrPushRejected)
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
errPushRej := err.(*git.ErrPushRejected)
|
||||
if len(errPushRej.Message) == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplDeleteFile, &form)
|
||||
} else {
|
||||
@@ -602,10 +607,48 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
Message: message,
|
||||
Files: form.Files,
|
||||
}); err != nil {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
if models.IsErrLFSFileLocked(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(models.ErrLFSFileLocked).Path, err.(models.ErrLFSFileLocked).UserName), tplUploadFile, &form)
|
||||
} else if models.IsErrFilenameInvalid(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplUploadFile, &form)
|
||||
} else if models.IsErrFilePathInvalid(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
fileErr := err.(models.ErrFilePathInvalid)
|
||||
switch fileErr.Type {
|
||||
case git.EntryModeSymlink:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplUploadFile, &form)
|
||||
case git.EntryModeTree:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplUploadFile, &form)
|
||||
case git.EntryModeBlob:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplUploadFile, &form)
|
||||
default:
|
||||
ctx.Error(500, err.Error())
|
||||
}
|
||||
} else if models.IsErrRepoFileAlreadyExists(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplUploadFile, &form)
|
||||
} else if git.IsErrBranchNotExist(err) {
|
||||
branchErr := err.(git.ErrBranchNotExist)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name), tplUploadFile, &form)
|
||||
} else if models.IsErrBranchAlreadyExists(err) {
|
||||
// For when a user specifies a new branch that already exists
|
||||
ctx.Data["Err_NewBranchName"] = true
|
||||
branchErr := err.(models.ErrBranchAlreadyExists)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplUploadFile, &form)
|
||||
} else if git.IsErrPushOutOfDate(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+ctx.Repo.CommitID+"..."+form.NewBranchName), tplUploadFile, &form)
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
errPushRej := err.(*git.ErrPushRejected)
|
||||
if len(errPushRej.Message) == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected_no_message"), tplUploadFile, &form)
|
||||
} else {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.push_rejected", utils.SanitizeFlashErrorString(errPushRej.Message)), tplUploadFile, &form)
|
||||
}
|
||||
} else {
|
||||
// os.ErrNotExist - upload file missing in the intervening time?!
|
||||
log.Error("Error during upload to repo: %-v to filepath: %s on %s from %s: %v", ctx.Repo.Repository, form.TreePath, oldBranchName, form.NewBranchName, err)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.unable_to_upload_files", form.TreePath, err), tplUploadFile, &form)
|
||||
}
|
||||
return
|
||||
|
@@ -10,7 +10,6 @@ import (
|
||||
"container/list"
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
@@ -668,18 +667,9 @@ func UpdatePullRequest(ctx *context.Context) {
|
||||
message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch)
|
||||
|
||||
if err = pull_service.Update(issue.PullRequest, ctx.User, message); err != nil {
|
||||
sanitize := func(x string) string {
|
||||
runes := []rune(x)
|
||||
|
||||
if len(runes) > 512 {
|
||||
x = "..." + string(runes[len(runes)-512:])
|
||||
}
|
||||
|
||||
return strings.Replace(html.EscapeString(x), "\n", "<br>", -1)
|
||||
}
|
||||
if models.IsErrMergeConflicts(err) {
|
||||
conflictError := err.(models.ErrMergeConflicts)
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_conflict", sanitize(conflictError.StdErr), sanitize(conflictError.StdOut)))
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_conflict", utils.SanitizeFlashErrorString(conflictError.StdErr), utils.SanitizeFlashErrorString(conflictError.StdOut)))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
|
||||
return
|
||||
}
|
||||
@@ -814,14 +804,14 @@ func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories"))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
||||
return
|
||||
} else if models.IsErrMergePushOutOfDate(err) {
|
||||
} else if git.IsErrPushOutOfDate(err) {
|
||||
log.Debug("MergePushOutOfDate error: %v", err)
|
||||
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) {
|
||||
} else if git.IsErrPushRejected(err) {
|
||||
log.Debug("MergePushRejected error: %v", err)
|
||||
pushrejErr := err.(models.ErrPushRejected)
|
||||
pushrejErr := err.(*git.ErrPushRejected)
|
||||
message := pushrejErr.Message
|
||||
if len(message) == 0 {
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message"))
|
||||
|
Reference in New Issue
Block a user