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>
This commit is contained in:
parent
4563148a61
commit
5cb0c9aa0d
193 changed files with 1264 additions and 1154 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue