summaryrefslogtreecommitdiffstats
path: root/services/pull
diff options
context:
space:
mode:
authora1012112796 <1012112796@qq.com>2021-08-31 22:03:45 +0800
committerGitHub <noreply@github.com>2021-08-31 16:03:45 +0200
commitcbf05c3f795c1eed999dafe8d0757495e07f1ee2 (patch)
treee9b227ef8dd8d836b04bd126806c8a1264b750ee /services/pull
parent2bb32006fd560af44426a06f63f83e3c70c3f258 (diff)
downloadgitea-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.go17
-rw-r--r--services/pull/update.go55
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