diff options
author | zeripath <art27@cantab.net> | 2022-01-19 23:26:57 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-19 23:26:57 +0000 |
commit | 5cb0c9aa0d7eed087055b1efca79628957207d36 (patch) | |
tree | d117a514e1f17e5f6bfcda1be273f6a971112663 /models | |
parent | 4563148a61ba892e8f2bb66342f00a950bcd5315 (diff) | |
download | gitea-5cb0c9aa0d7eed087055b1efca79628957207d36.tar.gz gitea-5cb0c9aa0d7eed087055b1efca79628957207d36.zip |
Propagate context and ensure git commands run in request context (#17868)
This PR continues the work in #17125 by progressively ensuring that git
commands run within the request context.
This now means that the if there is a git repo already open in the context it will be used instead of reopening it.
Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'models')
-rw-r--r-- | models/admin/notice.go | 8 | ||||
-rw-r--r-- | models/db/context.go | 7 | ||||
-rwxr-xr-x | models/db/engine.go | 1 | ||||
-rw-r--r-- | models/issue_comment.go | 25 | ||||
-rw-r--r-- | models/issue_comment_test.go | 5 | ||||
-rw-r--r-- | models/issue_xref_test.go | 2 | ||||
-rw-r--r-- | models/migrations/v136.go | 3 | ||||
-rw-r--r-- | models/migrations/v156.go | 2 | ||||
-rw-r--r-- | models/migrations/v82.go | 2 | ||||
-rw-r--r-- | models/pull.go | 3 | ||||
-rw-r--r-- | models/repo/repo.go | 3 | ||||
-rw-r--r-- | models/repo_activity.go | 13 | ||||
-rw-r--r-- | models/review.go | 20 | ||||
-rw-r--r-- | models/review_test.go | 11 |
14 files changed, 57 insertions, 48 deletions
diff --git a/models/admin/notice.go b/models/admin/notice.go index 2d71b426dd..daf095f680 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/models/db/context.go b/models/db/context.go index 55e38ba7e5..833c26ff6c 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -35,7 +35,7 @@ type Context struct { func WithEngine(ctx context.Context, e Engine) *Context { return &Context{ Context: ctx, - e: e, + e: e.Context(ctx), } } @@ -52,6 +52,11 @@ func (ctx *Context) Value(key interface{}) interface{} { return ctx.Context.Value(key) } +// WithContext returns this engine tied to this context +func (ctx *Context) WithContext(other context.Context) *Context { + return WithEngine(other, ctx.e) +} + // Engined structs provide an Engine type Engined interface { Engine() Engine diff --git a/models/db/engine.go b/models/db/engine.go index 63e1d5547a..665808d701 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -64,6 +64,7 @@ type Engine interface { Distinct(...string) *xorm.Session Query(...interface{}) ([]map[string][]byte, error) Cols(...string) *xorm.Session + Context(ctx context.Context) *xorm.Session } // TableInfo returns table's information via an object diff --git a/models/issue_comment.go b/models/issue_comment.go index f4a6b3ce13..bf36881a00 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -724,7 +724,7 @@ func (c *Comment) CodeCommentURL() string { } // LoadPushCommits Load push commits -func (c *Comment) LoadPushCommits() (err error) { +func (c *Comment) LoadPushCommits(ctx context.Context) (err error) { if c.Content == "" || c.Commits != nil || c.Type != CommentTypePullPush { return nil } @@ -746,11 +746,11 @@ func (c *Comment) LoadPushCommits() (err error) { c.NewCommit = data.CommitIDs[1] } else { repoPath := c.Issue.Repo.RepoPath() - gitRepo, err := git.OpenRepository(repoPath) + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath) if err != nil { return err } - defer gitRepo.Close() + defer closer.Close() c.Commits = ConvertFromGitCommit(gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo) c.CommitsNum = int64(len(c.Commits)) @@ -1272,6 +1272,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu var err error if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ + Ctx: ctx, URLPrefix: issue.Repo.Link(), Metas: issue.Repo.ComposeMetas(), }, comment.Content); err != nil { @@ -1282,19 +1283,19 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu } // FetchCodeCommentsByLine fetches the code comments for a given treePath and line number -func FetchCodeCommentsByLine(issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) { +func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) { opts := FindCommentsOptions{ Type: CommentTypeCode, IssueID: issue.ID, TreePath: treePath, Line: line, } - return findCodeComments(db.DefaultContext, opts, issue, currentUser, nil) + return findCodeComments(ctx, opts, issue, currentUser, nil) } // FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line -func FetchCodeComments(issue *Issue, currentUser *user_model.User) (CodeComments, error) { - return fetchCodeComments(db.DefaultContext, issue, currentUser) +func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) { + return fetchCodeComments(ctx, issue, currentUser) } // UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id @@ -1318,7 +1319,7 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID } // CreatePushPullComment create push code to pull base comment -func CreatePushPullComment(pusher *user_model.User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) { +func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) { if pr.HasMerged || oldCommitID == "" || newCommitID == "" { return nil, nil } @@ -1331,7 +1332,7 @@ func CreatePushPullComment(pusher *user_model.User, pr *PullRequest, oldCommitID var data PushActionContent - data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) + data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) if err != nil { return nil, err } @@ -1353,13 +1354,13 @@ func CreatePushPullComment(pusher *user_model.User, pr *PullRequest, oldCommitID // getCommitsFromRepo get commit IDs from repo in between oldCommitID and newCommitID // isForcePush will be true if oldCommit isn't on the branch // Commit on baseBranch will skip -func getCommitIDsFromRepo(repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { +func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { repoPath := repo.RepoPath() - gitRepo, err := git.OpenRepository(repoPath) + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath) if err != nil { return nil, false, err } - defer gitRepo.Close() + defer closer.Close() oldCommit, err := gitRepo.GetCommit(oldCommitID) if err != nil { diff --git a/models/issue_comment_test.go b/models/issue_comment_test.go index ec318688ee..d323a08167 100644 --- a/models/issue_comment_test.go +++ b/models/issue_comment_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -49,7 +50,7 @@ func TestFetchCodeComments(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 2}).(*Issue) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User) - res, err := FetchCodeComments(issue, user) + res, err := FetchCodeComments(db.DefaultContext, issue, user) assert.NoError(t, err) assert.Contains(t, res, "README.md") assert.Contains(t, res["README.md"], int64(4)) @@ -57,7 +58,7 @@ func TestFetchCodeComments(t *testing.T) { assert.Equal(t, int64(4), res["README.md"][4][0].ID) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - res, err = FetchCodeComments(issue, user2) + res, err = FetchCodeComments(db.DefaultContext, issue, user2) assert.NoError(t, err) assert.Len(t, res, 1) } diff --git a/models/issue_xref_test.go b/models/issue_xref_test.go index 9b1cb5e2d5..1deeb44ad5 100644 --- a/models/issue_xref_test.go +++ b/models/issue_xref_test.go @@ -162,7 +162,7 @@ func testCreatePR(t *testing.T, repo, doer int64, title, content string) *PullRe d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}).(*user_model.User) i := &Issue{RepoID: r.ID, PosterID: d.ID, Poster: d, Title: title, Content: content, IsPull: true} pr := &PullRequest{HeadRepoID: repo, BaseRepoID: repo, HeadBranch: "head", BaseBranch: "base", Status: PullRequestStatusMergeable} - assert.NoError(t, NewPullRequest(r, i, nil, nil, pr)) + assert.NoError(t, NewPullRequest(db.DefaultContext, r, i, nil, nil, pr)) pr.Issue = i return pr } diff --git a/models/migrations/v136.go b/models/migrations/v136.go index 101cf75955..94372e4142 100644 --- a/models/migrations/v136.go +++ b/models/migrations/v136.go @@ -12,6 +12,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -90,7 +91,7 @@ func addCommitDivergenceToPulls(x *xorm.Engine) error { gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) - divergence, err := git.GetDivergingCommits(repoPath, pr.BaseBranch, gitRefName) + divergence, err := git.GetDivergingCommits(graceful.GetManager().HammerContext(), repoPath, pr.BaseBranch, gitRefName) if err != nil { log.Warn("Could not recalculate Divergence for pull: %d", pr.ID) pr.CommitsAhead = 0 diff --git a/models/migrations/v156.go b/models/migrations/v156.go index 7158d7bb6b..77aed3ff57 100644 --- a/models/migrations/v156.go +++ b/models/migrations/v156.go @@ -109,7 +109,7 @@ func fixPublisherIDforTagReleases(x *xorm.Engine) error { return err } } - gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name)) + gitRepo, err = git.OpenRepositoryCtx(git.DefaultContext, repoPath(repo.OwnerName, repo.Name)) if err != nil { log.Error("Error whilst opening git repo for [%d]%s/%s. Error: %v", repo.ID, repo.OwnerName, repo.Name, err) return err diff --git a/models/migrations/v82.go b/models/migrations/v82.go index 67bb0cb8c9..7f9f979d95 100644 --- a/models/migrations/v82.go +++ b/models/migrations/v82.go @@ -99,7 +99,7 @@ func fixReleaseSha1OnReleaseTable(x *xorm.Engine) error { userCache[repo.OwnerID] = user } - gitRepo, err = git.OpenRepository(RepoPath(user.Name, repo.Name)) + gitRepo, err = git.OpenRepositoryCtx(git.DefaultContext, RepoPath(user.Name, repo.Name)) if err != nil { return err } diff --git a/models/pull.go b/models/pull.go index 243d40b1fa..d6bfbbf09f 100644 --- a/models/pull.go +++ b/models/pull.go @@ -436,7 +436,7 @@ func (pr *PullRequest) SetMerged() (bool, error) { } // NewPullRequest creates new pull request with labels for repository. -func NewPullRequest(repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) { +func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) { idx, err := db.GetNextResourceIndex("issue_index", repo.ID) if err != nil { return fmt.Errorf("generate pull request index failed: %v", err) @@ -449,6 +449,7 @@ func NewPullRequest(repo *repo_model.Repository, issue *Issue, labelIDs []int64, return err } defer committer.Close() + ctx.WithContext(outerCtx) if err = newIssue(ctx, issue.Poster, NewIssueOptions{ Repo: repo, diff --git a/models/repo/repo.go b/models/repo/repo.go index 5108231cd8..a78d287315 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -485,8 +485,9 @@ func (repo *Repository) CanEnableEditor() bool { } // DescriptionHTML does special handles to description and return HTML string. -func (repo *Repository) DescriptionHTML() template.HTML { +func (repo *Repository) DescriptionHTML(ctx context.Context) template.HTML { desc, err := markup.RenderDescriptionHTML(&markup.RenderContext{ + Ctx: ctx, URLPrefix: repo.HTMLURL(), Metas: repo.ComposeMetas(), }, repo.Description) diff --git a/models/repo_activity.go b/models/repo_activity.go index 5bdea80b97..7475be2b11 100644 --- a/models/repo_activity.go +++ b/models/repo_activity.go @@ -5,6 +5,7 @@ package models import ( + "context" "fmt" "sort" "time" @@ -43,7 +44,7 @@ type ActivityStats struct { } // GetActivityStats return stats for repository at given time range -func GetActivityStats(repo *repo_model.Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) { +func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) { stats := &ActivityStats{Code: &git.CodeActivityStats{}} if releases { if err := stats.FillReleases(repo.ID, timeFrom); err != nil { @@ -64,11 +65,11 @@ func GetActivityStats(repo *repo_model.Repository, timeFrom time.Time, releases, return nil, fmt.Errorf("FillUnresolvedIssues: %v", err) } if code { - gitRepo, err := git.OpenRepository(repo.RepoPath()) + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) if err != nil { return nil, fmt.Errorf("OpenRepository: %v", err) } - defer gitRepo.Close() + defer closer.Close() code, err := gitRepo.GetCodeActivityStats(timeFrom, repo.DefaultBranch) if err != nil { @@ -80,12 +81,12 @@ func GetActivityStats(repo *repo_model.Repository, timeFrom time.Time, releases, } // GetActivityStatsTopAuthors returns top author stats for git commits for all branches -func GetActivityStatsTopAuthors(repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) { - gitRepo, err := git.OpenRepository(repo.RepoPath()) +func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) { + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) if err != nil { return nil, fmt.Errorf("OpenRepository: %v", err) } - defer gitRepo.Close() + defer closer.Close() code, err := gitRepo.GetCodeActivityStats(timeFrom, "") if err != nil { diff --git a/models/review.go b/models/review.go index 88d0819089..8b0092b1ed 100644 --- a/models/review.go +++ b/models/review.go @@ -86,7 +86,8 @@ func init() { db.RegisterModel(new(Review)) } -func (r *Review) loadCodeComments(ctx context.Context) (err error) { +// LoadCodeComments loads CodeComments +func (r *Review) LoadCodeComments(ctx context.Context) (err error) { if r.CodeComments != nil { return } @@ -97,11 +98,6 @@ func (r *Review) loadCodeComments(ctx context.Context) (err error) { return } -// LoadCodeComments loads CodeComments -func (r *Review) LoadCodeComments() error { - return r.loadCodeComments(db.DefaultContext) -} - func (r *Review) loadIssue(e db.Engine) (err error) { if r.Issue != nil { return @@ -137,12 +133,13 @@ func (r *Review) LoadReviewerTeam() error { return r.loadReviewerTeam(db.GetEngine(db.DefaultContext)) } -func (r *Review) loadAttributes(ctx context.Context) (err error) { +// LoadAttributes loads all attributes except CodeComments +func (r *Review) LoadAttributes(ctx context.Context) (err error) { e := db.GetEngine(ctx) if err = r.loadIssue(e); err != nil { return } - if err = r.loadCodeComments(ctx); err != nil { + if err = r.LoadCodeComments(ctx); err != nil { return } if err = r.loadReviewer(e); err != nil { @@ -154,11 +151,6 @@ func (r *Review) loadAttributes(ctx context.Context) (err error) { return } -// LoadAttributes loads all attributes except CodeComments -func (r *Review) LoadAttributes() error { - return r.loadAttributes(db.DefaultContext) -} - func getReviewByID(e db.Engine, id int64) (*Review, error) { review := new(Review) if has, err := e.ID(id).Get(review); err != nil { @@ -405,7 +397,7 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co return nil, nil, err } } else { - if err := review.loadCodeComments(ctx); err != nil { + if err := review.LoadCodeComments(ctx); err != nil { return nil, nil, err } if reviewType != ReviewTypeApprove && len(review.CodeComments) == 0 && len(strings.TrimSpace(content)) == 0 { diff --git a/models/review_test.go b/models/review_test.go index b9d156ceb1..20810dac4a 100644 --- a/models/review_test.go +++ b/models/review_test.go @@ -7,6 +7,7 @@ package models import ( "testing" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -28,23 +29,23 @@ func TestGetReviewByID(t *testing.T) { func TestReview_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) review := unittest.AssertExistsAndLoadBean(t, &Review{ID: 1}).(*Review) - assert.NoError(t, review.LoadAttributes()) + assert.NoError(t, review.LoadAttributes(db.DefaultContext)) assert.NotNil(t, review.Issue) assert.NotNil(t, review.Reviewer) invalidReview1 := unittest.AssertExistsAndLoadBean(t, &Review{ID: 2}).(*Review) - assert.Error(t, invalidReview1.LoadAttributes()) + assert.Error(t, invalidReview1.LoadAttributes(db.DefaultContext)) invalidReview2 := unittest.AssertExistsAndLoadBean(t, &Review{ID: 3}).(*Review) - assert.Error(t, invalidReview2.LoadAttributes()) + assert.Error(t, invalidReview2.LoadAttributes(db.DefaultContext)) } func TestReview_LoadCodeComments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) review := unittest.AssertExistsAndLoadBean(t, &Review{ID: 4}).(*Review) - assert.NoError(t, review.LoadAttributes()) - assert.NoError(t, review.LoadCodeComments()) + assert.NoError(t, review.LoadAttributes(db.DefaultContext)) + assert.NoError(t, review.LoadCodeComments(db.DefaultContext)) assert.Len(t, review.CodeComments, 1) assert.Equal(t, int64(4), review.CodeComments["README.md"][int64(4)][0].Line) } |