diff options
author | zeripath <art27@cantab.net> | 2021-12-20 00:32:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-20 08:32:54 +0800 |
commit | e4e411821d985cf8f9007d9640909ab9ee271dd7 (patch) | |
tree | 11af3c3a933949d0561f1e292acd8296181a63db /services | |
parent | b24a965b81d5aa4e7bd87c6a4c6370d7e0ec9a50 (diff) | |
download | gitea-e4e411821d985cf8f9007d9640909ab9ee271dd7.tar.gz gitea-e4e411821d985cf8f9007d9640909ab9ee271dd7.zip |
Abort merge if head has been updated before pressing merge (#18032)
* Abort merge if head has been updated before pressing merge
It is possible that a PR head may be pushed to between the merge page being shown
and the merge button being pressed. Pass the current expected head in as a parameter
and cancel the merge if it has changed.
Fix #18028
Signed-off-by: Andrew Thornton <art27@cantab.net>
* adjust swagger
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fix test
Signed-off-by: Andrew Thornton <art27@cantab.net>
* placate lint
Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'services')
-rw-r--r-- | services/forms/repo_form.go | 1 | ||||
-rw-r--r-- | services/pull/merge.go | 20 | ||||
-rw-r--r-- | services/pull/update.go | 2 |
3 files changed, 19 insertions, 4 deletions
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index c571951bb9..19b5a37664 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -571,6 +571,7 @@ type MergePullRequestForm struct { MergeTitleField string MergeMessageField string MergeCommitID string // only used for manually-merged + HeadCommitID string `json:"head_commit_id,omitempty"` ForceMerge *bool `json:"force_merge,omitempty"` DeleteBranchAfterMerge bool `json:"delete_branch_after_merge,omitempty"` } diff --git a/services/pull/merge.go b/services/pull/merge.go index ab1f43a50a..e541495bef 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -34,7 +34,7 @@ import ( // Merge merges pull request to base repository. // Caller should check PR is ready to be merged (review and status checks) // FIXME: add repoWorkingPull make sure two merges does not happen at same time. -func Merge(pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, message string) (err error) { +func Merge(pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) (err error) { if err = pr.LoadHeadRepo(); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %v", err) @@ -59,7 +59,7 @@ func Merge(pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repos go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "") }() - pr.MergedCommitID, err = rawMerge(pr, doer, mergeStyle, message) + pr.MergedCommitID, err = rawMerge(pr, doer, mergeStyle, expectedHeadCommitID, message) if err != nil { return err } @@ -114,7 +114,7 @@ func Merge(pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repos } // rawMerge perform the merge operation without changing any pull information in database -func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, message string) (string, error) { +func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) (string, error) { err := git.LoadGitVersion() if err != nil { log.Error("git.LoadGitVersion: %v", err) @@ -137,6 +137,20 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod trackingBranch := "tracking" stagingBranch := "staging" + if expectedHeadCommitID != "" { + trackingCommitID, err := git.NewCommand("show-ref", "--hash", git.BranchPrefix+trackingBranch).RunInDir(tmpBasePath) + if err != nil { + log.Error("show-ref[%s] --hash refs/heads/trackingn: %v", tmpBasePath, git.BranchPrefix+trackingBranch, err) + return "", fmt.Errorf("getDiffTree: %v", err) + } + if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID { + return "", models.ErrSHADoesNotMatch{ + GivenSHA: expectedHeadCommitID, + CurrentSHA: trackingCommitID, + } + } + } + var outbuf, errbuf strings.Builder // Enable sparse-checkout diff --git a/services/pull/update.go b/services/pull/update.go index 25c6d36308..8ca7e4cee7 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -55,7 +55,7 @@ func Update(pull *models.PullRequest, doer *user_model.User, message string, reb return fmt.Errorf("HeadBranch of PR %d is up to date", pull.Index) } - _, err = rawMerge(pr, doer, style, message) + _, err = rawMerge(pr, doer, style, "", message) defer func() { if rebase { |