diff options
author | a1012112796 <1012112796@qq.com> | 2021-08-31 22:03:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-31 16:03:45 +0200 |
commit | cbf05c3f795c1eed999dafe8d0757495e07f1ee2 (patch) | |
tree | e9b227ef8dd8d836b04bd126806c8a1264b750ee /services/pull | |
parent | 2bb32006fd560af44426a06f63f83e3c70c3f258 (diff) | |
download | gitea-cbf05c3f795c1eed999dafe8d0757495e07f1ee2.tar.gz gitea-cbf05c3f795c1eed999dafe8d0757495e07f1ee2.zip |
Add option to update pull request by `rebase` (#16125)
* add option to update pull request by `rebase`
Signed-off-by: a1012112796 <1012112796@qq.com>
Diffstat (limited to 'services/pull')
-rw-r--r-- | services/pull/merge.go | 17 | ||||
-rw-r--r-- | services/pull/update.go | 55 |
2 files changed, 56 insertions, 16 deletions
diff --git a/services/pull/merge.go b/services/pull/merge.go index 7e6a214b87..ef797e1ca4 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -253,6 +253,8 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge } case models.MergeStyleRebase: fallthrough + case models.MergeStyleRebaseUpdate: + fallthrough case models.MergeStyleRebaseMerge: // Checkout head branch if err := git.NewCommand("checkout", "-b", stagingBranch, trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { @@ -305,6 +307,11 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge outbuf.Reset() errbuf.Reset() + // not need merge, just update by rebase. so skip + if mergeStyle == models.MergeStyleRebaseUpdate { + break + } + // Checkout base branch again if err := git.NewCommand("checkout", baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { log.Error("git checkout base prior to merge post staging rebase [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String()) @@ -410,8 +417,16 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge pr.ID, ) + var pushCmd *git.Command + if mergeStyle == models.MergeStyleRebaseUpdate { + // force push the rebase result to head brach + pushCmd = git.NewCommand("push", "-f", "head_repo", stagingBranch+":refs/heads/"+pr.HeadBranch) + } else { + pushCmd = git.NewCommand("push", "origin", baseBranch+":refs/heads/"+pr.BaseBranch) + } + // Push back to upstream. - if err := git.NewCommand("push", "origin", baseBranch+":refs/heads/"+pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil { + if err := pushCmd.RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil { if strings.Contains(errbuf.String(), "non-fast-forward") { return "", &git.ErrPushOutOfDate{ StdOut: outbuf.String(), diff --git a/services/pull/update.go b/services/pull/update.go index c2c13845e3..4b4e67797e 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -13,13 +13,24 @@ import ( ) // Update updates pull request with base branch. -func Update(pull *models.PullRequest, doer *models.User, message string) error { - //use merge functions but switch repo's and branch's - pr := &models.PullRequest{ - HeadRepoID: pull.BaseRepoID, - BaseRepoID: pull.HeadRepoID, - HeadBranch: pull.BaseBranch, - BaseBranch: pull.HeadBranch, +func Update(pull *models.PullRequest, doer *models.User, message string, rebase bool) error { + var ( + pr *models.PullRequest + style models.MergeStyle + ) + + if rebase { + pr = pull + style = models.MergeStyleRebaseUpdate + } else { + //use merge functions but switch repo's and branch's + pr = &models.PullRequest{ + HeadRepoID: pull.BaseRepoID, + BaseRepoID: pull.HeadRepoID, + HeadBranch: pull.BaseBranch, + BaseBranch: pull.HeadBranch, + } + style = models.MergeStyleMerge } if pull.Flow == models.PullRequestFlowAGit { @@ -42,9 +53,13 @@ func Update(pull *models.PullRequest, doer *models.User, message string) error { return fmt.Errorf("HeadBranch of PR %d is up to date", pull.Index) } - _, err = rawMerge(pr, doer, models.MergeStyleMerge, message) + _, err = rawMerge(pr, doer, style, message) defer func() { + if rebase { + go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "") + return + } go AddTestPullRequestTask(doer, pr.HeadRepo.ID, pr.HeadBranch, false, "", "") }() @@ -52,17 +67,17 @@ func Update(pull *models.PullRequest, doer *models.User, message string) error { } // IsUserAllowedToUpdate check if user is allowed to update PR with given permissions and branch protections -func IsUserAllowedToUpdate(pull *models.PullRequest, user *models.User) (bool, error) { +func IsUserAllowedToUpdate(pull *models.PullRequest, user *models.User) (mergeAllowed, rebaseAllowed bool, err error) { if pull.Flow == models.PullRequestFlowAGit { - return false, nil + return false, false, nil } if user == nil { - return false, nil + return false, false, nil } headRepoPerm, err := models.GetUserRepoPermission(pull.HeadRepo, user) if err != nil { - return false, err + return false, false, err } pr := &models.PullRequest{ @@ -74,15 +89,25 @@ func IsUserAllowedToUpdate(pull *models.PullRequest, user *models.User) (bool, e err = pr.LoadProtectedBranch() if err != nil { - return false, err + return false, false, err + } + + // can't do rebase on protected branch because need force push + if pr.ProtectedBranch == nil { + rebaseAllowed = true } // Update function need push permission if pr.ProtectedBranch != nil && !pr.ProtectedBranch.CanUserPush(user.ID) { - return false, nil + return false, false, nil + } + + mergeAllowed, err = IsUserAllowedToMerge(pr, headRepoPerm, user) + if err != nil { + return false, false, err } - return IsUserAllowedToMerge(pr, headRepoPerm, user) + return mergeAllowed, rebaseAllowed, nil } // GetDiverging determines how many commits a PR is ahead or behind the PR base branch |