aboutsummaryrefslogtreecommitdiffstats
path: root/services/pull/pull.go
diff options
context:
space:
mode:
Diffstat (limited to 'services/pull/pull.go')
-rw-r--r--services/pull/pull.go111
1 files changed, 56 insertions, 55 deletions
diff --git a/services/pull/pull.go b/services/pull/pull.go
index db3533ebe4..4f691c0eba 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -9,6 +9,7 @@ import (
"bytes"
"context"
"fmt"
+ "io"
"regexp"
"strings"
"time"
@@ -22,24 +23,25 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
+ "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
issue_service "code.gitea.io/gitea/services/issue"
)
// NewPullRequest creates new pull request with labels for repository.
-func NewPullRequest(repo *repo_model.Repository, pull *models.Issue, labelIDs []int64, uuids []string, pr *models.PullRequest, assigneeIDs []int64) error {
+func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *models.Issue, labelIDs []int64, uuids []string, pr *models.PullRequest, assigneeIDs []int64) error {
if err := TestPatch(pr); err != nil {
return err
}
- divergence, err := GetDiverging(pr)
+ divergence, err := GetDiverging(ctx, pr)
if err != nil {
return err
}
pr.CommitsAhead = divergence.Ahead
pr.CommitsBehind = divergence.Behind
- if err := models.NewPullRequest(repo, pull, labelIDs, uuids, pr); err != nil {
+ if err := models.NewPullRequest(ctx, repo, pull, labelIDs, uuids, pr); err != nil {
return err
}
@@ -52,10 +54,16 @@ func NewPullRequest(repo *repo_model.Repository, pull *models.Issue, labelIDs []
pr.Issue = pull
pull.PullRequest = pr
+ // Now - even if the request context has been cancelled as the PR has been created
+ // in the db and there is no way to cancel that transaction we have to proceed - therefore
+ // create new context and work from there
+ prCtx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("NewPullRequest: %s:%d", repo.FullName(), pr.Index))
+ defer finished()
+
if pr.Flow == models.PullRequestFlowGithub {
- err = PushToBaseRepo(pr)
+ err = PushToBaseRepo(prCtx, pr)
} else {
- err = UpdateRef(pr)
+ err = UpdateRef(prCtx, pr)
}
if err != nil {
return err
@@ -75,7 +83,7 @@ func NewPullRequest(repo *repo_model.Repository, pull *models.Issue, labelIDs []
}
// add first push codes comment
- baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
+ baseGitRepo, err := git.OpenRepositoryCtx(prCtx, pr.BaseRepo.RepoPath())
if err != nil {
return err
}
@@ -115,7 +123,7 @@ func NewPullRequest(repo *repo_model.Repository, pull *models.Issue, labelIDs []
}
// ChangeTargetBranch changes the target branch of this pull request, as the given user.
-func ChangeTargetBranch(pr *models.PullRequest, doer *user_model.User, targetBranch string) (err error) {
+func ChangeTargetBranch(ctx context.Context, pr *models.PullRequest, doer *user_model.User, targetBranch string) (err error) {
// Current target branch is already the same
if pr.BaseBranch == targetBranch {
return nil
@@ -141,7 +149,7 @@ func ChangeTargetBranch(pr *models.PullRequest, doer *user_model.User, targetBra
}
// Check if branches are equal
- branchesEqual, err := IsHeadEqualWithBranch(pr, targetBranch)
+ branchesEqual, err := IsHeadEqualWithBranch(ctx, pr, targetBranch)
if err != nil {
return err
}
@@ -184,7 +192,7 @@ func ChangeTargetBranch(pr *models.PullRequest, doer *user_model.User, targetBra
}
// Update Commit Divergence
- divergence, err := GetDiverging(pr)
+ divergence, err := GetDiverging(ctx, pr)
if err != nil {
return err
}
@@ -211,12 +219,12 @@ func ChangeTargetBranch(pr *models.PullRequest, doer *user_model.User, targetBra
return nil
}
-func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *user_model.User, branch string) error {
+func checkForInvalidation(ctx context.Context, requests models.PullRequestList, repoID int64, doer *user_model.User, branch string) error {
repo, err := repo_model.GetRepositoryByID(repoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID: %v", err)
}
- gitRepo, err := git.OpenRepository(repo.RepoPath())
+ gitRepo, err := git.OpenRepositoryCtx(ctx, repo.RepoPath())
if err != nil {
return fmt.Errorf("git.OpenRepository: %v", err)
}
@@ -251,13 +259,13 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
if err = requests.LoadAttributes(); err != nil {
log.Error("PullRequestList.LoadAttributes: %v", err)
}
- if invalidationErr := checkForInvalidation(requests, repoID, doer, branch); invalidationErr != nil {
+ if invalidationErr := checkForInvalidation(ctx, requests, repoID, doer, branch); invalidationErr != nil {
log.Error("checkForInvalidation: %v", invalidationErr)
}
if err == nil {
for _, pr := range prs {
if newCommitID != "" && newCommitID != git.EmptySHA {
- changed, err := checkIfPRContentChanged(pr, oldCommitID, newCommitID)
+ changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID)
if err != nil {
log.Error("checkIfPRContentChanged: %v", err)
}
@@ -270,7 +278,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
if err := models.MarkReviewsAsNotStale(pr.IssueID, newCommitID); err != nil {
log.Error("MarkReviewsAsNotStale: %v", err)
}
- divergence, err := GetDiverging(pr)
+ divergence, err := GetDiverging(ctx, pr)
if err != nil {
log.Error("GetDiverging: %v", err)
} else {
@@ -290,7 +298,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
for _, pr := range prs {
log.Trace("Updating PR[%d]: composing new test task", pr.ID)
if pr.Flow == models.PullRequestFlowGithub {
- if err := PushToBaseRepo(pr); err != nil {
+ if err := PushToBaseRepo(ctx, pr); err != nil {
log.Error("PushToBaseRepo: %v", err)
continue
}
@@ -299,7 +307,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
}
AddToTaskQueue(pr)
- comment, err := models.CreatePushPullComment(doer, pr, oldCommitID, newCommitID)
+ comment, err := models.CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
if err == nil && comment != nil {
notification.NotifyPullRequestPushCommits(doer, pr, comment)
}
@@ -312,7 +320,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
return
}
for _, pr := range prs {
- divergence, err := GetDiverging(pr)
+ divergence, err := GetDiverging(ctx, pr)
if err != nil {
if models.IsErrBranchDoesNotExist(err) && !git.IsBranchExist(ctx, pr.HeadRepo.RepoPath(), pr.HeadBranch) {
log.Warn("Cannot test PR %s/%d: head_branch %s no longer exists", pr.BaseRepo.Name, pr.IssueID, pr.HeadBranch)
@@ -332,7 +340,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
// checkIfPRContentChanged checks if diff to target branch has changed by push
// A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged
-func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) {
+func checkIfPRContentChanged(ctx context.Context, pr *models.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) {
if err = pr.LoadHeadRepo(); err != nil {
return false, fmt.Errorf("LoadHeadRepo: %v", err)
} else if pr.HeadRepo == nil {
@@ -344,7 +352,7 @@ func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID st
return false, fmt.Errorf("LoadBaseRepo: %v", err)
}
- headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
+ headGitRepo, err := git.OpenRepositoryCtx(ctx, pr.HeadRepo.RepoPath())
if err != nil {
return false, fmt.Errorf("OpenRepository: %v", err)
}
@@ -404,11 +412,11 @@ func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID st
// PushToBaseRepo pushes commits from branches of head repository to
// corresponding branches of base repository.
// FIXME: Only push branches that are actually updates?
-func PushToBaseRepo(pr *models.PullRequest) (err error) {
- return pushToBaseRepoHelper(pr, "")
+func PushToBaseRepo(ctx context.Context, pr *models.PullRequest) (err error) {
+ return pushToBaseRepoHelper(ctx, pr, "")
}
-func pushToBaseRepoHelper(pr *models.PullRequest, prefixHeadBranch string) (err error) {
+func pushToBaseRepoHelper(ctx context.Context, pr *models.PullRequest, prefixHeadBranch string) (err error) {
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName())
if err := pr.LoadHeadRepo(); err != nil {
@@ -432,7 +440,7 @@ func pushToBaseRepoHelper(pr *models.PullRequest, prefixHeadBranch string) (err
gitRefName := pr.GetGitRefName()
- if err := git.Push(git.DefaultContext, headRepoPath, git.PushOptions{
+ if err := git.Push(ctx, headRepoPath, git.PushOptions{
Remote: baseRepoPath,
Branch: prefixHeadBranch + pr.HeadBranch + ":" + gitRefName,
Force: true,
@@ -452,8 +460,8 @@ func pushToBaseRepoHelper(pr *models.PullRequest, prefixHeadBranch string) (err
log.Info("Can't push with %s%s", prefixHeadBranch, pr.HeadBranch)
return err
}
- log.Info("Retrying to push with "+git.BranchPrefix+"%s", pr.HeadBranch)
- err = pushToBaseRepoHelper(pr, git.BranchPrefix)
+ log.Info("Retrying to push with %s%s", git.BranchPrefix, pr.HeadBranch)
+ err = pushToBaseRepoHelper(ctx, pr, git.BranchPrefix)
return err
}
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
@@ -464,14 +472,14 @@ func pushToBaseRepoHelper(pr *models.PullRequest, prefixHeadBranch string) (err
}
// UpdateRef update refs/pull/id/head directly for agit flow pull request
-func UpdateRef(pr *models.PullRequest) (err error) {
+func UpdateRef(ctx context.Context, pr *models.PullRequest) (err error) {
log.Trace("UpdateRef[%d]: upgate pull request ref in base repo '%s'", pr.ID, pr.GetGitRefName())
if err := pr.LoadBaseRepo(); err != nil {
log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err)
return err
}
- _, err = git.NewCommand("update-ref", pr.GetGitRefName(), pr.HeadCommitID).RunInDir(pr.BaseRepo.RepoPath())
+ _, err = git.NewCommandContext(ctx, "update-ref", pr.GetGitRefName(), pr.HeadCommitID).RunInDir(pr.BaseRepo.RepoPath())
if err != nil {
log.Error("Unable to update ref in base repository for PR[%d] Error: %v", pr.ID, err)
}
@@ -525,8 +533,8 @@ func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error
}
// CloseRepoBranchesPulls close all pull requests which head branches are in the given repository, but only whose base repo is not in the given repository
-func CloseRepoBranchesPulls(doer *user_model.User, repo *repo_model.Repository) error {
- branches, _, err := git.GetBranchesByPath(repo.RepoPath(), 0, 0)
+func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) error {
+ branches, _, err := git.GetBranchesByPath(ctx, repo.RepoPath(), 0, 0)
if err != nil {
return err
}
@@ -563,7 +571,7 @@ func CloseRepoBranchesPulls(doer *user_model.User, repo *repo_model.Repository)
var commitMessageTrailersPattern = regexp.MustCompile(`(?:^|\n\n)(?:[\w-]+[ \t]*:[^\n]+\n*(?:[ \t]+[^\n]+\n*)*)+$`)
// GetSquashMergeCommitMessages returns the commit messages between head and merge base (if there is one)
-func GetSquashMergeCommitMessages(pr *models.PullRequest) string {
+func GetSquashMergeCommitMessages(ctx context.Context, pr *models.PullRequest) string {
if err := pr.LoadIssue(); err != nil {
log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err)
return ""
@@ -583,12 +591,12 @@ func GetSquashMergeCommitMessages(pr *models.PullRequest) string {
}
}
- gitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
+ gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath())
if err != nil {
log.Error("Unable to open head repository: Error: %v", err)
return ""
}
- defer gitRepo.Close()
+ defer closer.Close()
var headCommit *git.Commit
if pr.Flow == models.PullRequestFlowGithub {
@@ -719,7 +727,7 @@ func GetSquashMergeCommitMessages(pr *models.PullRequest) string {
}
// GetIssuesLastCommitStatus returns a map
-func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.CommitStatus, error) {
+func GetIssuesLastCommitStatus(ctx context.Context, issues models.IssueList) (map[int64]*models.CommitStatus, error) {
if err := issues.LoadPullRequests(); err != nil {
return nil, err
}
@@ -744,7 +752,7 @@ func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.Commi
}
gitRepo, ok := gitRepos[issue.RepoID]
if !ok {
- gitRepo, err = git.OpenRepository(issue.Repo.RepoPath())
+ gitRepo, err = git.OpenRepositoryCtx(ctx, issue.Repo.RepoPath())
if err != nil {
log.Error("Cannot open git repository %-v for issue #%d[%d]. Error: %v", issue.Repo, issue.Index, issue.ID, err)
continue
@@ -762,20 +770,6 @@ func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.Commi
return res, nil
}
-// GetLastCommitStatus returns list of commit statuses for latest commit on this pull request.
-func GetLastCommitStatus(pr *models.PullRequest) (status *models.CommitStatus, err error) {
- if err = pr.LoadBaseRepo(); err != nil {
- return nil, err
- }
- gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
- if err != nil {
- return nil, err
- }
- defer gitRepo.Close()
-
- return getLastCommitStatus(gitRepo, pr)
-}
-
// getLastCommitStatus get pr's last commit status. PR's last commit status is the head commit id's last commit status
func getLastCommitStatus(gitRepo *git.Repository, pr *models.PullRequest) (status *models.CommitStatus, err error) {
sha, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
@@ -791,16 +785,16 @@ func getLastCommitStatus(gitRepo *git.Repository, pr *models.PullRequest) (statu
}
// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head
-func IsHeadEqualWithBranch(pr *models.PullRequest, branchName string) (bool, error) {
+func IsHeadEqualWithBranch(ctx context.Context, pr *models.PullRequest, branchName string) (bool, error) {
var err error
if err = pr.LoadBaseRepo(); err != nil {
return false, err
}
- baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
+ baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath())
if err != nil {
return false, err
}
- defer baseGitRepo.Close()
+ defer closer.Close()
baseCommit, err := baseGitRepo.GetBranchCommit(branchName)
if err != nil {
@@ -810,11 +804,18 @@ func IsHeadEqualWithBranch(pr *models.PullRequest, branchName string) (bool, err
if err = pr.LoadHeadRepo(); err != nil {
return false, err
}
- headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
- if err != nil {
- return false, err
+ var headGitRepo *git.Repository
+ if pr.HeadRepoID == pr.BaseRepoID {
+ headGitRepo = baseGitRepo
+ } else {
+ var closer io.Closer
+
+ headGitRepo, closer, err = git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath())
+ if err != nil {
+ return false, err
+ }
+ defer closer.Close()
}
- defer headGitRepo.Close()
var headCommit *git.Commit
if pr.Flow == models.PullRequestFlowGithub {