summaryrefslogtreecommitdiffstats
path: root/services/pull
diff options
context:
space:
mode:
Diffstat (limited to 'services/pull')
-rw-r--r--services/pull/check.go58
-rw-r--r--services/pull/commit_status.go12
-rw-r--r--services/pull/lfs.go9
-rw-r--r--services/pull/merge.go71
-rw-r--r--services/pull/patch.go30
-rw-r--r--services/pull/pull.go111
-rw-r--r--services/pull/review.go25
-rw-r--r--services/pull/temp_repo.go17
-rw-r--r--services/pull/update.go13
9 files changed, 185 insertions, 161 deletions
diff --git a/services/pull/check.go b/services/pull/check.go
index 363a716b28..3615c6c654 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
+ "code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -69,7 +70,7 @@ func checkAndUpdateStatus(pr *models.PullRequest) {
// getMergeCommit checks if a pull request got merged
// Returns the git.Commit of the pull request if merged
-func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
+func getMergeCommit(ctx context.Context, pr *models.PullRequest) (*git.Commit, error) {
if pr.BaseRepo == nil {
var err error
pr.BaseRepo, err = repo_model.GetRepositoryByID(pr.BaseRepoID)
@@ -91,7 +92,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
headFile := pr.GetGitRefName()
// Check if a pull request is merged into BaseBranch
- _, err = git.NewCommand("merge-base", "--is-ancestor", headFile, pr.BaseBranch).
+ _, err = git.NewCommandContext(ctx, "merge-base", "--is-ancestor", headFile, pr.BaseBranch).
RunInDirWithEnv(pr.BaseRepo.RepoPath(), []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()})
if err != nil {
// Errors are signaled by a non-zero status that is not 1
@@ -112,7 +113,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
cmd := commitID[:40] + ".." + pr.BaseBranch
// Get the commit from BaseBranch where the pull request got merged
- mergeCommit, err := git.NewCommand("rev-list", "--ancestry-path", "--merges", "--reverse", cmd).
+ mergeCommit, err := git.NewCommandContext(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse", cmd).
RunInDirWithEnv("", []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()})
if err != nil {
return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %v", err)
@@ -121,7 +122,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
mergeCommit = commitID[:40]
}
- gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
+ gitRepo, err := git.OpenRepositoryCtx(ctx, pr.BaseRepo.RepoPath())
if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err)
}
@@ -137,7 +138,7 @@ func getMergeCommit(pr *models.PullRequest) (*git.Commit, error) {
// manuallyMerged checks if a pull request got manually merged
// When a pull request got manually merged mark the pull request as merged
-func manuallyMerged(pr *models.PullRequest) bool {
+func manuallyMerged(ctx context.Context, pr *models.PullRequest) bool {
if err := pr.LoadBaseRepo(); err != nil {
log.Error("PullRequest[%d].LoadBaseRepo: %v", pr.ID, err)
return false
@@ -153,7 +154,7 @@ func manuallyMerged(pr *models.PullRequest) bool {
return false
}
- commit, err := getMergeCommit(pr)
+ commit, err := getMergeCommit(ctx, pr)
if err != nil {
log.Error("PullRequest[%d].getMergeCommit: %v", pr.ID, err)
return false
@@ -219,26 +220,37 @@ func handle(data ...queue.Data) {
for _, datum := range data {
id, _ := strconv.ParseInt(datum.(string), 10, 64)
- log.Trace("Testing PR ID %d from the pull requests patch checking queue", id)
+ testPR(id)
+ }
+}
- pr, err := models.GetPullRequestByID(id)
- if err != nil {
- log.Error("GetPullRequestByID[%s]: %v", datum, err)
- continue
- } else if pr.HasMerged {
- continue
- } else if manuallyMerged(pr) {
- continue
- } else if err = TestPatch(pr); err != nil {
- log.Error("testPatch[%d]: %v", pr.ID, err)
- pr.Status = models.PullRequestStatusError
- if err := pr.UpdateCols("status"); err != nil {
- log.Error("update pr [%d] status to PullRequestStatusError failed: %v", pr.ID, err)
- }
- continue
+func testPR(id int64) {
+ ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("Test PR[%d] from patch checking queue", id))
+ defer finished()
+
+ pr, err := models.GetPullRequestByID(id)
+ if err != nil {
+ log.Error("GetPullRequestByID[%d]: %v", id, err)
+ return
+ }
+
+ if pr.HasMerged {
+ return
+ }
+
+ if manuallyMerged(ctx, pr) {
+ return
+ }
+
+ if err := TestPatch(pr); err != nil {
+ log.Error("testPatch[%d]: %v", pr.ID, err)
+ pr.Status = models.PullRequestStatusError
+ if err := pr.UpdateCols("status"); err != nil {
+ log.Error("update pr [%d] status to PullRequestStatusError failed: %v", pr.ID, err)
}
- checkAndUpdateStatus(pr)
+ return
}
+ checkAndUpdateStatus(pr)
}
// CheckPrsForBaseBranch check all pulls with bseBrannch
diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go
index 5324b49fa9..d605f8e301 100644
--- a/services/pull/commit_status.go
+++ b/services/pull/commit_status.go
@@ -6,6 +6,8 @@
package pull
import (
+ "context"
+
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/git"
@@ -80,7 +82,7 @@ func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, require
}
// IsPullCommitStatusPass returns if all required status checks PASS
-func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
+func IsPullCommitStatusPass(ctx context.Context, pr *models.PullRequest) (bool, error) {
if err := pr.LoadProtectedBranch(); err != nil {
return false, errors.Wrap(err, "GetLatestCommitStatus")
}
@@ -88,7 +90,7 @@ func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
return true, nil
}
- state, err := GetPullRequestCommitStatusState(pr)
+ state, err := GetPullRequestCommitStatusState(ctx, pr)
if err != nil {
return false, err
}
@@ -96,18 +98,18 @@ func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
}
// GetPullRequestCommitStatusState returns pull request merged commit status state
-func GetPullRequestCommitStatusState(pr *models.PullRequest) (structs.CommitStatusState, error) {
+func GetPullRequestCommitStatusState(ctx context.Context, pr *models.PullRequest) (structs.CommitStatusState, error) {
// Ensure HeadRepo is loaded
if err := pr.LoadHeadRepo(); err != nil {
return "", errors.Wrap(err, "LoadHeadRepo")
}
// check if all required status checks are successful
- headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
+ headGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath())
if err != nil {
return "", errors.Wrap(err, "OpenRepository")
}
- defer headGitRepo.Close()
+ defer closer.Close()
if pr.Flow == models.PullRequestFlowGithub && !headGitRepo.IsBranchExist(pr.HeadBranch) {
return "", errors.New("Head branch does not exist, can not merge")
diff --git a/services/pull/lfs.go b/services/pull/lfs.go
index c9ec415cb1..fada9b6121 100644
--- a/services/pull/lfs.go
+++ b/services/pull/lfs.go
@@ -7,6 +7,7 @@ package pull
import (
"bufio"
+ "context"
"io"
"strconv"
"sync"
@@ -18,7 +19,7 @@ import (
)
// LFSPush pushes lfs objects referred to in new commits in the head repository from the base repository
-func LFSPush(tmpBasePath, mergeHeadSHA, mergeBaseSHA string, pr *models.PullRequest) error {
+func LFSPush(ctx context.Context, tmpBasePath, mergeHeadSHA, mergeBaseSHA string, pr *models.PullRequest) error {
// Now we have to implement git lfs push
// git rev-list --objects --filter=blob:limit=1k HEAD --not base
// pass blob shas in to git cat-file --batch-check (possibly unnecessary)
@@ -41,19 +42,19 @@ func LFSPush(tmpBasePath, mergeHeadSHA, mergeBaseSHA string, pr *models.PullRequ
go createLFSMetaObjectsFromCatFileBatch(catFileBatchReader, &wg, pr)
// 5. Take the shas of the blobs and batch read them
- go pipeline.CatFileBatch(shasToBatchReader, catFileBatchWriter, &wg, tmpBasePath)
+ go pipeline.CatFileBatch(ctx, shasToBatchReader, catFileBatchWriter, &wg, tmpBasePath)
// 4. From the provided objects restrict to blobs <=1k
go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg)
// 3. Run batch-check on the objects retrieved from rev-list
- go pipeline.CatFileBatchCheck(shasToCheckReader, catFileCheckWriter, &wg, tmpBasePath)
+ go pipeline.CatFileBatchCheck(ctx, shasToCheckReader, catFileCheckWriter, &wg, tmpBasePath)
// 2. Check each object retrieved rejecting those without names as they will be commits or trees
go pipeline.BlobsFromRevListObjects(revListReader, shasToCheckWriter, &wg)
// 1. Run rev-list objects from mergeHead to mergeBase
- go pipeline.RevListObjects(revListWriter, &wg, tmpBasePath, mergeHeadSHA, mergeBaseSHA, errChan)
+ go pipeline.RevListObjects(ctx, revListWriter, &wg, tmpBasePath, mergeHeadSHA, mergeBaseSHA, errChan)
wg.Wait()
select {
diff --git a/services/pull/merge.go b/services/pull/merge.go
index f6a6415bff..2a67507a87 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -8,6 +8,7 @@ package pull
import (
"bufio"
"bytes"
+ "context"
"fmt"
"os"
"path/filepath"
@@ -34,7 +35,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, expectedHeadCommitID, message string) (err error) {
+func Merge(ctx context.Context, 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 +60,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, expectedHeadCommitID, message)
+ pr.MergedCommitID, err = rawMerge(ctx, pr, doer, mergeStyle, expectedHeadCommitID, message)
if err != nil {
return err
}
@@ -117,7 +118,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, expectedHeadCommitID, message string) (string, error) {
+func rawMerge(ctx context.Context, 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)
@@ -125,7 +126,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
}
// Clone base repo.
- tmpBasePath, err := createTemporaryRepo(pr)
+ tmpBasePath, err := createTemporaryRepo(ctx, pr)
if err != nil {
log.Error("CreateTemporaryPath: %v", err)
return "", err
@@ -141,7 +142,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
stagingBranch := "staging"
if expectedHeadCommitID != "" {
- trackingCommitID, err := git.NewCommand("show-ref", "--hash", git.BranchPrefix+trackingBranch).RunInDir(tmpBasePath)
+ trackingCommitID, err := git.NewCommandContext(ctx, "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)
@@ -157,7 +158,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
var outbuf, errbuf strings.Builder
// Enable sparse-checkout
- sparseCheckoutList, err := getDiffTree(tmpBasePath, baseBranch, trackingBranch)
+ sparseCheckoutList, err := getDiffTree(ctx, tmpBasePath, baseBranch, trackingBranch)
if err != nil {
log.Error("getDiffTree(%s, %s, %s): %v", tmpBasePath, baseBranch, trackingBranch, err)
return "", fmt.Errorf("getDiffTree: %v", err)
@@ -178,11 +179,11 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
var gitConfigCommand func() *git.Command
if git.CheckGitVersionAtLeast("1.8.0") == nil {
gitConfigCommand = func() *git.Command {
- return git.NewCommand("config", "--local")
+ return git.NewCommandContext(ctx, "config", "--local")
}
} else {
gitConfigCommand = func() *git.Command {
- return git.NewCommand("config")
+ return git.NewCommandContext(ctx, "config")
}
}
@@ -223,7 +224,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
errbuf.Reset()
// Read base branch index
- if err := git.NewCommand("read-tree", "HEAD").RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "read-tree", "HEAD").RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("git read-tree HEAD: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
return "", fmt.Errorf("Unable to read base branch in to the index: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
}
@@ -236,7 +237,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
// Determine if we should sign
signArg := ""
if git.CheckGitVersionAtLeast("1.7.9") == nil {
- sign, keyID, signer, _ := asymkey_service.SignMerge(pr, doer, tmpBasePath, "HEAD", trackingBranch)
+ sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, pr, doer, tmpBasePath, "HEAD", trackingBranch)
if sign {
signArg = "-S" + keyID
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
@@ -262,13 +263,13 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
// Merge commits.
switch mergeStyle {
case repo_model.MergeStyleMerge:
- cmd := git.NewCommand("merge", "--no-ff", "--no-commit", trackingBranch)
+ cmd := git.NewCommandContext(ctx, "merge", "--no-ff", "--no-commit", trackingBranch)
if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
log.Error("Unable to merge tracking into base: %v", err)
return "", err
}
- if err := commitAndSignNoAuthor(pr, message, signArg, tmpBasePath, env); err != nil {
+ if err := commitAndSignNoAuthor(ctx, pr, message, signArg, tmpBasePath, env); err != nil {
log.Error("Unable to make final commit: %v", err)
return "", err
}
@@ -278,7 +279,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
fallthrough
case repo_model.MergeStyleRebaseMerge:
// Checkout head branch
- if err := git.NewCommand("checkout", "-b", stagingBranch, trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "checkout", "-b", stagingBranch, trackingBranch).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())
return "", fmt.Errorf("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())
}
@@ -286,7 +287,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
errbuf.Reset()
// Rebase before merging
- if err := git.NewCommand("rebase", baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "rebase", baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
// Rebase will leave a REBASE_HEAD file in .git if there is a conflict
if _, statErr := os.Stat(filepath.Join(tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil {
var commitSha string
@@ -334,14 +335,14 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
}
// Checkout base branch again
- if err := git.NewCommand("checkout", baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "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())
return "", fmt.Errorf("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())
}
outbuf.Reset()
errbuf.Reset()
- cmd := git.NewCommand("merge")
+ cmd := git.NewCommandContext(ctx, "merge")
if mergeStyle == repo_model.MergeStyleRebase {
cmd.AddArguments("--ff-only")
} else {
@@ -355,14 +356,14 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
return "", err
}
if mergeStyle == repo_model.MergeStyleRebaseMerge {
- if err := commitAndSignNoAuthor(pr, message, signArg, tmpBasePath, env); err != nil {
+ if err := commitAndSignNoAuthor(ctx, pr, message, signArg, tmpBasePath, env); err != nil {
log.Error("Unable to make final commit: %v", err)
return "", err
}
}
case repo_model.MergeStyleSquash:
// Merge with squash
- cmd := git.NewCommand("merge", "--squash", trackingBranch)
+ cmd := git.NewCommandContext(ctx, "merge", "--squash", trackingBranch)
if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
log.Error("Unable to merge --squash tracking into base: %v", err)
return "", err
@@ -374,7 +375,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
}
sig := pr.Issue.Poster.NewGitSig()
if signArg == "" {
- if err := git.NewCommand("commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
return "", fmt.Errorf("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
}
@@ -383,7 +384,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
// add trailer
message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
}
- if err := git.NewCommand("commit", signArg, fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "commit", signArg, fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
return "", fmt.Errorf("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
}
@@ -395,15 +396,15 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
}
// OK we should cache our current head and origin/headbranch
- mergeHeadSHA, err := git.GetFullCommitID(tmpBasePath, "HEAD")
+ mergeHeadSHA, err := git.GetFullCommitID(ctx, tmpBasePath, "HEAD")
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for HEAD: %v", err)
}
- mergeBaseSHA, err := git.GetFullCommitID(tmpBasePath, "original_"+baseBranch)
+ mergeBaseSHA, err := git.GetFullCommitID(ctx, tmpBasePath, "original_"+baseBranch)
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for origin/%s: %v", pr.BaseBranch, err)
}
- mergeCommitID, err := git.GetFullCommitID(tmpBasePath, baseBranch)
+ mergeCommitID, err := git.GetFullCommitID(ctx, tmpBasePath, baseBranch)
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for the new merge: %v", err)
}
@@ -412,7 +413,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
// I think in the interests of data safety - failures to push to the lfs should prevent
// the merge as you can always remerge.
if setting.LFS.StartServer {
- if err := LFSPush(tmpBasePath, mergeHeadSHA, mergeBaseSHA, pr); err != nil {
+ if err := LFSPush(ctx, tmpBasePath, mergeHeadSHA, mergeBaseSHA, pr); err != nil {
return "", err
}
}
@@ -441,9 +442,9 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
var pushCmd *git.Command
if mergeStyle == repo_model.MergeStyleRebaseUpdate {
// force push the rebase result to head branch
- pushCmd = git.NewCommand("push", "-f", "head_repo", stagingBranch+":"+git.BranchPrefix+pr.HeadBranch)
+ pushCmd = git.NewCommandContext(ctx, "push", "-f", "head_repo", stagingBranch+":"+git.BranchPrefix+pr.HeadBranch)
} else {
- pushCmd = git.NewCommand("push", "origin", baseBranch+":"+git.BranchPrefix+pr.BaseBranch)
+ pushCmd = git.NewCommandContext(ctx, "push", "origin", baseBranch+":"+git.BranchPrefix+pr.BaseBranch)
}
// Push back to upstream.
@@ -471,15 +472,15 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle repo_mod
return mergeCommitID, nil
}
-func commitAndSignNoAuthor(pr *models.PullRequest, message, signArg, tmpBasePath string, env []string) error {
+func commitAndSignNoAuthor(ctx context.Context, pr *models.PullRequest, message, signArg, tmpBasePath string, env []string) error {
var outbuf, errbuf strings.Builder
if signArg == "" {
- if err := git.NewCommand("commit", "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "commit", "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
}
} else {
- if err := git.NewCommand("commit", signArg, "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "commit", signArg, "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
}
@@ -518,11 +519,11 @@ func runMergeCommand(pr *models.PullRequest, mergeStyle repo_model.MergeStyle, c
var escapedSymbols = regexp.MustCompile(`([*[?! \\])`)
-func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) {
+func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) (string, error) {
getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) {
var outbuf, errbuf strings.Builder
// Compute the diff-tree for sparse-checkout
- if err := git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root", baseBranch, headBranch, "--").RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root", baseBranch, headBranch, "--").RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
return "", fmt.Errorf("git diff-tree [%s base:%s head:%s]: %s", repoPath, baseBranch, headBranch, errbuf.String())
}
return outbuf.String(), nil
@@ -562,7 +563,7 @@ func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) {
}
// IsSignedIfRequired check if merge will be signed if required
-func IsSignedIfRequired(pr *models.PullRequest, doer *user_model.User) (bool, error) {
+func IsSignedIfRequired(ctx context.Context, pr *models.PullRequest, doer *user_model.User) (bool, error) {
if err := pr.LoadProtectedBranch(); err != nil {
return false, err
}
@@ -571,7 +572,7 @@ func IsSignedIfRequired(pr *models.PullRequest, doer *user_model.User) (bool, er
return true, nil
}
- sign, _, _, err := asymkey_service.SignMerge(pr, doer, pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName())
+ sign, _, _, err := asymkey_service.SignMerge(ctx, pr, doer, pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName())
return sign, err
}
@@ -595,7 +596,7 @@ func IsUserAllowedToMerge(pr *models.PullRequest, p models.Permission, user *use
}
// CheckPRReadyToMerge checks whether the PR is ready to be merged (reviews and status checks)
-func CheckPRReadyToMerge(pr *models.PullRequest, skipProtectedFilesCheck bool) (err error) {
+func CheckPRReadyToMerge(ctx context.Context, pr *models.PullRequest, skipProtectedFilesCheck bool) (err error) {
if err = pr.LoadBaseRepo(); err != nil {
return fmt.Errorf("LoadBaseRepo: %v", err)
}
@@ -607,7 +608,7 @@ func CheckPRReadyToMerge(pr *models.PullRequest, skipProtectedFilesCheck bool) (
return nil
}
- isPass, err := IsPullCommitStatusPass(pr)
+ isPass, err := IsPullCommitStatusPass(ctx, pr)
if err != nil {
return err
}
diff --git a/services/pull/patch.go b/services/pull/patch.go
index 0eba3f86ed..a632167916 100644
--- a/services/pull/patch.go
+++ b/services/pull/patch.go
@@ -26,17 +26,18 @@ import (
)
// DownloadDiffOrPatch will write the patch for the pr to the writer
-func DownloadDiffOrPatch(pr *models.PullRequest, w io.Writer, patch, binary bool) error {
+func DownloadDiffOrPatch(ctx context.Context, pr *models.PullRequest, w io.Writer, patch, binary bool) error {
if err := pr.LoadBaseRepo(); err != nil {
log.Error("Unable to load base repository ID %d for pr #%d [%d]", pr.BaseRepoID, pr.Index, pr.ID)
return err
}
- gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
+ gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath())
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
- defer gitRepo.Close()
+ defer closer.Close()
+
if err := gitRepo.GetDiffOrPatch(pr.MergeBase, pr.GetGitRefName(), w, patch, binary); err != nil {
log.Error("Unable to get patch file from %s to %s in %s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
return fmt.Errorf("Unable to get patch file from %s to %s in %s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
@@ -53,8 +54,11 @@ var patchErrorSuffices = []string{
// TestPatch will test whether a simple patch will apply
func TestPatch(pr *models.PullRequest) error {
+ ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("TestPatch: Repo[%d]#%d", pr.BaseRepoID, pr.Index))
+ defer finished()
+
// Clone base repo.
- tmpBasePath, err := createTemporaryRepo(pr)
+ tmpBasePath, err := createTemporaryRepo(ctx, pr)
if err != nil {
log.Error("CreateTemporaryPath: %v", err)
return err
@@ -65,14 +69,14 @@ func TestPatch(pr *models.PullRequest) error {
}
}()
- gitRepo, err := git.OpenRepository(tmpBasePath)
+ gitRepo, err := git.OpenRepositoryCtx(ctx, tmpBasePath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
defer gitRepo.Close()
// 1. update merge base
- pr.MergeBase, err = git.NewCommand("merge-base", "--", "base", "tracking").RunInDir(tmpBasePath)
+ pr.MergeBase, err = git.NewCommandContext(ctx, "merge-base", "--", "base", "tracking").RunInDir(tmpBasePath)
if err != nil {
var err2 error
pr.MergeBase, err2 = gitRepo.GetRefCommitID(git.BranchPrefix + "base")
@@ -322,7 +326,7 @@ func checkConflicts(pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath
pr.Status = models.PullRequestStatusChecking
// 3. Read the base branch in to the index of the temporary repository
- _, err = git.NewCommand("read-tree", "base").RunInDir(tmpBasePath)
+ _, err = git.NewCommandContext(gitRepo.Ctx, "read-tree", "base").RunInDir(tmpBasePath)
if err != nil {
return false, fmt.Errorf("git read-tree %s: %v", pr.BaseBranch, err)
}
@@ -365,7 +369,7 @@ func checkConflicts(pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath
// 7. Run the check command
conflict = false
- err = git.NewCommand(args...).
+ err = git.NewCommandContext(gitRepo.Ctx, args...).
RunInDirTimeoutEnvFullPipelineFunc(
nil, -1, tmpBasePath,
nil, stderrWriter, nil,
@@ -432,11 +436,11 @@ func checkConflicts(pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath
}
// CheckFileProtection check file Protection
-func CheckFileProtection(oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string, repo *git.Repository) ([]string, error) {
+func CheckFileProtection(repo *git.Repository, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) {
if len(patterns) == 0 {
return nil, nil
}
- affectedFiles, err := git.GetAffectedFiles(oldCommitID, newCommitID, env, repo)
+ affectedFiles, err := git.GetAffectedFiles(repo, oldCommitID, newCommitID, env)
if err != nil {
return nil, err
}
@@ -462,11 +466,11 @@ func CheckFileProtection(oldCommitID, newCommitID string, patterns []glob.Glob,
}
// CheckUnprotectedFiles check if the commit only touches unprotected files
-func CheckUnprotectedFiles(oldCommitID, newCommitID string, patterns []glob.Glob, env []string, repo *git.Repository) (bool, error) {
+func CheckUnprotectedFiles(repo *git.Repository, oldCommitID, newCommitID string, patterns []glob.Glob, env []string) (bool, error) {
if len(patterns) == 0 {
return false, nil
}
- affectedFiles, err := git.GetAffectedFiles(oldCommitID, newCommitID, env, repo)
+ affectedFiles, err := git.GetAffectedFiles(repo, oldCommitID, newCommitID, env)
if err != nil {
return false, err
}
@@ -498,7 +502,7 @@ func checkPullFilesProtection(pr *models.PullRequest, gitRepo *git.Repository) e
}
var err error
- pr.ChangedProtectedFiles, err = CheckFileProtection(pr.MergeBase, "tracking", pr.ProtectedBranch.GetProtectedFilePatterns(), 10, os.Environ(), gitRepo)
+ pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.MergeBase, "tracking", pr.ProtectedBranch.GetProtectedFilePatterns(), 10, os.Environ())
if err != nil && !models.IsErrFilePathProtected(err) {
return err
}
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 {
diff --git a/services/pull/review.go b/services/pull/review.go
index 42292ac209..0db3168895 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -6,6 +6,7 @@
package pull
import (
+ "context"
"fmt"
"io"
"regexp"
@@ -22,7 +23,8 @@ import (
)
// CreateCodeComment creates a comment on the code line
-func CreateCodeComment(doer *user_model.User, gitRepo *git.Repository, issue *models.Issue, line int64, content, treePath string, isReview bool, replyReviewID int64, latestCommitID string) (*models.Comment, error) {
+func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *models.Issue, line int64, content, treePath string, isReview bool, replyReviewID int64, latestCommitID string) (*models.Comment, error) {
+
var (
existsReview bool
err error
@@ -47,7 +49,7 @@ func CreateCodeComment(doer *user_model.User, gitRepo *git.Repository, issue *mo
return nil, err
}
- comment, err := createCodeComment(
+ comment, err := createCodeComment(ctx,
doer,
issue.Repo,
issue,
@@ -87,7 +89,7 @@ func CreateCodeComment(doer *user_model.User, gitRepo *git.Repository, issue *mo
}
}
- comment, err := createCodeComment(
+ comment, err := createCodeComment(ctx,
doer,
issue.Repo,
issue,
@@ -102,7 +104,7 @@ func CreateCodeComment(doer *user_model.User, gitRepo *git.Repository, issue *mo
if !isReview && !existsReview {
// Submit the review we've just created so the comment shows up in the issue view
- if _, _, err = SubmitReview(doer, gitRepo, issue, models.ReviewTypeComment, "", latestCommitID, nil); err != nil {
+ if _, _, err = SubmitReview(ctx, doer, gitRepo, issue, models.ReviewTypeComment, "", latestCommitID, nil); err != nil {
return nil, err
}
}
@@ -115,7 +117,7 @@ func CreateCodeComment(doer *user_model.User, gitRepo *git.Repository, issue *mo
var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has only \d+ lines?`)
// createCodeComment creates a plain code comment at the specified line / path
-func createCodeComment(doer *user_model.User, repo *repo_model.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) {
+func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) {
var commitID, patch string
if err := issue.LoadPullRequest(); err != nil {
return nil, fmt.Errorf("GetPullRequestByIssueID: %v", err)
@@ -124,11 +126,11 @@ func createCodeComment(doer *user_model.User, repo *repo_model.Repository, issue
if err := pr.LoadBaseRepo(); err != nil {
return nil, fmt.Errorf("LoadHeadRepo: %v", err)
}
- gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
+ gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath())
if err != nil {
return nil, fmt.Errorf("OpenRepository: %v", err)
}
- defer gitRepo.Close()
+ defer closer.Close()
invalidated := false
head := pr.GetGitRefName()
@@ -217,7 +219,7 @@ func createCodeComment(doer *user_model.User, repo *repo_model.Repository, issue
}
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
-func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.Issue, reviewType models.ReviewType, content, commitID string, attachmentUUIDs []string) (*models.Review, *models.Comment, error) {
+func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *models.Issue, reviewType models.ReviewType, content, commitID string, attachmentUUIDs []string) (*models.Review, *models.Comment, error) {
pr, err := issue.GetPullRequest()
if err != nil {
return nil, nil, err
@@ -235,7 +237,7 @@ func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.
if headCommitID == commitID {
stale = false
} else {
- stale, err = checkIfPRContentChanged(pr, commitID, headCommitID)
+ stale, err = checkIfPRContentChanged(ctx, pr, commitID, headCommitID)
if err != nil {
return nil, nil, err
}
@@ -247,7 +249,6 @@ func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.
return nil, nil, err
}
- ctx := db.DefaultContext
mentions, err := issue.FindAndUpdateIssueMentions(ctx, doer, comm.Content)
if err != nil {
return nil, nil, err
@@ -271,7 +272,7 @@ func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.
}
// DismissReview dismissing stale review by repo admin
-func DismissReview(reviewID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
+func DismissReview(ctx context.Context, reviewID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
review, err := models.GetReviewByID(reviewID)
if err != nil {
return
@@ -290,7 +291,7 @@ func DismissReview(reviewID int64, message string, doer *user_model.User, isDism
}
// load data for notify
- if err = review.LoadAttributes(); err != nil {
+ if err = review.LoadAttributes(ctx); err != nil {
return
}
if err = review.Issue.LoadPullRequest(); err != nil {
diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go
index d5dc8a5c4b..140403172c 100644
--- a/services/pull/temp_repo.go
+++ b/services/pull/temp_repo.go
@@ -6,6 +6,7 @@
package pull
import (
+ "context"
"fmt"
"os"
"path/filepath"
@@ -20,7 +21,7 @@ import (
// createTemporaryRepo creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch
// it also create a second base branch called "original_base"
-func createTemporaryRepo(pr *models.PullRequest) (string, error) {
+func createTemporaryRepo(ctx context.Context, pr *models.PullRequest) (string, error) {
if err := pr.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err)
return "", fmt.Errorf("LoadHeadRepo: %v", err)
@@ -55,7 +56,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
baseRepoPath := pr.BaseRepo.RepoPath()
headRepoPath := pr.HeadRepo.RepoPath()
- if err := git.InitRepository(tmpBasePath, false); err != nil {
+ if err := git.InitRepository(ctx, tmpBasePath, false); err != nil {
log.Error("git init tmpBasePath: %v", err)
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
@@ -92,7 +93,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
}
var outbuf, errbuf strings.Builder
- if err := git.NewCommand("remote", "add", "-t", pr.BaseBranch, "-m", pr.BaseBranch, "origin", baseRepoPath).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "remote", "add", "-t", pr.BaseBranch, "-m", pr.BaseBranch, "origin", baseRepoPath).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("Unable to add base repository as origin [%s -> %s]: %v\n%s\n%s", pr.BaseRepo.FullName(), tmpBasePath, err, outbuf.String(), errbuf.String())
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
@@ -102,7 +103,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
outbuf.Reset()
errbuf.Reset()
- if err := git.NewCommand("fetch", "origin", "--no-tags", "--", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "fetch", "origin", "--no-tags", "--", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, outbuf.String(), errbuf.String())
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
@@ -112,7 +113,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
outbuf.Reset()
errbuf.Reset()
- if err := git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "symbolic-ref", "HEAD", git.BranchPrefix+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("Unable to set HEAD as base branch [%s]: %v\n%s\n%s", tmpBasePath, err, outbuf.String(), errbuf.String())
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
@@ -130,7 +131,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
return "", fmt.Errorf("Unable to head base repository to temporary repo [%s -> tmpBasePath]: %v", pr.HeadRepo.FullName(), err)
}
- if err := git.NewCommand("remote", "add", remoteRepoName, headRepoPath).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "remote", "add", remoteRepoName, headRepoPath).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
log.Error("Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n%s", pr.HeadRepo.FullName(), tmpBasePath, err, outbuf.String(), errbuf.String())
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
@@ -150,11 +151,11 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
} else {
headBranch = pr.GetGitRefName()
}
- if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, headBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
+ if err := git.NewCommandContext(ctx, "fetch", "--no-tags", remoteRepoName, headBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
}
- if !git.IsBranchExist(git.DefaultContext, pr.HeadRepo.RepoPath(), pr.HeadBranch) {
+ if !git.IsBranchExist(ctx, pr.HeadRepo.RepoPath(), pr.HeadBranch) {
return "", models.ErrBranchDoesNotExist{
BranchName: pr.HeadBranch,
}
diff --git a/services/pull/update.go b/services/pull/update.go
index 8ca7e4cee7..09cf1ce52e 100644
--- a/services/pull/update.go
+++ b/services/pull/update.go
@@ -5,6 +5,7 @@
package pull
import (
+ "context"
"fmt"
"code.gitea.io/gitea/models"
@@ -15,7 +16,7 @@ import (
)
// Update updates pull request with base branch.
-func Update(pull *models.PullRequest, doer *user_model.User, message string, rebase bool) error {
+func Update(ctx context.Context, pull *models.PullRequest, doer *user_model.User, message string, rebase bool) error {
var (
pr *models.PullRequest
style repo_model.MergeStyle
@@ -48,14 +49,14 @@ func Update(pull *models.PullRequest, doer *user_model.User, message string, reb
return fmt.Errorf("LoadBaseRepo: %v", err)
}
- diffCount, err := GetDiverging(pull)
+ diffCount, err := GetDiverging(ctx, pull)
if err != nil {
return err
} else if diffCount.Behind == 0 {
return fmt.Errorf("HeadBranch of PR %d is up to date", pull.Index)
}
- _, err = rawMerge(pr, doer, style, "", message)
+ _, err = rawMerge(ctx, pr, doer, style, "", message)
defer func() {
if rebase {
@@ -113,7 +114,7 @@ func IsUserAllowedToUpdate(pull *models.PullRequest, user *user_model.User) (mer
}
// GetDiverging determines how many commits a PR is ahead or behind the PR base branch
-func GetDiverging(pr *models.PullRequest) (*git.DivergeObject, error) {
+func GetDiverging(ctx context.Context, pr *models.PullRequest) (*git.DivergeObject, error) {
log.Trace("GetDiverging[%d]: compare commits", pr.ID)
if err := pr.LoadBaseRepo(); err != nil {
return nil, err
@@ -122,7 +123,7 @@ func GetDiverging(pr *models.PullRequest) (*git.DivergeObject, error) {
return nil, err
}
- tmpRepo, err := createTemporaryRepo(pr)
+ tmpRepo, err := createTemporaryRepo(ctx, pr)
if err != nil {
if !models.IsErrBranchDoesNotExist(err) {
log.Error("CreateTemporaryRepo: %v", err)
@@ -135,6 +136,6 @@ func GetDiverging(pr *models.PullRequest) (*git.DivergeObject, error) {
}
}()
- diff, err := git.GetDivergingCommits(tmpRepo, "base", "tracking")
+ diff, err := git.GetDivergingCommits(ctx, tmpRepo, "base", "tracking")
return &diff, err
}