From 6c9c38a840377685111c0bd1f7ee964fe2cbf075 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Tue, 30 Nov 2021 21:57:59 +0000 Subject: [PATCH] Propagate context and ensure git commands run in request context This PR continues the work in #17125 by progressively ensuring that git commands run within the request context. Signed-off-by: Andrew Thornton --- cmd/admin.go | 2 +- .../api_repo_get_contents_list_test.go | 2 +- integrations/api_repo_get_contents_test.go | 2 +- .../git_helper_for_declarative_test.go | 4 +- integrations/pull_merge_test.go | 6 +-- integrations/pull_update_test.go | 11 ++-- models/admin/notice.go | 8 ++- modules/git/commit_info_test.go | 2 +- modules/git/repo.go | 11 ++-- modules/git/repo_branch.go | 4 +- modules/indexer/code/bleve.go | 6 +-- modules/indexer/code/elastic_search.go | 4 +- modules/indexer/code/indexer.go | 8 +-- modules/indexer/code/indexer_test.go | 3 +- modules/indexer/code/wrapped.go | 5 +- modules/repository/generate.go | 16 +++--- modules/repository/init.go | 16 +++--- modules/repository/repo.go | 4 +- routers/api/v1/repo/branch.go | 4 +- routers/api/v1/repo/pull.go | 8 +-- routers/api/v1/repo/repo.go | 2 +- routers/api/v1/repo/wiki.go | 6 +-- routers/private/serv.go | 2 +- routers/web/admin/repos.go | 2 +- routers/web/repo/branch.go | 6 +-- routers/web/repo/http.go | 3 +- routers/web/repo/lfs.go | 2 +- routers/web/repo/pull.go | 8 +-- routers/web/repo/setting.go | 4 +- routers/web/repo/wiki.go | 6 +-- services/agit/agit.go | 2 +- services/gitdiff/gitdiff.go | 2 +- services/migrations/dump.go | 6 +-- services/mirror/mirror_pull.go | 2 +- services/pull/merge.go | 51 ++++++++++--------- services/pull/patch.go | 11 ++-- services/pull/pull.go | 32 ++++++------ services/pull/temp_repo.go | 17 ++++--- services/pull/update.go | 11 ++-- services/repository/branch.go | 35 +++++++------ services/repository/check.go | 2 +- services/repository/repository.go | 5 +- services/wiki/wiki.go | 38 +++++++------- services/wiki/wiki_test.go | 24 ++++----- 44 files changed, 209 insertions(+), 196 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index d11b824fa12e..f5b641275178 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -565,7 +565,7 @@ func runRepoSyncReleases(_ *cli.Context) error { log.Trace("Processing next %d repos of %d", len(repos), count) for _, repo := range repos { log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath()) - gitRepo, err := git.OpenRepository(repo.RepoPath()) + gitRepo, err := git.OpenRepositoryCtx(ctx, repo.RepoPath()) if err != nil { log.Warn("OpenRepository: %v", err) continue diff --git a/integrations/api_repo_get_contents_list_test.go b/integrations/api_repo_get_contents_list_test.go index 63ac9cfb5306..2741e6605665 100644 --- a/integrations/api_repo_get_contents_list_test.go +++ b/integrations/api_repo_get_contents_list_test.go @@ -72,7 +72,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { // Make a new branch in repo1 newBranch := "test_branch" - err := repo_service.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch) + err := repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, repo1.DefaultBranch, newBranch) assert.NoError(t, err) // Get the commit ID of the default branch gitRepo, err := git.OpenRepository(repo1.RepoPath()) diff --git a/integrations/api_repo_get_contents_test.go b/integrations/api_repo_get_contents_test.go index 9843239ec4a7..33253452e0cf 100644 --- a/integrations/api_repo_get_contents_test.go +++ b/integrations/api_repo_get_contents_test.go @@ -73,7 +73,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { // Make a new branch in repo1 newBranch := "test_branch" - err := repo_service.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch) + err := repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, repo1.DefaultBranch, newBranch) assert.NoError(t, err) // Get the commit ID of the default branch gitRepo, err := git.OpenRepository(repo1.RepoPath()) diff --git a/integrations/git_helper_for_declarative_test.go b/integrations/git_helper_for_declarative_test.go index 71473ce464bc..c8200fe99994 100644 --- a/integrations/git_helper_for_declarative_test.go +++ b/integrations/git_helper_for_declarative_test.go @@ -128,7 +128,7 @@ func doGitCloneFail(u *url.URL) func(*testing.T) { tmpDir, err := os.MkdirTemp("", "doGitCloneFail") assert.NoError(t, err) defer util.RemoveAll(tmpDir) - assert.Error(t, git.Clone(u.String(), tmpDir, git.CloneRepoOptions{})) + assert.Error(t, git.Clone(git.DefaultContext, u.String(), tmpDir, git.CloneRepoOptions{})) exist, err := util.IsExist(filepath.Join(tmpDir, "README.md")) assert.NoError(t, err) assert.False(t, exist) @@ -138,7 +138,7 @@ func doGitCloneFail(u *url.URL) func(*testing.T) { func doGitInitTestRepository(dstPath string) func(*testing.T) { return func(t *testing.T) { // Init repository in dstPath - assert.NoError(t, git.InitRepository(dstPath, false)) + assert.NoError(t, git.InitRepository(git.DefaultContext, dstPath, false)) assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", dstPath)), 0644)) assert.NoError(t, git.AddChanges(dstPath, true)) signature := git.Signature{ diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go index 2e219dcc9182..8bd308a57e44 100644 --- a/integrations/pull_merge_test.go +++ b/integrations/pull_merge_test.go @@ -240,11 +240,11 @@ func TestCantMergeConflict(t *testing.T) { gitRepo, err := git.OpenRepository(models.RepoPath(user1.Name, repo1.Name)) assert.NoError(t, err) - err = pull.Merge(pr, user1, gitRepo, models.MergeStyleMerge, "CONFLICT") + err = pull.Merge(git.DefaultContext, pr, user1, gitRepo, models.MergeStyleMerge, "CONFLICT") assert.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrMergeConflicts(err), "Merge error is not a conflict error") - err = pull.Merge(pr, user1, gitRepo, models.MergeStyleRebase, "CONFLICT") + err = pull.Merge(git.DefaultContext, pr, user1, gitRepo, models.MergeStyleRebase, "CONFLICT") assert.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error") gitRepo.Close() @@ -328,7 +328,7 @@ func TestCantMergeUnrelated(t *testing.T) { BaseBranch: "base", }).(*models.PullRequest) - err = pull.Merge(pr, user1, gitRepo, models.MergeStyleMerge, "UNRELATED") + err = pull.Merge(git.DefaultContext, pr, user1, gitRepo, models.MergeStyleMerge, "UNRELATED") assert.Error(t, err, "Merge should return an error due to unrelated") assert.True(t, models.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error") gitRepo.Close() diff --git a/integrations/pull_update_test.go b/integrations/pull_update_test.go index e5e19475caa4..9e129e727007 100644 --- a/integrations/pull_update_test.go +++ b/integrations/pull_update_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" files_service "code.gitea.io/gitea/services/repository/files" @@ -28,7 +29,7 @@ func TestAPIPullUpdate(t *testing.T) { pr := createOutdatedPR(t, user, org26) //Test GetDiverging - diffCount, err := pull_service.GetDiverging(pr) + diffCount, err := pull_service.GetDiverging(git.DefaultContext, pr) assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) @@ -41,7 +42,7 @@ func TestAPIPullUpdate(t *testing.T) { session.MakeRequest(t, req, http.StatusOK) //Test GetDiverging after update - diffCount, err = pull_service.GetDiverging(pr) + diffCount, err = pull_service.GetDiverging(git.DefaultContext, pr) assert.NoError(t, err) assert.EqualValues(t, 0, diffCount.Behind) assert.EqualValues(t, 2, diffCount.Ahead) @@ -56,7 +57,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) { pr := createOutdatedPR(t, user, org26) //Test GetDiverging - diffCount, err := pull_service.GetDiverging(pr) + diffCount, err := pull_service.GetDiverging(git.DefaultContext, pr) assert.NoError(t, err) assert.EqualValues(t, 1, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) @@ -69,7 +70,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) { session.MakeRequest(t, req, http.StatusOK) //Test GetDiverging after update - diffCount, err = pull_service.GetDiverging(pr) + diffCount, err = pull_service.GetDiverging(git.DefaultContext, pr) assert.NoError(t, err) assert.EqualValues(t, 0, diffCount.Behind) assert.EqualValues(t, 1, diffCount.Ahead) @@ -160,7 +161,7 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *models.Pul BaseRepo: baseRepo, Type: models.PullRequestGitea, } - err = pull_service.NewPullRequest(baseRepo, pullIssue, nil, nil, pullRequest, nil) + err = pull_service.NewPullRequest(git.DefaultContext, baseRepo, pullIssue, nil, nil, pullRequest, nil) assert.NoError(t, err) issue := unittest.AssertExistsAndLoadBean(t, &models.Issue{Title: "Test Pull -to-update-"}).(*models.Issue) diff --git a/models/admin/notice.go b/models/admin/notice.go index 2d71b426dde7..daf095f680f4 100644 --- a/models/admin/notice.go +++ b/models/admin/notice.go @@ -56,6 +56,7 @@ func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...inter // CreateRepositoryNotice creates new system notice with type NoticeRepository. func CreateRepositoryNotice(desc string, args ...interface{}) error { + // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled return CreateNotice(db.DefaultContext, NoticeRepository, desc, args...) } @@ -65,7 +66,8 @@ func RemoveAllWithNotice(ctx context.Context, title, path string) { if err := util.RemoveAll(path); err != nil { desc := fmt.Sprintf("%s [%s]: %v", title, path, err) log.Warn(title+" [%s]: %v", path, err) - if err = CreateNotice(ctx, NoticeRepository, desc); err != nil { + // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled + if err = CreateNotice(db.DefaultContext, NoticeRepository, desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } @@ -77,7 +79,9 @@ func RemoveStorageWithNotice(ctx context.Context, bucket storage.ObjectStorage, if err := bucket.Delete(path); err != nil { desc := fmt.Sprintf("%s [%s]: %v", title, path, err) log.Warn(title+" [%s]: %v", path, err) - if err = CreateNotice(ctx, NoticeRepository, desc); err != nil { + + // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled + if err = CreateNotice(db.DefaultContext, NoticeRepository, desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } diff --git a/modules/git/commit_info_test.go b/modules/git/commit_info_test.go index 8467bdaa9034..a4c0483004df 100644 --- a/modules/git/commit_info_test.go +++ b/modules/git/commit_info_test.go @@ -24,7 +24,7 @@ func cloneRepo(url, dir, name string) (string, error) { if _, err := os.Stat(repoDir); err == nil { return repoDir, nil } - return repoDir, Clone(url, repoDir, CloneRepoOptions{ + return repoDir, Clone(DefaultContext, url, repoDir, CloneRepoOptions{ Mirror: false, Bare: false, Quiet: true, diff --git a/modules/git/repo.go b/modules/git/repo.go index 3950bb4a92aa..3a005866c1e4 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -63,13 +63,13 @@ func IsRepoURLAccessible(url string) bool { } // InitRepository initializes a new Git repository. -func InitRepository(repoPath string, bare bool) error { +func InitRepository(ctx context.Context, repoPath string, bare bool) error { err := os.MkdirAll(repoPath, os.ModePerm) if err != nil { return err } - cmd := NewCommand("init") + cmd := NewCommandContext(ctx, "init") if bare { cmd.AddArguments("--bare") } @@ -104,12 +104,7 @@ type CloneRepoOptions struct { } // Clone clones original repository to target path. -func Clone(from, to string, opts CloneRepoOptions) error { - return CloneWithContext(DefaultContext, from, to, opts) -} - -// CloneWithContext clones original repository to target path. -func CloneWithContext(ctx context.Context, from, to string, opts CloneRepoOptions) error { +func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { cargs := make([]string, len(GlobalCommandArgs)) copy(cargs, GlobalCommandArgs) return CloneWithArgs(ctx, from, to, cargs, opts) diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index 98b1bc8ae7c7..fd02018b84f3 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -88,8 +88,8 @@ func (repo *Repository) GetBranch(branch string) (*Branch, error) { // GetBranchesByPath returns a branch by it's path // if limit = 0 it will not limit -func GetBranchesByPath(path string, skip, limit int) ([]*Branch, int, error) { - gitRepo, err := OpenRepository(path) +func GetBranchesByPath(ctx context.Context, path string, skip, limit int) ([]*Branch, int, error) { + gitRepo, err := OpenRepositoryCtx(ctx, path) if err != nil { return nil, 0, err } diff --git a/modules/indexer/code/bleve.go b/modules/indexer/code/bleve.go index 97d5fb082cdc..d739618d278c 100644 --- a/modules/indexer/code/bleve.go +++ b/modules/indexer/code/bleve.go @@ -6,6 +6,7 @@ package code import ( "bufio" + "context" "fmt" "io" "os" @@ -271,11 +272,10 @@ func (b *BleveIndexer) Close() { } // Index indexes the data -func (b *BleveIndexer) Index(repo *models.Repository, sha string, changes *repoChanges) error { +func (b *BleveIndexer) Index(ctx context.Context, repo *models.Repository, sha string, changes *repoChanges) error { batch := gitea_bleve.NewFlushingBatch(b.indexer, maxBatchSize) if len(changes.Updates) > 0 { - - batchWriter, batchReader, cancel := git.CatFileBatch(git.DefaultContext, repo.RepoPath()) + batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath()) defer cancel() for _, update := range changes.Updates { diff --git a/modules/indexer/code/elastic_search.go b/modules/indexer/code/elastic_search.go index 6e0813dc1580..509098c2e5a6 100644 --- a/modules/indexer/code/elastic_search.go +++ b/modules/indexer/code/elastic_search.go @@ -244,11 +244,11 @@ func (b *ElasticSearchIndexer) addDelete(filename string, repo *models.Repositor } // Index will save the index data -func (b *ElasticSearchIndexer) Index(repo *models.Repository, sha string, changes *repoChanges) error { +func (b *ElasticSearchIndexer) Index(ctx context.Context, repo *models.Repository, sha string, changes *repoChanges) error { reqs := make([]elastic.BulkableRequest, 0) if len(changes.Updates) > 0 { - batchWriter, batchReader, cancel := git.CatFileBatch(git.DefaultContext, repo.RepoPath()) + batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath()) defer cancel() for _, update := range changes.Updates { diff --git a/modules/indexer/code/indexer.go b/modules/indexer/code/indexer.go index c56b1b2bb0c5..99019b5efa44 100644 --- a/modules/indexer/code/indexer.go +++ b/modules/indexer/code/indexer.go @@ -42,7 +42,7 @@ type SearchResultLanguages struct { // Indexer defines an interface to index and search code contents type Indexer interface { - Index(repo *models.Repository, sha string, changes *repoChanges) error + Index(ctx context.Context, repo *models.Repository, sha string, changes *repoChanges) error Delete(repoID int64) error Search(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error) Close() @@ -82,7 +82,7 @@ var ( indexerQueue queue.UniqueQueue ) -func index(indexer Indexer, repoID int64) error { +func index(ctx context.Context, indexer Indexer, repoID int64) error { repo, err := models.GetRepositoryByID(repoID) if models.IsErrRepoNotExist(err) { return indexer.Delete(repoID) @@ -102,7 +102,7 @@ func index(indexer Indexer, repoID int64) error { return nil } - if err := indexer.Index(repo, sha, changes); err != nil { + if err := indexer.Index(ctx, repo, sha, changes); err != nil { return err } @@ -150,7 +150,7 @@ func Init() { } log.Trace("IndexerData Process Repo: %d", indexerData.RepoID) - if err := index(indexer, indexerData.RepoID); err != nil { + if err := index(ctx, indexer, indexerData.RepoID); err != nil { log.Error("index: %v", err) continue } diff --git a/modules/indexer/code/indexer_test.go b/modules/indexer/code/indexer_test.go index b8fedcb3239e..d1a3300d98de 100644 --- a/modules/indexer/code/indexer_test.go +++ b/modules/indexer/code/indexer_test.go @@ -9,6 +9,7 @@ import ( "testing" "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/modules/git" "github.com/stretchr/testify/assert" ) @@ -20,7 +21,7 @@ func TestMain(m *testing.M) { func testIndexer(name string, t *testing.T, indexer Indexer) { t.Run(name, func(t *testing.T) { var repoID int64 = 1 - err := index(indexer, repoID) + err := index(git.DefaultContext, indexer, repoID) assert.NoError(t, err) var ( keywords = []struct { diff --git a/modules/indexer/code/wrapped.go b/modules/indexer/code/wrapped.go index 5b19f9c62573..948cb9f9e97b 100644 --- a/modules/indexer/code/wrapped.go +++ b/modules/indexer/code/wrapped.go @@ -5,6 +5,7 @@ package code import ( + "context" "fmt" "sync" @@ -57,12 +58,12 @@ func (w *wrappedIndexer) get() (Indexer, error) { return w.internal, nil } -func (w *wrappedIndexer) Index(repo *models.Repository, sha string, changes *repoChanges) error { +func (w *wrappedIndexer) Index(ctx context.Context, repo *models.Repository, sha string, changes *repoChanges) error { indexer, err := w.get() if err != nil { return err } - return indexer.Index(repo, sha, changes) + return indexer.Index(ctx, repo, sha, changes) } func (w *wrappedIndexer) Delete(repoID int64) error { diff --git a/modules/repository/generate.go b/modules/repository/generate.go index 61a8b0d11159..a792d10d47a1 100644 --- a/modules/repository/generate.go +++ b/modules/repository/generate.go @@ -98,7 +98,7 @@ func checkGiteaTemplate(tmpDir string) (*models.GiteaTemplate, error) { return gt, nil } -func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmpDir string) error { +func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *models.Repository, tmpDir string) error { commitTimeStr := time.Now().Format(time.RFC3339) authorSig := repo.Owner.NewGitSig() @@ -114,7 +114,7 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp // Clone to temporary path and do the init commit. templateRepoPath := templateRepo.RepoPath() - if err := git.Clone(templateRepoPath, tmpDir, git.CloneRepoOptions{ + if err := git.Clone(ctx, templateRepoPath, tmpDir, git.CloneRepoOptions{ Depth: 1, Branch: templateRepo.DefaultBranch, }); err != nil { @@ -171,19 +171,19 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp } } - if err := git.InitRepository(tmpDir, false); err != nil { + if err := git.InitRepository(ctx, tmpDir, false); err != nil { return err } repoPath := repo.RepoPath() - if stdout, err := git.NewCommand("remote", "add", "origin", repoPath). + if stdout, err := git.NewCommandContext(ctx, "remote", "add", "origin", repoPath). SetDescription(fmt.Sprintf("generateRepoCommit (git remote add): %s to %s", templateRepoPath, tmpDir)). RunInDirWithEnv(tmpDir, env); err != nil { log.Error("Unable to add %v as remote origin to temporary repo to %s: stdout %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git remote add: %v", err) } - return initRepoCommit(tmpDir, repo, repo.Owner, templateRepo.DefaultBranch) + return initRepoCommit(ctx, tmpDir, repo, repo.Owner, templateRepo.DefaultBranch) } func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *models.Repository) (err error) { @@ -198,7 +198,7 @@ func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *m } }() - if err = generateRepoCommit(repo, templateRepo, generateRepo, tmpDir); err != nil { + if err = generateRepoCommit(ctx, repo, templateRepo, generateRepo, tmpDir); err != nil { return fmt.Errorf("generateRepoCommit: %v", err) } @@ -208,7 +208,7 @@ func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *m } repo.DefaultBranch = templateRepo.DefaultBranch - gitRepo, err := git.OpenRepository(repo.RepoPath()) + gitRepo, err := git.OpenRepositoryCtx(ctx, repo.RepoPath()) if err != nil { return fmt.Errorf("openRepository: %v", err) } @@ -272,7 +272,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ } } - if err = checkInitRepository(owner.Name, generateRepo.Name); err != nil { + if err = checkInitRepository(ctx, owner.Name, generateRepo.Name); err != nil { return generateRepo, err } diff --git a/modules/repository/init.go b/modules/repository/init.go index d7f31fabde38..b6a66cb3bedf 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -101,7 +101,7 @@ func prepareRepoCommit(ctx context.Context, repo *models.Repository, tmpDir, rep } // initRepoCommit temporarily changes with work directory. -func initRepoCommit(tmpPath string, repo *models.Repository, u *user_model.User, defaultBranch string) (err error) { +func initRepoCommit(ctx context.Context, tmpPath string, repo *models.Repository, u *user_model.User, defaultBranch string) (err error) { commitTimeStr := time.Now().Format(time.RFC3339) sig := u.NewGitSig() @@ -115,7 +115,7 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *user_model.User, committerName := sig.Name committerEmail := sig.Email - if stdout, err := git.NewCommand("add", "--all"). + if stdout, err := git.NewCommandContext(ctx, "add", "--all"). SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)). RunInDir(tmpPath); err != nil { log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err) @@ -152,7 +152,7 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *user_model.User, "GIT_COMMITTER_EMAIL="+committerEmail, ) - if stdout, err := git.NewCommand(args...). + if stdout, err := git.NewCommandContext(ctx, args...). SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)). RunInDirWithEnv(tmpPath, env); err != nil { log.Error("Failed to commit: %v: Stdout: %s\nError: %v", args, stdout, err) @@ -163,7 +163,7 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *user_model.User, defaultBranch = setting.Repository.DefaultBranch } - if stdout, err := git.NewCommand("push", "origin", "HEAD:"+defaultBranch). + if stdout, err := git.NewCommandContext(ctx, "push", "origin", "HEAD:"+defaultBranch). SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). RunInDirWithEnv(tmpPath, models.InternalPushingEnvironment(u, repo)); err != nil { log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err) @@ -173,7 +173,7 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *user_model.User, return nil } -func checkInitRepository(owner, name string) (err error) { +func checkInitRepository(ctx context.Context, owner, name string) (err error) { // Somehow the directory could exist. repoPath := models.RepoPath(owner, name) isExist, err := util.IsExist(repoPath) @@ -189,7 +189,7 @@ func checkInitRepository(owner, name string) (err error) { } // Init git bare new repository. - if err = git.InitRepository(repoPath, true); err != nil { + if err = git.InitRepository(ctx, repoPath, true); err != nil { return fmt.Errorf("git.InitRepository: %v", err) } else if err = createDelegateHooks(repoPath); err != nil { return fmt.Errorf("createDelegateHooks: %v", err) @@ -199,7 +199,7 @@ func checkInitRepository(owner, name string) (err error) { // InitRepository initializes README and .gitignore if needed. func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *models.Repository, opts models.CreateRepoOptions) (err error) { - if err = checkInitRepository(repo.OwnerName, repo.Name); err != nil { + if err = checkInitRepository(ctx, repo.OwnerName, repo.Name); err != nil { return err } @@ -220,7 +220,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re } // Apply changes and commit. - if err = initRepoCommit(tmpDir, repo, u, opts.DefaultBranch); err != nil { + if err = initRepoCommit(ctx, tmpDir, repo, u, opts.DefaultBranch); err != nil { return fmt.Errorf("initRepoCommit: %v", err) } } diff --git a/modules/repository/repo.go b/modules/repository/repo.go index c7145658f80f..349635d81275 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -70,7 +70,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, return repo, fmt.Errorf("Failed to remove %s: %v", repoPath, err) } - if err = git.CloneWithContext(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ + if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ Mirror: true, Quiet: true, Timeout: migrateTimeout, @@ -86,7 +86,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err) } - if err = git.CloneWithContext(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ + if err = git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ Mirror: true, Quiet: true, Timeout: migrateTimeout, diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index e511152e5745..14384ca7e696 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -176,7 +176,7 @@ func CreateBranch(ctx *context.APIContext) { opt.OldBranchName = ctx.Repo.Repository.DefaultBranch } - err := repo_service.CreateNewBranch(ctx.User, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName) + err := repo_service.CreateNewBranch(ctx, ctx.User, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName) if err != nil { if models.IsErrBranchDoesNotExist(err) { @@ -257,7 +257,7 @@ func ListBranches(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) skip, _ := listOptions.GetStartEnd() - branches, totalNumOfBranches, err := repo_service.GetBranches(ctx.Repo.Repository, skip, listOptions.PageSize) + branches, totalNumOfBranches, err := repo_service.GetBranches(ctx, ctx.Repo.Repository, skip, listOptions.PageSize) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranches", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index dd415a34af3f..d4c9640251e0 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -409,7 +409,7 @@ func CreatePullRequest(ctx *context.APIContext) { } } - if err := pull_service.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, assigneeIDs); err != nil { + if err := pull_service.NewPullRequest(ctx, repo, prIssue, labelIDs, []string{}, pr, assigneeIDs); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err) return @@ -596,7 +596,7 @@ func EditPullRequest(ctx *context.APIContext) { ctx.Error(http.StatusNotFound, "NewBaseBranchNotExist", fmt.Errorf("new base '%s' not exist", form.Base)) return } - if err := pull_service.ChangeTargetBranch(pr, ctx.User, form.Base); err != nil { + if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.User, form.Base); err != nil { if models.IsErrPullRequestAlreadyExists(err) { ctx.Error(http.StatusConflict, "IsErrPullRequestAlreadyExists", err) return @@ -836,7 +836,7 @@ func MergePullRequest(ctx *context.APIContext) { message += "\n\n" + form.MergeMessageField } - if err := pull_service.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { + if err := pull_service.Merge(ctx, pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { if models.IsErrInvalidMergeStyle(err) { ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", models.MergeStyle(form.Do))) return @@ -1119,7 +1119,7 @@ func UpdatePullRequest(ctx *context.APIContext) { // default merge commit message message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch) - if err = pull_service.Update(pr, ctx.User, message, rebase); err != nil { + if err = pull_service.Update(ctx, pr, ctx.User, message, rebase); err != nil { if models.IsErrMergeConflicts(err) { ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict") return diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 2f37e10984a0..80a2d3d0b37d 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -1020,7 +1020,7 @@ func Delete(ctx *context.APIContext) { ctx.Repo.GitRepo.Close() } - if err := repo_service.DeleteRepository(ctx.User, repo); err != nil { + if err := repo_service.DeleteRepository(ctx, ctx.User, repo); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteRepository", err) return } diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index f8969067be27..97fc3286a6d0 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -71,7 +71,7 @@ func NewWikiPage(ctx *context.APIContext) { } form.ContentBase64 = string(content) - if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.ContentBase64, form.Message); err != nil { + if err := wiki_service.AddWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName, form.ContentBase64, form.Message); err != nil { if models.IsErrWikiReservedName(err) { ctx.Error(http.StatusBadRequest, "IsErrWikiReservedName", err) } else if models.IsErrWikiAlreadyExist(err) { @@ -144,7 +144,7 @@ func EditWikiPage(ctx *context.APIContext) { } form.ContentBase64 = string(content) - if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.ContentBase64, form.Message); err != nil { + if err := wiki_service.EditWikiPage(ctx, ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.ContentBase64, form.Message); err != nil { ctx.Error(http.StatusInternalServerError, "EditWikiPage", err) return } @@ -233,7 +233,7 @@ func DeleteWikiPage(ctx *context.APIContext) { wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) - if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { + if err := wiki_service.DeleteWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName); err != nil { if err.Error() == "file does not exist" { ctx.NotFound(err) return diff --git a/routers/private/serv.go b/routers/private/serv.go index 9cbd0c2c82e6..6363c3fe91fd 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -390,7 +390,7 @@ func ServCommand(ctx *context.PrivateContext) { } // Finally if we're trying to touch the wiki we should init it - if err = wiki_service.InitWiki(repo); err != nil { + if err = wiki_service.InitWiki(ctx, repo); err != nil { log.Error("Failed to initialize the wiki in %-v Error: %v", repo, err) ctx.JSON(http.StatusInternalServerError, private.ErrServCommand{ Results: results, diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go index 69e522ef7e9b..c82ee2f2cea0 100644 --- a/routers/web/admin/repos.go +++ b/routers/web/admin/repos.go @@ -51,7 +51,7 @@ func DeleteRepo(ctx *context.Context) { ctx.Repo.GitRepo.Close() } - if err := repo_service.DeleteRepository(ctx.User, repo); err != nil { + if err := repo_service.DeleteRepository(ctx, ctx.User, repo); err != nil { ctx.ServerError("DeleteRepository", err) return } diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index 05b45eba4b20..fa9991ce64e7 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -172,7 +172,7 @@ func loadBranches(ctx *context.Context, skip, limit int) ([]*Branch, int) { return nil, 0 } - rawBranches, totalNumOfBranches, err := repo_service.GetBranches(ctx.Repo.Repository, skip, limit) + rawBranches, totalNumOfBranches, err := repo_service.GetBranches(ctx, ctx.Repo.Repository, skip, limit) if err != nil { log.Error("GetBranches: %v", err) ctx.ServerError("GetBranches", err) @@ -351,9 +351,9 @@ func CreateBranch(ctx *context.Context) { } err = release_service.CreateNewTag(ctx.User, ctx.Repo.Repository, target, form.NewBranchName, "") } else if ctx.Repo.IsViewBranch { - err = repo_service.CreateNewBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) + err = repo_service.CreateNewBranch(ctx, ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) } else { - err = repo_service.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName) + err = repo_service.CreateNewBranchFromCommit(ctx, ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName) } if err != nil { if models.IsErrTagAlreadyExists(err) { diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index 3aa8e84f57fa..0ff643d4762b 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -322,7 +322,7 @@ func dummyInfoRefs(ctx *context.Context) { } }() - if err := git.InitRepository(tmpDir, true); err != nil { + if err := git.InitRepository(ctx, tmpDir, true); err != nil { log.Error("Failed to init bare repo for git-receive-pack cache: %v", err) return } @@ -484,7 +484,6 @@ func serviceRPC(h serviceHandler, service string) { h.environ = append(h.environ, "GIT_PROTOCOL="+protocol) } - // ctx, cancel := gocontext.WithCancel(git.DefaultContext) ctx, _, finished := process.GetManager().AddContext(h.r.Context(), fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.dir)) defer finished() diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go index b1bc06f08b46..7717499b7912 100644 --- a/routers/web/repo/lfs.go +++ b/routers/web/repo/lfs.go @@ -115,7 +115,7 @@ func LFSLocks(ctx *context.Context) { } }() - if err := git.Clone(ctx.Repo.Repository.RepoPath(), tmpBasePath, git.CloneRepoOptions{ + if err := git.Clone(ctx, ctx.Repo.Repository.RepoPath(), tmpBasePath, git.CloneRepoOptions{ Bare: true, Shared: true, }); err != nil { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 7593e7fbc885..795548378acf 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -767,7 +767,7 @@ func UpdatePullRequest(ctx *context.Context) { // default merge commit message message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch) - if err = pull_service.Update(issue.PullRequest, ctx.User, message, rebase); err != nil { + if err = pull_service.Update(ctx, issue.PullRequest, ctx.User, message, rebase); err != nil { if models.IsErrMergeConflicts(err) { conflictError := err.(models.ErrMergeConflicts) flashError, err := ctx.HTMLString(string(tplAlertDetails), map[string]interface{}{ @@ -932,7 +932,7 @@ func MergePullRequest(ctx *context.Context) { return } - if err = pull_service.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { + if err = pull_service.Merge(ctx, pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil { if models.IsErrInvalidMergeStyle(err) { ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option")) ctx.Redirect(issue.Link()) @@ -1132,7 +1132,7 @@ func CompareAndPullRequestPost(ctx *context.Context) { // FIXME: check error in the case two people send pull request at almost same time, give nice error prompt // instead of 500. - if err := pull_service.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, assigneeIDs); err != nil { + if err := pull_service.NewPullRequest(ctx, repo, pullIssue, labelIDs, attachments, pullRequest, assigneeIDs); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err.Error()) return @@ -1379,7 +1379,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { return } - if err := pull_service.ChangeTargetBranch(pr, ctx.User, targetBranch); err != nil { + if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.User, targetBranch); err != nil { if models.IsErrPullRequestAlreadyExists(err) { err := err.(models.ErrPullRequestAlreadyExists) diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index 4fc1e91c2529..70bb845d868c 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -666,7 +666,7 @@ func SettingsPost(ctx *context.Context) { ctx.Repo.GitRepo.Close() } - if err := repo_service.DeleteRepository(ctx.User, ctx.Repo.Repository); err != nil { + if err := repo_service.DeleteRepository(ctx, ctx.User, ctx.Repo.Repository); err != nil { ctx.ServerError("DeleteRepository", err) return } @@ -685,7 +685,7 @@ func SettingsPost(ctx *context.Context) { return } - err := wiki_service.DeleteWiki(repo) + err := wiki_service.DeleteWiki(ctx, repo) if err != nil { log.Error("Delete Wiki: %v", err.Error()) } diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 44914a3e3d30..b506566b3891 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -657,7 +657,7 @@ func NewWikiPost(ctx *context.Context) { form.Message = ctx.Tr("repo.editor.add", form.Title) } - if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { + if err := wiki_service.AddWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { if models.IsErrWikiReservedName(err) { ctx.Data["Err_Title"] = true ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form) @@ -711,7 +711,7 @@ func EditWikiPost(ctx *context.Context) { form.Message = ctx.Tr("repo.editor.update", form.Title) } - if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { + if err := wiki_service.EditWikiPage(ctx, ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { ctx.ServerError("EditWikiPage", err) return } @@ -726,7 +726,7 @@ func DeleteWikiPagePost(ctx *context.Context) { wikiName = "Home" } - if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { + if err := wiki_service.DeleteWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName); err != nil { ctx.ServerError("DeleteWikiPage", err) return } diff --git a/services/agit/agit.go b/services/agit/agit.go index beb21940b0cd..11b92e20b095 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -156,7 +156,7 @@ func ProcRecive(ctx *context.PrivateContext, opts *private.HookOptions) []privat Flow: models.PullRequestFlowAGit, } - if err := pull_service.NewPullRequest(repo, prIssue, []int64{}, []string{}, pr, []int64{}); err != nil { + if err := pull_service.NewPullRequest(ctx, repo, prIssue, []int64{}, []string{}, pr, []int64{}); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err.Error()) return nil diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 166660b87e18..f0bb75643b4f 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -1389,7 +1389,7 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff IndexFile: indexFilename, WorkTree: worktree, } - ctx, cancel := context.WithCancel(git.DefaultContext) + ctx, cancel := context.WithCancel(ctx) if err := checker.Init(ctx); err != nil { log.Error("Unable to open checker for %s. Error: %v", opts.AfterCommitID, err) } else { diff --git a/services/migrations/dump.go b/services/migrations/dump.go index afff49a05973..e1181c85ebbf 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -150,7 +150,7 @@ func (g *RepositoryDumper) CreateRepo(repo *base.Repository, opts base.MigrateOp return err } - err = git.Clone(remoteAddr, repoPath, git.CloneRepoOptions{ + err = git.Clone(g.ctx, remoteAddr, repoPath, git.CloneRepoOptions{ Mirror: true, Quiet: true, Timeout: migrateTimeout, @@ -167,7 +167,7 @@ func (g *RepositoryDumper) CreateRepo(repo *base.Repository, opts base.MigrateOp return fmt.Errorf("Failed to remove %s: %v", wikiPath, err) } - if err := git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{ + if err := git.Clone(g.ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ Mirror: true, Quiet: true, Timeout: migrateTimeout, @@ -181,7 +181,7 @@ func (g *RepositoryDumper) CreateRepo(repo *base.Repository, opts base.MigrateOp } } - g.gitRepo, err = git.OpenRepository(g.gitPath()) + g.gitRepo, err = git.OpenRepositoryCtx(g.ctx, g.gitPath()) return err } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 7a2bc125c588..b443cdec1414 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -336,7 +336,7 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool) } log.Trace("SyncMirrors [repo: %-v]: invalidating mirror branch caches...", m.Repo) - branches, _, err := git.GetBranchesByPath(m.Repo.RepoPath(), 0, 0) + branches, _, err := git.GetBranchesByPath(ctx, m.Repo.RepoPath(), 0, 0) if err != nil { log.Error("GetBranches: %v", err) return nil, false diff --git a/services/pull/merge.go b/services/pull/merge.go index 75c089eee879..ecc224330ab4 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" @@ -31,7 +32,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 models.MergeStyle, message string) (err error) { +func Merge(ctx context.Context, pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle models.MergeStyle, message string) (err error) { if err = pr.LoadHeadRepo(); err != nil { log.Error("LoadHeadRepo: %v", err) return fmt.Errorf("LoadHeadRepo: %v", err) @@ -56,7 +57,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, message) + pr.MergedCommitID, err = rawMerge(ctx, pr, doer, mergeStyle, message) if err != nil { return err } @@ -111,7 +112,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 models.MergeStyle, message string) (string, error) { +func rawMerge(ctx context.Context, pr *models.PullRequest, doer *user_model.User, mergeStyle models.MergeStyle, message string) (string, error) { err := git.LoadGitVersion() if err != nil { log.Error("git.LoadGitVersion: %v", err) @@ -119,7 +120,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M } // Clone base repo. - tmpBasePath, err := createTemporaryRepo(pr) + tmpBasePath, err := createTemporaryRepo(ctx, pr) if err != nil { log.Error("CreateTemporaryPath: %v", err) return "", err @@ -137,7 +138,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M 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) @@ -158,11 +159,11 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M 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") } } @@ -203,7 +204,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M 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()) } @@ -242,13 +243,13 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M // Merge commits. switch mergeStyle { case models.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 } @@ -258,7 +259,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M fallthrough case models.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()) } @@ -266,7 +267,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M 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 @@ -314,14 +315,14 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M } // 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 == models.MergeStyleRebase { cmd.AddArguments("--ff-only") } else { @@ -335,14 +336,14 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M return "", err } if mergeStyle == models.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 models.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 @@ -354,7 +355,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M } 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()) } @@ -363,7 +364,7 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M // 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()) } @@ -421,9 +422,9 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M var pushCmd *git.Command if mergeStyle == models.MergeStyleRebaseUpdate { // force push the rebase result to head brach - 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. @@ -451,15 +452,15 @@ func rawMerge(pr *models.PullRequest, doer *user_model.User, mergeStyle models.M 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()) } @@ -498,11 +499,11 @@ func runMergeCommand(pr *models.PullRequest, mergeStyle models.MergeStyle, cmd * 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 diff --git a/services/pull/patch.go b/services/pull/patch.go index b971eb4bf30d..a1e33b72f1e6 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -16,7 +16,9 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/util" "github.com/gobwas/glob" @@ -50,8 +52,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: %s#%d", pr.BaseRepo.FullName(), 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 @@ -62,14 +67,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") diff --git a/services/pull/pull.go b/services/pull/pull.go index 8bfe20c80e69..b3020dba2e9f 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -26,12 +26,12 @@ import ( ) // NewPullRequest creates new pull request with labels for repository. -func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int64, uuids []string, pr *models.PullRequest, assigneeIDs []int64) error { +func NewPullRequest(ctx context.Context, repo *models.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 } @@ -52,7 +52,7 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6 pull.PullRequest = pr if pr.Flow == models.PullRequestFlowGithub { - err = PushToBaseRepo(pr) + err = PushToBaseRepo(ctx, pr) } else { err = UpdateRef(pr) } @@ -114,7 +114,7 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6 } // 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 @@ -183,7 +183,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 } @@ -269,7 +269,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 { @@ -289,7 +289,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 } @@ -311,7 +311,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) @@ -403,11 +403,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 { @@ -431,7 +431,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, @@ -451,8 +451,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) @@ -524,8 +524,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 *models.Repository) error { - branches, _, err := git.GetBranchesByPath(repo.RepoPath(), 0, 0) +func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *models.Repository) error { + branches, _, err := git.GetBranchesByPath(ctx, repo.RepoPath(), 0, 0) if err != nil { return err } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index e30dba7add60..873944803cee 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" @@ -18,7 +19,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) @@ -53,7 +54,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) @@ -90,7 +91,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) @@ -100,7 +101,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) @@ -110,7 +111,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) @@ -128,7 +129,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) @@ -148,11 +149,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 ef6e84598e5d..0d047fff70e4 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" @@ -14,7 +15,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 models.MergeStyle @@ -47,14 +48,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 { @@ -112,7 +113,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 @@ -121,7 +122,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) diff --git a/services/repository/branch.go b/services/repository/branch.go index f33bac762181..6fc5260f5f6d 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -5,6 +5,7 @@ package repository import ( + "context" "errors" "fmt" @@ -18,19 +19,19 @@ import ( ) // CreateNewBranch creates a new repository branch -func CreateNewBranch(doer *user_model.User, repo *models.Repository, oldBranchName, branchName string) (err error) { +func CreateNewBranch(ctx context.Context, doer *user_model.User, repo *models.Repository, oldBranchName, branchName string) (err error) { // Check if branch name can be used - if err := checkBranchName(repo, branchName); err != nil { + if err := checkBranchName(ctx, repo, branchName); err != nil { return err } - if !git.IsBranchExist(git.DefaultContext, repo.RepoPath(), oldBranchName) { + if !git.IsBranchExist(ctx, repo.RepoPath(), oldBranchName) { return models.ErrBranchDoesNotExist{ BranchName: oldBranchName, } } - if err := git.Push(git.DefaultContext, repo.RepoPath(), git.PushOptions{ + if err := git.Push(ctx, repo.RepoPath(), git.PushOptions{ Remote: repo.RepoPath(), Branch: fmt.Sprintf("%s:%s%s", oldBranchName, git.BranchPrefix, branchName), Env: models.PushingEnvironment(doer, repo), @@ -60,32 +61,34 @@ func GetBranch(repo *models.Repository, branch string) (*git.Branch, error) { // GetBranches returns branches from the repository, skipping skip initial branches and // returning at most limit branches, or all branches if limit is 0. -func GetBranches(repo *models.Repository, skip, limit int) ([]*git.Branch, int, error) { - return git.GetBranchesByPath(repo.RepoPath(), skip, limit) +func GetBranches(ctx context.Context, repo *models.Repository, skip, limit int) ([]*git.Branch, int, error) { + return git.GetBranchesByPath(ctx, repo.RepoPath(), skip, limit) } // checkBranchName validates branch name with existing repository branches -func checkBranchName(repo *models.Repository, name string) error { - gitRepo, err := git.OpenRepository(repo.RepoPath()) +// FIXME: There really has to be faster mechanism than this. git cat-file --batch-check will check a branchname +// and or tag name... (git.DefaultContext - as a marker to come back to this) +func checkBranchName(ctx context.Context, repo *models.Repository, name string) error { + gitRepo, err := git.OpenRepositoryCtx(ctx, repo.RepoPath()) if err != nil { return err } defer gitRepo.Close() - branches, _, err := GetBranches(repo, 0, 0) + branches, _, err := gitRepo.GetBranches(0, 0) if err != nil { return err } for _, branch := range branches { - if branch.Name == name { + if branch == name { return models.ErrBranchAlreadyExists{ - BranchName: branch.Name, + BranchName: branch, } - } else if (len(branch.Name) < len(name) && branch.Name+"/" == name[0:len(branch.Name)+1]) || - (len(branch.Name) > len(name) && name+"/" == branch.Name[0:len(name)+1]) { + } else if (len(branch) < len(name) && branch+"/" == name[0:len(branch)+1]) || + (len(branch) > len(name) && name+"/" == branch[0:len(name)+1]) { return models.ErrBranchNameConflict{ - BranchName: branch.Name, + BranchName: branch, } } } @@ -100,9 +103,9 @@ func checkBranchName(repo *models.Repository, name string) error { } // CreateNewBranchFromCommit creates a new repository branch -func CreateNewBranchFromCommit(doer *user_model.User, repo *models.Repository, commit, branchName string) (err error) { +func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo *models.Repository, commit, branchName string) (err error) { // Check if branch name can be used - if err := checkBranchName(repo, branchName); err != nil { + if err := checkBranchName(ctx, repo, branchName); err != nil { return err } diff --git a/services/repository/check.go b/services/repository/check.go index ab7539e55554..a2b4022fa051 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -195,7 +195,7 @@ func ReinitMissingRepositories(ctx context.Context) error { default: } log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID) - if err := git.InitRepository(repo.RepoPath(), true); err != nil { + if err := git.InitRepository(ctx, repo.RepoPath(), true); err != nil { log.Error("Unable (re)initialize repository %d at %s. Error: %v", repo.ID, repo.RepoPath(), err) if err2 := admin_model.CreateRepositoryNotice("InitRepository [%d]: %v", repo.ID, err); err2 != nil { log.Error("CreateRepositoryNotice: %v", err2) diff --git a/services/repository/repository.go b/services/repository/repository.go index 4929f9f446f8..e65ab980b71f 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -5,6 +5,7 @@ package repository import ( + "context" "fmt" "code.gitea.io/gitea/models" @@ -30,8 +31,8 @@ func CreateRepository(doer, owner *user_model.User, opts models.CreateRepoOption } // DeleteRepository deletes a repository for a user or organization. -func DeleteRepository(doer *user_model.User, repo *models.Repository) error { - if err := pull_service.CloseRepoBranchesPulls(doer, repo); err != nil { +func DeleteRepository(ctx context.Context, doer *user_model.User, repo *models.Repository) error { + if err := pull_service.CloseRepoBranchesPulls(ctx, doer, repo); err != nil { log.Error("CloseRepoBranchesPulls failed: %v", err) } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index cf25c33274b2..82d19725bf66 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -6,6 +6,7 @@ package wiki import ( + "context" "fmt" "net/url" "os" @@ -13,7 +14,6 @@ import ( "code.gitea.io/gitea/models" admin_model "code.gitea.io/gitea/models/admin" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -70,16 +70,16 @@ func FilenameToName(filename string) (string, error) { // InitWiki initializes a wiki for repository, // it does nothing when repository already has wiki. -func InitWiki(repo *models.Repository) error { +func InitWiki(ctx context.Context, repo *models.Repository) error { if repo.HasWiki() { return nil } - if err := git.InitRepository(repo.WikiPath(), true); err != nil { + if err := git.InitRepository(ctx, repo.WikiPath(), true); err != nil { return fmt.Errorf("InitRepository: %v", err) } else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil { return fmt.Errorf("createDelegateHooks: %v", err) - } else if _, err = git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").RunInDir(repo.WikiPath()); err != nil { + } else if _, err = git.NewCommandContext(ctx, "symbolic-ref", "HEAD", git.BranchPrefix+"master").RunInDir(repo.WikiPath()); err != nil { return fmt.Errorf("unable to set default wiki branch to master: %v", err) } return nil @@ -117,18 +117,18 @@ func prepareWikiFileName(gitRepo *git.Repository, wikiName string) (bool, string } // updateWikiPage adds a new page to the repository wiki. -func updateWikiPage(doer *user_model.User, repo *models.Repository, oldWikiName, newWikiName, content, message string, isNew bool) (err error) { +func updateWikiPage(ctx context.Context, doer *user_model.User, repo *models.Repository, oldWikiName, newWikiName, content, message string, isNew bool) (err error) { if err = nameAllowed(newWikiName); err != nil { return err } wikiWorkingPool.CheckIn(fmt.Sprint(repo.ID)) defer wikiWorkingPool.CheckOut(fmt.Sprint(repo.ID)) - if err = InitWiki(repo); err != nil { + if err = InitWiki(ctx, repo); err != nil { return fmt.Errorf("InitWiki: %v", err) } - hasMasterBranch := git.IsBranchExist(git.DefaultContext, repo.WikiPath(), "master") + hasMasterBranch := git.IsBranchExist(ctx, repo.WikiPath(), "master") basePath, err := models.CreateTemporaryPath("update-wiki") if err != nil { @@ -149,12 +149,12 @@ func updateWikiPage(doer *user_model.User, repo *models.Repository, oldWikiName, cloneOpts.Branch = "master" } - if err := git.Clone(repo.WikiPath(), basePath, cloneOpts); err != nil { + if err := git.Clone(ctx, repo.WikiPath(), basePath, cloneOpts); err != nil { log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err) } - gitRepo, err := git.OpenRepository(basePath) + gitRepo, err := git.OpenRepositoryCtx(ctx, basePath) if err != nil { log.Error("Unable to open temporary repository: %s (%v)", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) @@ -265,22 +265,22 @@ func updateWikiPage(doer *user_model.User, repo *models.Repository, oldWikiName, } // AddWikiPage adds a new wiki page with a given wikiPath. -func AddWikiPage(doer *user_model.User, repo *models.Repository, wikiName, content, message string) error { - return updateWikiPage(doer, repo, "", wikiName, content, message, true) +func AddWikiPage(ctx context.Context, doer *user_model.User, repo *models.Repository, wikiName, content, message string) error { + return updateWikiPage(ctx, doer, repo, "", wikiName, content, message, true) } // EditWikiPage updates a wiki page identified by its wikiPath, // optionally also changing wikiPath. -func EditWikiPage(doer *user_model.User, repo *models.Repository, oldWikiName, newWikiName, content, message string) error { - return updateWikiPage(doer, repo, oldWikiName, newWikiName, content, message, false) +func EditWikiPage(ctx context.Context, doer *user_model.User, repo *models.Repository, oldWikiName, newWikiName, content, message string) error { + return updateWikiPage(ctx, doer, repo, oldWikiName, newWikiName, content, message, false) } // DeleteWikiPage deletes a wiki page identified by its path. -func DeleteWikiPage(doer *user_model.User, repo *models.Repository, wikiName string) (err error) { +func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *models.Repository, wikiName string) (err error) { wikiWorkingPool.CheckIn(fmt.Sprint(repo.ID)) defer wikiWorkingPool.CheckOut(fmt.Sprint(repo.ID)) - if err = InitWiki(repo); err != nil { + if err = InitWiki(ctx, repo); err != nil { return fmt.Errorf("InitWiki: %v", err) } @@ -294,7 +294,7 @@ func DeleteWikiPage(doer *user_model.User, repo *models.Repository, wikiName str } }() - if err := git.Clone(repo.WikiPath(), basePath, git.CloneRepoOptions{ + if err := git.Clone(ctx, repo.WikiPath(), basePath, git.CloneRepoOptions{ Bare: true, Shared: true, Branch: "master", @@ -303,7 +303,7 @@ func DeleteWikiPage(doer *user_model.User, repo *models.Repository, wikiName str return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err) } - gitRepo, err := git.OpenRepository(basePath) + gitRepo, err := git.OpenRepositoryCtx(ctx, basePath) if err != nil { log.Error("Unable to open temporary repository: %s (%v)", basePath, err) return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) @@ -372,11 +372,11 @@ func DeleteWikiPage(doer *user_model.User, repo *models.Repository, wikiName str } // DeleteWiki removes the actual and local copy of repository wiki. -func DeleteWiki(repo *models.Repository) error { +func DeleteWiki(ctx context.Context, repo *models.Repository) error { if err := models.UpdateRepositoryUnits(repo, nil, []unit.Type{unit.TypeWiki}); err != nil { return err } - admin_model.RemoveAllWithNotice(db.DefaultContext, "Delete repository wiki", repo.WikiPath()) + admin_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) return nil } diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index 5b42dd590f76..8b5735cef5c4 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -114,11 +114,11 @@ func TestRepository_InitWiki(t *testing.T) { unittest.PrepareTestEnv(t) // repo1 already has a wiki repo1 := unittest.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) - assert.NoError(t, InitWiki(repo1)) + assert.NoError(t, InitWiki(git.DefaultContext, repo1)) // repo2 does not already have a wiki repo2 := unittest.AssertExistsAndLoadBean(t, &models.Repository{ID: 2}).(*models.Repository) - assert.NoError(t, InitWiki(repo2)) + assert.NoError(t, InitWiki(git.DefaultContext, repo2)) assert.True(t, repo2.HasWiki()) } @@ -135,9 +135,9 @@ func TestRepository_AddWikiPage(t *testing.T) { wikiName := wikiName t.Run("test wiki exist: "+wikiName, func(t *testing.T) { t.Parallel() - assert.NoError(t, AddWikiPage(doer, repo, wikiName, wikiContent, commitMsg)) + assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, wikiName, wikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(repo.WikiPath()) + gitRepo, err := git.OpenRepositoryCtx(git.DefaultContext, repo.WikiPath()) assert.NoError(t, err) defer gitRepo.Close() masterTree, err := gitRepo.GetTree("master") @@ -152,7 +152,7 @@ func TestRepository_AddWikiPage(t *testing.T) { t.Run("check wiki already exist", func(t *testing.T) { t.Parallel() // test for already-existing wiki name - err := AddWikiPage(doer, repo, "Home", wikiContent, commitMsg) + err := AddWikiPage(git.DefaultContext, doer, repo, "Home", wikiContent, commitMsg) assert.Error(t, err) assert.True(t, models.IsErrWikiAlreadyExist(err)) }) @@ -160,7 +160,7 @@ func TestRepository_AddWikiPage(t *testing.T) { t.Run("check wiki reserved name", func(t *testing.T) { t.Parallel() // test for reserved wiki name - err := AddWikiPage(doer, repo, "_edit", wikiContent, commitMsg) + err := AddWikiPage(git.DefaultContext, doer, repo, "_edit", wikiContent, commitMsg) assert.Error(t, err) assert.True(t, models.IsErrWikiReservedName(err)) }) @@ -179,10 +179,10 @@ func TestRepository_EditWikiPage(t *testing.T) { "New/name/with/slashes", } { unittest.PrepareTestEnv(t) - assert.NoError(t, EditWikiPage(doer, repo, "Home", newWikiName, newWikiContent, commitMsg)) + assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", newWikiName, newWikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(repo.WikiPath()) + gitRepo, err := git.OpenRepositoryCtx(git.DefaultContext, repo.WikiPath()) assert.NoError(t, err) masterTree, err := gitRepo.GetTree("master") assert.NoError(t, err) @@ -203,10 +203,10 @@ func TestRepository_DeleteWikiPage(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - assert.NoError(t, DeleteWikiPage(doer, repo, "Home")) + assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home")) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(repo.WikiPath()) + gitRepo, err := git.OpenRepositoryCtx(git.DefaultContext, repo.WikiPath()) assert.NoError(t, err) defer gitRepo.Close() masterTree, err := gitRepo.GetTree("master") @@ -219,7 +219,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { func TestPrepareWikiFileName(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) - gitRepo, err := git.OpenRepository(repo.WikiPath()) + gitRepo, err := git.OpenRepositoryCtx(git.DefaultContext, repo.WikiPath()) defer gitRepo.Close() assert.NoError(t, err) @@ -279,7 +279,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) { } }() - err = git.InitRepository(tmpDir, true) + err = git.InitRepository(git.DefaultContext, tmpDir, true) assert.NoError(t, err) gitRepo, err := git.OpenRepository(tmpDir)