mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 15:04:00 +01:00 
			
		
		
		
	Refresh the refernce of the closed PR when reopening (#24231)
Close #24213 
Replace #23830
#### Cause
- Before, in order to making PR can get latest commit after reopening,
the `ref`(${REPO_PATH}/refs/pull/${PR_INDEX}/head) of evrey closed PR
will be updated when pushing commits to the `head branch` of the closed
PR.
#### Changes
- For closed PR , won't perform these behavior: insert`comment`, push
`notification` (UI and email), exectue
[pushToBaseRepo](7422503341/services/pull/pull.go (L409))
function and trigger `action` any more when pushing to the `head branch`
of the closed PR.
- Refresh the reference of the PR when reopening the closed PR (**even
if the head branch has been deleted before**). Make the reference of PR
consistent with the `head branch`.
			
			
This commit is contained in:
		
							parent
							
								
									80765aab8c
								
							
						
					
					
						commit
						e962ade99c
					
				@ -433,6 +433,10 @@ func (pr *PullRequest) GetGitRefName() string {
 | 
				
			|||||||
	return fmt.Sprintf("%s%d/head", git.PullPrefix, pr.Index)
 | 
						return fmt.Sprintf("%s%d/head", git.PullPrefix, pr.Index)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pr *PullRequest) GetGitHeadBranchRefName() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%s%s", git.BranchPrefix, pr.HeadBranch)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsChecking returns true if this pull request is still checking conflict.
 | 
					// IsChecking returns true if this pull request is still checking conflict.
 | 
				
			||||||
func (pr *PullRequest) IsChecking() bool {
 | 
					func (pr *PullRequest) IsChecking() bool {
 | 
				
			||||||
	return pr.Status == PullRequestStatusChecking
 | 
						return pr.Status == PullRequestStatusChecking
 | 
				
			||||||
 | 
				
			|||||||
@ -51,16 +51,11 @@ func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xor
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
 | 
					// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
 | 
				
			||||||
// by given head information (repo and branch).
 | 
					func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
 | 
				
			||||||
// arg `includeClosed` controls whether the SQL returns closed PRs
 | 
					 | 
				
			||||||
func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string, includeClosed bool) ([]*PullRequest, error) {
 | 
					 | 
				
			||||||
	prs := make([]*PullRequest, 0, 2)
 | 
						prs := make([]*PullRequest, 0, 2)
 | 
				
			||||||
	sess := db.GetEngine(db.DefaultContext).
 | 
						sess := db.GetEngine(db.DefaultContext).
 | 
				
			||||||
		Join("INNER", "issue", "issue.id = pull_request.issue_id").
 | 
							Join("INNER", "issue", "issue.id = pull_request.issue_id").
 | 
				
			||||||
		Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND flow = ?", repoID, branch, false, PullRequestFlowGithub)
 | 
							Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?", repoID, branch, false, false, PullRequestFlowGithub)
 | 
				
			||||||
	if !includeClosed {
 | 
					 | 
				
			||||||
		sess.Where("issue.is_closed = ?", false)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return prs, sess.Find(&prs)
 | 
						return prs, sess.Find(&prs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -74,7 +69,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *
 | 
				
			|||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch, false)
 | 
						prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -118,7 +118,7 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
 | 
					func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, unittest.PrepareTestDatabase())
 | 
						assert.NoError(t, unittest.PrepareTestDatabase())
 | 
				
			||||||
	prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2", false)
 | 
						prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2")
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, prs, 1)
 | 
						assert.Len(t, prs, 1)
 | 
				
			||||||
	for _, pr := range prs {
 | 
						for _, pr := range prs {
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup"
 | 
						"code.gitea.io/gitea/modules/markup"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup/markdown"
 | 
						"code.gitea.io/gitea/modules/markup/markdown"
 | 
				
			||||||
 | 
						repo_module "code.gitea.io/gitea/modules/repository"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/templates/vars"
 | 
						"code.gitea.io/gitea/modules/templates/vars"
 | 
				
			||||||
@ -2784,7 +2785,8 @@ func NewComment(ctx *context.Context) {
 | 
				
			|||||||
				pr, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow)
 | 
									pr, err = issues_model.GetUnmergedPullRequest(ctx, pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch, pull.Flow)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					if !issues_model.IsErrPullRequestNotExist(err) {
 | 
										if !issues_model.IsErrPullRequestNotExist(err) {
 | 
				
			||||||
						ctx.ServerError("GetUnmergedPullRequest", err)
 | 
											ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
 | 
				
			||||||
 | 
											ctx.Redirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, pull.Index))
 | 
				
			||||||
						return
 | 
											return
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -2794,6 +2796,57 @@ func NewComment(ctx *context.Context) {
 | 
				
			|||||||
					issue.PullRequest.HeadCommitID = ""
 | 
										issue.PullRequest.HeadCommitID = ""
 | 
				
			||||||
					pull_service.AddToTaskQueue(issue.PullRequest)
 | 
										pull_service.AddToTaskQueue(issue.PullRequest)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// check whether the ref of PR <refs/pulls/pr_index/head> in base repo is consistent with the head commit of head branch in the head repo
 | 
				
			||||||
 | 
									// get head commit of PR
 | 
				
			||||||
 | 
									prHeadRef := pull.GetGitRefName()
 | 
				
			||||||
 | 
									if err := pull.LoadBaseRepo(ctx); err != nil {
 | 
				
			||||||
 | 
										ctx.ServerError("Unable to load base repo", err)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									prHeadCommitID, err := git.GetFullCommitID(ctx, pull.BaseRepo.RepoPath(), prHeadRef)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										ctx.ServerError("Get head commit Id of pr fail", err)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// get head commit of branch in the head repo
 | 
				
			||||||
 | 
									if err := pull.LoadHeadRepo(ctx); err != nil {
 | 
				
			||||||
 | 
										ctx.ServerError("Unable to load head repo", err)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if ok := git.IsBranchExist(ctx, pull.HeadRepo.RepoPath(), pull.BaseBranch); !ok {
 | 
				
			||||||
 | 
										// todo localize
 | 
				
			||||||
 | 
										ctx.Flash.Error("The origin branch is delete, cannot reopen.")
 | 
				
			||||||
 | 
										ctx.Redirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, pull.Index))
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									headBranchRef := pull.GetGitHeadBranchRefName()
 | 
				
			||||||
 | 
									headBranchCommitID, err := git.GetFullCommitID(ctx, pull.HeadRepo.RepoPath(), headBranchRef)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										ctx.ServerError("Get head commit Id of head branch fail", err)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									err = pull.LoadIssue(ctx)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										ctx.ServerError("load the issue of pull request error", err)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if prHeadCommitID != headBranchCommitID {
 | 
				
			||||||
 | 
										// force push to base repo
 | 
				
			||||||
 | 
										err := git.Push(ctx, pull.HeadRepo.RepoPath(), git.PushOptions{
 | 
				
			||||||
 | 
											Remote: pull.BaseRepo.RepoPath(),
 | 
				
			||||||
 | 
											Branch: pull.HeadBranch + ":" + prHeadRef,
 | 
				
			||||||
 | 
											Force:  true,
 | 
				
			||||||
 | 
											Env:    repo_module.InternalPushingEnvironment(pull.Issue.Poster, pull.BaseRepo),
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											ctx.ServerError("force push error", err)
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if pr != nil {
 | 
								if pr != nil {
 | 
				
			||||||
@ -2822,6 +2875,7 @@ func NewComment(ctx *context.Context) {
 | 
				
			|||||||
					log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
 | 
										log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Redirect to comment hashtag if there is any actual content.
 | 
							// Redirect to comment hashtag if there is any actual content.
 | 
				
			||||||
 | 
				
			|||||||
@ -257,7 +257,8 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
 | 
				
			|||||||
		// If you don't let it run all the way then you will lose data
 | 
							// If you don't let it run all the way then you will lose data
 | 
				
			||||||
		// TODO: graceful: AddTestPullRequestTask needs to become a queue!
 | 
							// TODO: graceful: AddTestPullRequestTask needs to become a queue!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch, true)
 | 
							// GetUnmergedPullRequestsByHeadInfo() only return open and unmerged PR.
 | 
				
			||||||
 | 
							prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
 | 
								log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@ -274,12 +275,9 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
 | 
				
			|||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// If the PR is closed, someone still push some commits to the PR,
 | 
					 | 
				
			||||||
			// 1. We will insert comments of commits, but hidden until the PR is reopened.
 | 
					 | 
				
			||||||
			// 2. We won't send any notification.
 | 
					 | 
				
			||||||
			AddToTaskQueue(pr)
 | 
								AddToTaskQueue(pr)
 | 
				
			||||||
			comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
 | 
								comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
 | 
				
			||||||
			if err == nil && comment != nil && !pr.Issue.IsClosed {
 | 
								if err == nil && comment != nil {
 | 
				
			||||||
				notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment)
 | 
									notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -294,10 +292,6 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			if err == nil {
 | 
								if err == nil {
 | 
				
			||||||
				for _, pr := range prs {
 | 
									for _, pr := range prs {
 | 
				
			||||||
					if pr.Issue.IsClosed {
 | 
					 | 
				
			||||||
						// The closed PR never trigger action or webhook
 | 
					 | 
				
			||||||
						continue
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if newCommitID != "" && newCommitID != git.EmptySHA {
 | 
										if newCommitID != "" && newCommitID != git.EmptySHA {
 | 
				
			||||||
						changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID)
 | 
											changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID)
 | 
				
			||||||
						if err != nil {
 | 
											if err != nil {
 | 
				
			||||||
@ -503,7 +497,7 @@ func (errs errlist) Error() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// CloseBranchPulls close all the pull requests who's head branch is the branch
 | 
					// CloseBranchPulls close all the pull requests who's head branch is the branch
 | 
				
			||||||
func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error {
 | 
					func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error {
 | 
				
			||||||
	prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch, false)
 | 
						prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -539,7 +533,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var errs errlist
 | 
						var errs errlist
 | 
				
			||||||
	for _, branch := range branches {
 | 
						for _, branch := range branches {
 | 
				
			||||||
		prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name, false)
 | 
							prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user