From d710af6669654f27f02b69d7ef1ba563e7d58a90 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 21 Nov 2021 23:41:00 +0800 Subject: [PATCH] Remove NewSession method from db.Engine interface (#17577) * Remove NewSession method from db.Engine interface * Fix bug * Some improvements * Fix bug * Fix test * Use XXXBean instead of XXXExample --- models/branches.go | 11 ++- models/db/context.go | 55 ++++++----- models/db/engine.go | 1 + models/db/list_options.go | 2 +- models/issue.go | 21 ++--- models/issue_comment.go | 16 ++-- models/issue_dependency.go | 2 +- models/issue_label.go | 10 +- models/issue_milestone.go | 60 ++++++------ models/issue_reaction.go | 29 +++--- models/lfs.go | 46 ++++----- models/lfs_lock.go | 8 +- models/login/oauth2_application.go | 21 +++-- models/login/session.go | 35 ++++--- models/migrate.go | 56 +++++------ models/notification.go | 29 +++--- models/org.go | 41 +++----- models/org_team.go | 145 +++++++++++++---------------- models/project.go | 60 ++++++------ models/project_board.go | 19 ++-- models/project_issue.go | 9 +- models/pull.go | 9 +- models/repo.go | 92 +++++++++--------- models/repo_avatar.go | 20 ++-- models/repo_collaboration.go | 42 +++++---- models/repo_language_stats.go | 19 ++-- models/repo_list.go | 12 +-- models/repo_permission.go | 3 +- models/repo_transfer.go | 32 ++++--- models/repo_watch.go | 10 +- models/review.go | 26 +++--- models/ssh_key.go | 36 +++---- models/ssh_key_deploy.go | 24 ++--- models/ssh_key_principals.go | 11 ++- models/star.go | 26 +++--- models/task.go | 12 +-- models/topic.go | 19 ++-- models/upload.go | 10 +- models/user.go | 38 ++++---- models/user/follow.go | 40 ++++---- models/user_avatar.go | 10 +- models/user_email.go | 19 ++-- models/user_test.go | 10 +- models/webhook/webhook.go | 24 ++--- 44 files changed, 600 insertions(+), 620 deletions(-) diff --git a/models/branches.go b/models/branches.go index 50de52a277..fc0da58e38 100644 --- a/models/branches.go +++ b/models/branches.go @@ -614,12 +614,13 @@ func FindRenamedBranch(repoID int64, from string) (branch *RenamedBranch, exist // RenameBranch rename a branch func (repo *Repository) RenameBranch(from, to string, gitAction func(isDefault bool) error) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) // 1. update default branch if needed isDefault := repo.DefaultBranch == from if isDefault { @@ -663,10 +664,10 @@ func (repo *Repository) RenameBranch(from, to string, gitAction func(isDefault b From: from, To: to, } - _, err = sess.Insert(renamedBranch) + err = db.Insert(ctx, renamedBranch) if err != nil { return err } - return sess.Commit() + return committer.Commit() } diff --git a/models/db/context.go b/models/db/context.go index 62b77bc72f..55e38ba7e5 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -6,11 +6,11 @@ package db import ( "context" + "database/sql" "code.gitea.io/gitea/modules/setting" "xorm.io/builder" - "xorm.io/xorm" ) // DefaultContext is the default context to run xorm queries in @@ -44,15 +44,6 @@ func (ctx *Context) Engine() Engine { return ctx.e } -// NewSession returns a new session -func (ctx *Context) NewSession() *xorm.Session { - e, ok := ctx.e.(*xorm.Engine) - if ok { - return e.NewSession() - } - return nil -} - // Value shadows Value for context.Context but allows us to get ourselves and an Engined object func (ctx *Context) Value(key interface{}) interface{} { if key == EnginedContextKey { @@ -64,7 +55,6 @@ func (ctx *Context) Value(key interface{}) interface{} { // Engined structs provide an Engine type Engined interface { Engine() Engine - NewSession() *xorm.Session } // GetEngine will get a db Engine from this context or return an Engine restricted to this context @@ -79,24 +69,6 @@ func GetEngine(ctx context.Context) Engine { return x.Context(ctx) } -// NewSession will get a db Session from this context or return a session restricted to this context -func NewSession(ctx context.Context) *xorm.Session { - if engined, ok := ctx.(Engined); ok { - return engined.NewSession() - } - - enginedInterface := ctx.Value(EnginedContextKey) - if enginedInterface != nil { - sess := enginedInterface.(Engined).NewSession() - if sess != nil { - return sess.Context(ctx) - } - return nil - } - - return x.NewSession().Context(ctx) -} - // Committer represents an interface to Commit or Close the Context type Committer interface { Commit() error @@ -155,3 +127,28 @@ func Insert(ctx context.Context, beans ...interface{}) error { _, err := GetEngine(ctx).Insert(beans...) return err } + +// Exec executes a sql with args +func Exec(ctx context.Context, sqlAndArgs ...interface{}) (sql.Result, error) { + return GetEngine(ctx).Exec(sqlAndArgs...) +} + +// GetByBean filled empty fields of the bean according non-empty fields to query in database. +func GetByBean(ctx context.Context, bean interface{}) (bool, error) { + return GetEngine(ctx).Get(bean) +} + +// DeleteByBean deletes all records according non-empty fields of the bean as conditions. +func DeleteByBean(ctx context.Context, bean interface{}) (int64, error) { + return GetEngine(ctx).Delete(bean) +} + +// CountByBean counts the number of database records according non-empty fields of the bean as conditions. +func CountByBean(ctx context.Context, bean interface{}) (int64, error) { + return GetEngine(ctx).Count(bean) +} + +// TableName returns the table name according a bean object +func TableName(bean interface{}) string { + return x.TableName(bean) +} diff --git a/models/db/engine.go b/models/db/engine.go index b97e954cc3..0f744d027e 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -55,6 +55,7 @@ type Engine interface { Asc(colNames ...string) *xorm.Session Desc(colNames ...string) *xorm.Session Limit(limit int, start ...int) *xorm.Session + NoAutoTime() *xorm.Session SumInt(bean interface{}, columnName string) (res int64, err error) Sync2(...interface{}) error Select(string) *xorm.Session diff --git a/models/db/list_options.go b/models/db/list_options.go index f31febfe25..843e73c8ae 100644 --- a/models/db/list_options.go +++ b/models/db/list_options.go @@ -24,7 +24,7 @@ func GetPaginatedSession(p Paginator) *xorm.Session { } // SetSessionPagination sets pagination for a database session -func SetSessionPagination(sess *xorm.Session, p Paginator) *xorm.Session { +func SetSessionPagination(sess Engine, p Paginator) *xorm.Session { skip, take := p.GetSkipTake() return sess.Limit(take, skip) diff --git a/models/issue.go b/models/issue.go index 1b9d35d1e3..6de7c3204b 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1349,10 +1349,9 @@ func applyReviewRequestedCondition(sess *xorm.Session, reviewRequestedID int64) // CountIssuesByRepo map from repoID to number of issues matching the options func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + e := db.GetEngine(db.DefaultContext) - sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") + sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSession(sess) @@ -1377,10 +1376,9 @@ func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { // GetRepoIDsForIssuesOptions find all repo ids for the given options func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *User) ([]int64, error) { repoIDs := make([]int64, 0, 5) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + e := db.GetEngine(db.DefaultContext) - sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") + sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSession(sess) @@ -1397,10 +1395,9 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *User) ([]int64, error // Issues returns a list of issues by given conditions. func Issues(opts *IssuesOptions) ([]*Issue, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + e := db.GetEngine(db.DefaultContext) - sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") + sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSession(sess) sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID) @@ -1419,15 +1416,14 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) { // CountIssues number return of issues by given conditions. func CountIssues(opts *IssuesOptions) (int64, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + e := db.GetEngine(db.DefaultContext) countsSlice := make([]*struct { RepoID int64 Count int64 }, 0, 1) - sess.Select("COUNT(issue.id) AS count").Table("issue") + sess := e.Select("COUNT(issue.id) AS count").Table("issue") sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") opts.setupSession(sess) if err := sess.Find(&countsSlice); err != nil { @@ -1901,7 +1897,6 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *Us if issue.DeadlineUnix == deadlineUnix { return nil } - ctx, committer, err := db.TxContext() if err != nil { return err diff --git a/models/issue_comment.go b/models/issue_comment.go index fccc139cd0..8429596c82 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -1098,17 +1098,17 @@ func UpdateComment(c *Comment, doer *User) error { // DeleteComment deletes the comment func DeleteComment(comment *Comment) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := deleteComment(db.GetEngine(ctx), comment); err != nil { return err } - if err := deleteComment(sess, comment); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func deleteComment(e db.Engine, comment *Comment) error { diff --git a/models/issue_dependency.go b/models/issue_dependency.go index ee984fbe3e..ab81ef0c68 100644 --- a/models/issue_dependency.go +++ b/models/issue_dependency.go @@ -61,7 +61,7 @@ func CreateIssueDependency(user *User, issue, dep *Issue) error { return ErrCircularDependency{issue.ID, dep.ID} } - if _, err := sess.Insert(&IssueDependency{ + if err := db.Insert(ctx, &IssueDependency{ UserID: user.ID, IssueID: issue.ID, DependencyID: dep.ID, diff --git a/models/issue_label.go b/models/issue_label.go index 492e298600..2858b12dde 100644 --- a/models/issue_label.go +++ b/models/issue_label.go @@ -297,11 +297,13 @@ func DeleteLabel(id, labelID int64) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) if label.BelongsToOrg() && label.OrgID != id { return nil @@ -323,7 +325,7 @@ func DeleteLabel(id, labelID int64) error { return err } - return sess.Commit() + return committer.Commit() } // getLabelByID returns a label by label id diff --git a/models/issue_milestone.go b/models/issue_milestone.go index fd5d052cbd..de4e13b4bb 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -85,22 +85,22 @@ func (m *Milestone) State() api.StateType { // NewMilestone creates new milestone of repository. func NewMilestone(m *Milestone) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() m.Name = strings.TrimSpace(m.Name) - if _, err = sess.Insert(m); err != nil { + if err = db.Insert(ctx, m); err != nil { return err } - if _, err = sess.Exec("UPDATE `repository` SET num_milestones = num_milestones + 1 WHERE id = ?", m.RepoID); err != nil { + if _, err = db.Exec(ctx, "UPDATE `repository` SET num_milestones = num_milestones + 1 WHERE id = ?", m.RepoID); err != nil { return err } - return sess.Commit() + return committer.Commit() } func getMilestoneByRepoID(e db.Engine, repoID, id int64) (*Milestone, error) { @@ -150,11 +150,13 @@ func getMilestoneByID(e db.Engine, id int64) (*Milestone, error) { // UpdateMilestone updates information of given milestone. func UpdateMilestone(m *Milestone, oldIsClosed bool) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) if m.IsClosed && !oldIsClosed { m.ClosedDateUnix = timeutil.TimeStampNow() @@ -171,7 +173,7 @@ func UpdateMilestone(m *Milestone, oldIsClosed bool) error { } } - return sess.Commit() + return committer.Commit() } func updateMilestone(e db.Engine, m *Milestone) error { @@ -207,11 +209,13 @@ func updateMilestoneCounters(e db.Engine, id int64) error { // ChangeMilestoneStatusByRepoIDAndID changes a milestone open/closed status if the milestone ID is in the repo. func ChangeMilestoneStatusByRepoIDAndID(repoID, milestoneID int64, isClosed bool) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) m := &Milestone{ ID: milestoneID, @@ -229,22 +233,22 @@ func ChangeMilestoneStatusByRepoIDAndID(repoID, milestoneID int64, isClosed bool return err } - return sess.Commit() + return committer.Commit() } // ChangeMilestoneStatus changes the milestone open/closed status. func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := changeMilestoneStatus(db.GetEngine(ctx), m, isClosed); err != nil { return err } - if err := changeMilestoneStatus(sess, m, isClosed); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func changeMilestoneStatus(e db.Engine, m *Milestone, isClosed bool) error { @@ -335,11 +339,13 @@ func DeleteMilestoneByRepoID(repoID, id int64) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) if _, err = sess.ID(m.ID).Delete(new(Milestone)); err != nil { return err @@ -360,10 +366,10 @@ func DeleteMilestoneByRepoID(repoID, id int64) error { return err } - if _, err = sess.Exec("UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?", m.ID); err != nil { + if _, err = db.Exec(ctx, "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?", m.ID); err != nil { return err } - return sess.Commit() + return committer.Commit() } // MilestoneList is a list of milestones offering additional functionality diff --git a/models/issue_reaction.go b/models/issue_reaction.go index 2f64609e99..933246544b 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" - "xorm.io/xorm" ) // Reaction represents a reactions on issues and comments. @@ -102,7 +101,7 @@ func findReactions(e db.Engine, opts FindReactionsOptions) ([]*Reaction, error) return reactions, e.Find(&reactions) } -func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) { +func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) { reaction := &Reaction{ Type: opts.Type, UserID: opts.Doer.ID, @@ -148,18 +147,18 @@ func CreateReaction(opts *ReactionOptions) (*Reaction, error) { return nil, ErrForbiddenIssueReaction{opts.Type} } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() - reaction, err := createReaction(sess, opts) + reaction, err := createReaction(db.GetEngine(ctx), opts) if err != nil { return reaction, err } - if err := sess.Commit(); err != nil { + if err := committer.Commit(); err != nil { return nil, err } return reaction, nil @@ -203,17 +202,17 @@ func deleteReaction(e db.Engine, opts *ReactionOptions) error { // DeleteReaction deletes reaction for issue or comment. func DeleteReaction(opts *ReactionOptions) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := deleteReaction(db.GetEngine(ctx), opts); err != nil { return err } - if err := deleteReaction(sess, opts); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // DeleteIssueReaction deletes a reaction on issue. diff --git a/models/lfs.go b/models/lfs.go index 87f7a2871f..40539d2b78 100644 --- a/models/lfs.go +++ b/models/lfs.go @@ -44,27 +44,27 @@ var ErrLFSObjectNotExist = errors.New("LFS Meta object does not exist") func NewLFSMetaObject(m *LFSMetaObject) (*LFSMetaObject, error) { var err error - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() - has, err := sess.Get(m) + has, err := db.GetByBean(ctx, m) if err != nil { return nil, err } if has { m.Existing = true - return m, sess.Commit() + return m, committer.Commit() } - if _, err = sess.Insert(m); err != nil { + if err = db.Insert(ctx, m); err != nil { return nil, err } - return m, sess.Commit() + return m, committer.Commit() } // GetLFSMetaObjectByOid selects a LFSMetaObject entry from database by its OID. @@ -92,29 +92,28 @@ func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) (int64, error) { return 0, ErrLFSObjectNotExist } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { - return -1, err + ctx, committer, err := db.TxContext() + if err != nil { + return 0, err } + defer committer.Close() m := &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}, RepositoryID: repo.ID} - if _, err := sess.Delete(m); err != nil { + if _, err := db.DeleteByBean(ctx, m); err != nil { return -1, err } - count, err := sess.Count(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) + count, err := db.CountByBean(ctx, &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) if err != nil { return count, err } - return count, sess.Commit() + return count, committer.Commit() } // GetLFSMetaObjects returns all LFSMetaObjects associated with a repository func (repo *Repository) GetLFSMetaObjects(page, pageSize int) ([]*LFSMetaObject, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + sess := db.GetEngine(db.DefaultContext) if page >= 0 && pageSize > 0 { start := 0 @@ -145,11 +144,13 @@ func LFSObjectAccessible(user *User, oid string) (bool, error) { // LFSAutoAssociate auto associates accessible LFSMetaObjects func LFSAutoAssociate(metas []*LFSMetaObject, user *User, repoID int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) oids := make([]interface{}, len(metas)) oidMap := make(map[string]*LFSMetaObject, len(metas)) @@ -171,20 +172,21 @@ func LFSAutoAssociate(metas []*LFSMetaObject, user *User, repoID int64) error { newMetas[i].Size = oidMap[newMetas[i].Oid].Size newMetas[i].RepositoryID = repoID } - if _, err := sess.InsertMulti(newMetas); err != nil { + if err := db.Insert(ctx, newMetas); err != nil { return err } - return sess.Commit() + return committer.Commit() } // IterateLFS iterates lfs object func IterateLFS(f func(mo *LFSMetaObject) error) error { var start int const batchSize = 100 + var e = db.GetEngine(db.DefaultContext) for { mos := make([]*LFSMetaObject, 0, batchSize) - if err := db.GetEngine(db.DefaultContext).Limit(batchSize, start).Find(&mos); err != nil { + if err := e.Limit(batchSize, start).Find(&mos); err != nil { return err } if len(mos) == 0 { diff --git a/models/lfs_lock.go b/models/lfs_lock.go index 247444a66d..943699290f 100644 --- a/models/lfs_lock.go +++ b/models/lfs_lock.go @@ -105,18 +105,16 @@ func GetLFSLockByID(id int64) (*LFSLock, error) { // GetLFSLockByRepoID returns a list of locks of repository. func GetLFSLockByRepoID(repoID int64, page, pageSize int) ([]*LFSLock, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - + e := db.GetEngine(db.DefaultContext) if page >= 0 && pageSize > 0 { start := 0 if page > 0 { start = (page - 1) * pageSize } - sess.Limit(pageSize, start) + e.Limit(pageSize, start) } lfsLocks := make([]*LFSLock, 0, pageSize) - return lfsLocks, sess.Find(&lfsLocks, &LFSLock{RepoID: repoID}) + return lfsLocks, e.Find(&lfsLocks, &LFSLock{RepoID: repoID}) } // CountLFSLockByRepoID returns a count of all LFSLocks associated with a repository. diff --git a/models/login/oauth2_application.go b/models/login/oauth2_application.go index 060bfe5bc3..4cd73cf3a2 100644 --- a/models/login/oauth2_application.go +++ b/models/login/oauth2_application.go @@ -190,11 +190,12 @@ type UpdateOAuth2ApplicationOptions struct { // UpdateOAuth2Application updates an oauth2 application func UpdateOAuth2Application(opts UpdateOAuth2ApplicationOptions) (*OAuth2Application, error) { - sess := db.NewSession(db.DefaultContext) - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } - defer sess.Close() + defer committer.Close() + sess := db.GetEngine(ctx) app, err := getOAuth2ApplicationByID(sess, opts.ID) if err != nil { @@ -212,7 +213,7 @@ func UpdateOAuth2Application(opts UpdateOAuth2ApplicationOptions) (*OAuth2Applic } app.ClientSecret = "" - return app, sess.Commit() + return app, committer.Commit() } func updateOAuth2Application(e db.Engine, app *OAuth2Application) error { @@ -222,7 +223,7 @@ func updateOAuth2Application(e db.Engine, app *OAuth2Application) error { return nil } -func deleteOAuth2Application(sess *xorm.Session, id, userid int64) error { +func deleteOAuth2Application(sess db.Engine, id, userid int64) error { if deleted, err := sess.Delete(&OAuth2Application{ID: id, UID: userid}); err != nil { return err } else if deleted == 0 { @@ -251,15 +252,15 @@ func deleteOAuth2Application(sess *xorm.Session, id, userid int64) error { // DeleteOAuth2Application deletes the application with the given id and the grants and auth codes related to it. It checks if the userid was the creator of the app. func DeleteOAuth2Application(id, userid int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } - if err := deleteOAuth2Application(sess, id, userid); err != nil { + defer committer.Close() + if err := deleteOAuth2Application(db.GetEngine(ctx), id, userid); err != nil { return err } - return sess.Commit() + return committer.Commit() } // ListOAuth2Applications returns a list of oauth2 applications belongs to given user. diff --git a/models/login/session.go b/models/login/session.go index da3745016a..805606600a 100644 --- a/models/login/session.go +++ b/models/login/session.go @@ -36,23 +36,23 @@ func ReadSession(key string) (*Session, error) { session := Session{ Key: key, } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() - if has, err := sess.Get(&session); err != nil { + if has, err := db.GetByBean(ctx, &session); err != nil { return nil, err } else if !has { session.Expiry = timeutil.TimeStampNow() - _, err := sess.Insert(&session) - if err != nil { + if err := db.Insert(ctx, &session); err != nil { return nil, err } } - return &session, sess.Commit() + return &session, committer.Commit() } // ExistSession checks if a session exists @@ -73,13 +73,13 @@ func DestroySession(key string) error { // RegenerateSession regenerates a session from the old id func RegenerateSession(oldKey, newKey string) (*Session, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() - if has, err := sess.Get(&Session{ + if has, err := db.GetByBean(ctx, &Session{ Key: newKey, }); err != nil { return nil, err @@ -87,32 +87,31 @@ func RegenerateSession(oldKey, newKey string) (*Session, error) { return nil, fmt.Errorf("session Key: %s already exists", newKey) } - if has, err := sess.Get(&Session{ + if has, err := db.GetByBean(ctx, &Session{ Key: oldKey, }); err != nil { return nil, err } else if !has { - _, err := sess.Insert(&Session{ + if err := db.Insert(ctx, &Session{ Key: oldKey, Expiry: timeutil.TimeStampNow(), - }) - if err != nil { + }); err != nil { return nil, err } } - if _, err := sess.Exec("UPDATE "+sess.Engine().TableName(&Session{})+" SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil { + if _, err := db.Exec(ctx, "UPDATE "+db.TableName(&Session{})+" SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil { return nil, err } s := Session{ Key: newKey, } - if _, err := sess.Get(&s); err != nil { + if _, err := db.GetByBean(ctx, &s); err != nil { return nil, err } - return &s, sess.Commit() + return &s, committer.Commit() } // CountSessions returns the number of sessions diff --git a/models/migrate.go b/models/migrate.go index 18b1b11e46..efe4bd0c5e 100644 --- a/models/migrate.go +++ b/models/migrate.go @@ -9,7 +9,6 @@ import ( "code.gitea.io/gitea/modules/structs" "xorm.io/builder" - "xorm.io/xorm" ) // InsertMilestones creates milestones of repository. @@ -18,11 +17,12 @@ func InsertMilestones(ms ...*Milestone) (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) // to return the id, so we should not use batch insert for _, m := range ms { @@ -31,29 +31,29 @@ func InsertMilestones(ms ...*Milestone) (err error) { } } - if _, err = sess.Exec("UPDATE `repository` SET num_milestones = num_milestones + ? WHERE id = ?", len(ms), ms[0].RepoID); err != nil { + if _, err = db.Exec(ctx, "UPDATE `repository` SET num_milestones = num_milestones + ? WHERE id = ?", len(ms), ms[0].RepoID); err != nil { return err } - return sess.Commit() + return committer.Commit() } // InsertIssues insert issues to database func InsertIssues(issues ...*Issue) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() for _, issue := range issues { - if err := insertIssue(sess, issue); err != nil { + if err := insertIssue(db.GetEngine(ctx), issue); err != nil { return err } } - return sess.Commit() + return committer.Commit() } -func insertIssue(sess *xorm.Session, issue *Issue) error { +func insertIssue(sess db.Engine, issue *Issue) error { if _, err := sess.NoAutoTime().Insert(issue); err != nil { return err } @@ -144,13 +144,13 @@ func InsertIssueComments(comments []*Comment) error { issueIDs[comment.IssueID] = true } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() for _, comment := range comments { - if _, err := sess.NoAutoTime().Insert(comment); err != nil { + if _, err := db.GetEngine(ctx).NoAutoTime().Insert(comment); err != nil { return err } @@ -159,27 +159,28 @@ func InsertIssueComments(comments []*Comment) error { reaction.CommentID = comment.ID } if len(comment.Reactions) > 0 { - if _, err := sess.Insert(comment.Reactions); err != nil { + if err := db.Insert(ctx, comment.Reactions); err != nil { return err } } } for issueID := range issueIDs { - if _, err := sess.Exec("UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ?) WHERE id = ?", issueID, issueID); err != nil { + if _, err := db.Exec(ctx, "UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ?) WHERE id = ?", issueID, issueID); err != nil { return err } } - return sess.Commit() + return committer.Commit() } // InsertPullRequests inserted pull requests func InsertPullRequests(prs ...*PullRequest) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) for _, pr := range prs { if err := insertIssue(sess, pr.Issue); err != nil { return err @@ -190,16 +191,17 @@ func InsertPullRequests(prs ...*PullRequest) error { } } - return sess.Commit() + return committer.Commit() } // InsertReleases migrates release func InsertReleases(rels ...*Release) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) for _, rel := range rels { if _, err := sess.NoAutoTime().Insert(rel); err != nil { @@ -217,7 +219,7 @@ func InsertReleases(rels ...*Release) error { } } - return sess.Commit() + return committer.Commit() } func migratedIssueCond(tp structs.GitServiceType) builder.Cond { diff --git a/models/notification.go b/models/notification.go index 3c252d123d..db78558647 100644 --- a/models/notification.go +++ b/models/notification.go @@ -140,15 +140,16 @@ func CountNotifications(opts *FindNotificationOptions) (int64, error) { // CreateRepoTransferNotification creates notification for the user a repository was transferred to func CreateRepoTransferNotification(doer, newOwner *User, repo *Repository) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + var notify []*Notification if newOwner.IsOrganization() { - users, err := getUsersWhoCanCreateOrgRepo(sess, newOwner.ID) + users, err := getUsersWhoCanCreateOrgRepo(db.GetEngine(ctx), newOwner.ID) if err != nil || len(users) == 0 { return err } @@ -171,28 +172,28 @@ func CreateRepoTransferNotification(doer, newOwner *User, repo *Repository) erro }} } - if _, err := sess.InsertMulti(notify); err != nil { + if err := db.Insert(ctx, notify); err != nil { return err } - return sess.Commit() + return committer.Commit() } // CreateOrUpdateIssueNotifications creates an issue notification // for each watcher, or updates it if already exists // receiverID > 0 just send to reciver, else send to all watcher func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := createOrUpdateIssueNotifications(db.GetEngine(ctx), issueID, commentID, notificationAuthorID, receiverID); err != nil { return err } - if err := createOrUpdateIssueNotifications(sess, issueID, commentID, notificationAuthorID, receiverID); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func createOrUpdateIssueNotifications(e db.Engine, issueID, commentID, notificationAuthorID, receiverID int64) error { diff --git a/models/org.go b/models/org.go index c79af5c7bb..8e60422ef1 100644 --- a/models/org.go +++ b/models/org.go @@ -18,7 +18,6 @@ import ( "code.gitea.io/gitea/modules/structs" "xorm.io/builder" - "xorm.io/xorm" ) // Organization represents an organization @@ -441,13 +440,13 @@ func getUsersWhoCanCreateOrgRepo(e db.Engine, orgID int64) ([]*User, error) { And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users) } -func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*Organization, error) { +func getOrgsByUserID(e db.Engine, userID int64, showAll bool) ([]*Organization, error) { orgs := make([]*Organization, 0, 10) + sess := e.Where("`org_user`.uid=?", userID) if !showAll { - sess.And("`org_user`.is_public=?", true) + sess = sess.And("`org_user`.is_public=?", true) } return orgs, sess. - And("`org_user`.uid=?", userID). Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id"). Asc("`user`.name"). Find(&orgs) @@ -456,9 +455,7 @@ func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*Organiz // GetOrgsByUserID returns a list of organizations that the given user ID // has joined. func GetOrgsByUserID(userID int64, showAll bool) ([]*Organization, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - return getOrgsByUserID(sess, userID, showAll) + return getOrgsByUserID(db.GetEngine(db.DefaultContext), userID, showAll) } // MinimalOrg represents a simple orgnization with only needed columns @@ -466,9 +463,6 @@ type MinimalOrg = Organization // GetUserOrgsList returns one user's all orgs list func GetUserOrgsList(user *User) ([]*MinimalOrg, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - schema, err := db.TableInfo(new(User)) if err != nil { return nil, err @@ -491,7 +485,8 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) { groupByStr := groupByCols.String() groupByStr = groupByStr[0 : len(groupByStr)-1] - sess.Select(groupByStr+", count(distinct repo_id) as org_count"). + sess := db.GetEngine(db.DefaultContext) + sess = sess.Select(groupByStr+", count(distinct repo_id) as org_count"). Table("user"). Join("INNER", "team", "`team`.org_id = `user`.id"). Join("INNER", "team_user", "`team`.id = `team_user`.team_id"). @@ -524,7 +519,7 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) { return orgs, nil } -func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) { +func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*User, error) { orgs := make([]*User, 0, 10) return orgs, sess. Join("INNER", "`team_user`", "`team_user`.org_id=`user`.id"). @@ -572,9 +567,7 @@ func HasOrgsVisible(orgs []*Organization, user *User) bool { // GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID. func GetOwnedOrgsByUserID(userID int64) ([]*User, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - return getOwnedOrgsByUserID(sess, userID) + return getOwnedOrgsByUserID(db.GetEngine(db.DefaultContext), userID) } // GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by @@ -664,11 +657,11 @@ func AddOrgUser(orgID, uid int64) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() ou := &OrgUser{ UID: uid, @@ -676,19 +669,13 @@ func AddOrgUser(orgID, uid int64) error { IsPublic: setting.Service.DefaultOrgMemberVisible, } - if _, err := sess.Insert(ou); err != nil { - if err := sess.Rollback(); err != nil { - log.Error("AddOrgUser: sess.Rollback: %v", err) - } + if err := db.Insert(ctx, ou); err != nil { return err - } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil { - if err := sess.Rollback(); err != nil { - log.Error("AddOrgUser: sess.Rollback: %v", err) - } + } else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil { return err } - return sess.Commit() + return committer.Commit() } // GetOrgByIDCtx returns the user object by given ID if exists. diff --git a/models/org_team.go b/models/org_team.go index e3ad23c111..1bdffe2cb1 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -83,8 +83,7 @@ func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) { cond = cond.And(builder.Eq{"org_id": opts.OrgID}) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + sess := db.GetEngine(db.DefaultContext) count, err := sess. Where(cond). @@ -265,17 +264,17 @@ func (t *Team) addAllRepositories(e db.Engine) error { // AddAllRepositories adds all repositories to the team func (t *Team) AddAllRepositories() (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = t.addAllRepositories(db.GetEngine(ctx)); err != nil { return err } - if err = t.addAllRepositories(sess); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // AddRepository adds new repository to team of organization. @@ -286,17 +285,17 @@ func (t *Team) AddRepository(repo *Repository) (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = t.addRepository(db.GetEngine(ctx), repo); err != nil { return err } - if err = t.addRepository(sess, repo); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // RemoveAllRepositories removes all repositories from team and recalculates access @@ -305,17 +304,17 @@ func (t *Team) RemoveAllRepositories() (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = t.removeAllRepositories(db.GetEngine(ctx)); err != nil { return err } - if err = t.removeAllRepositories(sess); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // removeAllRepositories removes all repositories from team and recalculates access @@ -422,17 +421,17 @@ func (t *Team) RemoveRepository(repoID int64) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = t.removeRepository(db.GetEngine(ctx), repo, true); err != nil { return err } - if err = t.removeRepository(sess, repo, true); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // UnitEnabled returns if the team has the given unit type enabled @@ -494,17 +493,13 @@ func NewTeam(t *Team) (err error) { return ErrTeamAlreadyExist{t.OrgID, t.LowerName} } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if _, err = sess.Insert(t); err != nil { - errRollback := sess.Rollback() - if errRollback != nil { - log.Error("NewTeam sess.Rollback: %v", errRollback) - } + if err = db.Insert(ctx, t); err != nil { return err } @@ -513,32 +508,24 @@ func NewTeam(t *Team) (err error) { for _, unit := range t.Units { unit.TeamID = t.ID } - if _, err = sess.Insert(&t.Units); err != nil { - errRollback := sess.Rollback() - if errRollback != nil { - log.Error("NewTeam sess.Rollback: %v", errRollback) - } + if err = db.Insert(ctx, &t.Units); err != nil { return err } } // Add all repositories to the team if it has access to all of them. if t.IncludesAllRepositories { - err = t.addAllRepositories(sess) + err = t.addAllRepositories(db.GetEngine(ctx)) if err != nil { return fmt.Errorf("addAllRepositories: %v", err) } } // Update organization number of teams. - if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { - errRollback := sess.Rollback() - if errRollback != nil { - log.Error("NewTeam sess.Rollback: %v", errRollback) - } + if _, err = db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { return err } - return sess.Commit() + return committer.Commit() } func getTeam(e db.Engine, orgID int64, name string) (*Team, error) { @@ -624,11 +611,12 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) { t.Description = t.Description[:255] } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) t.LowerName = strings.ToLower(t.Name) has, err := sess. @@ -659,10 +647,6 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) { return err } if _, err = sess.Cols("org_id", "team_id", "type").Insert(&t.Units); err != nil { - errRollback := sess.Rollback() - if errRollback != nil { - log.Error("UpdateTeam sess.Rollback: %v", errRollback) - } return err } } @@ -688,7 +672,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) { } } - return sess.Commit() + return committer.Commit() } // DeleteTeam deletes given team. @@ -698,11 +682,12 @@ func DeleteTeam(t *Team) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) if err := t.getMembers(sess); err != nil { return err @@ -736,7 +721,7 @@ func DeleteTeam(t *Team) error { return err } - return sess.Commit() + return committer.Commit() } // ___________ ____ ___ @@ -839,13 +824,15 @@ func AddTeamMember(team *Team, userID int64) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if _, err := sess.Insert(&TeamUser{ + sess := db.GetEngine(ctx) + + if err := db.Insert(ctx, &TeamUser{ UID: userID, OrgID: team.OrgID, TeamID: team.ID, @@ -869,7 +856,7 @@ func AddTeamMember(team *Team, userID int64) error { } } - return sess.Commit() + return committer.Commit() } func removeTeamMember(ctx context.Context, team *Team, userID int64) error { @@ -1048,25 +1035,21 @@ func getUnitsByTeamID(e db.Engine, teamID int64) (units []*TeamUnit, err error) // UpdateTeamUnits updates a teams's units func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if _, err = sess.Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil { + if _, err = db.GetEngine(ctx).Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil { return err } if len(units) > 0 { - if _, err = sess.Insert(units); err != nil { - errRollback := sess.Rollback() - if errRollback != nil { - log.Error("UpdateTeamUnits sess.Rollback: %v", errRollback) - } + if err = db.Insert(ctx, units); err != nil { return err } } - return sess.Commit() + return committer.Commit() } diff --git a/models/project.go b/models/project.go index 8aaff50e15..e6a650674b 100644 --- a/models/project.go +++ b/models/project.go @@ -143,26 +143,25 @@ func NewProject(p *Project) error { return errors.New("project type is not valid") } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() - if err := sess.Begin(); err != nil { + if err := db.Insert(ctx, p); err != nil { return err } - if _, err := sess.Insert(p); err != nil { + if _, err := db.Exec(ctx, "UPDATE `repository` SET num_projects = num_projects + 1 WHERE id = ?", p.RepoID); err != nil { return err } - if _, err := sess.Exec("UPDATE `repository` SET num_projects = num_projects + 1 WHERE id = ?", p.RepoID); err != nil { + if err := createBoardsForProjectsType(db.GetEngine(ctx), p); err != nil { return err } - if err := createBoardsForProjectsType(sess, p); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // GetProjectByID returns the projects in a repository @@ -220,11 +219,12 @@ func updateRepositoryProjectCount(e db.Engine, repoID int64) error { // ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) p := new(Project) @@ -239,22 +239,22 @@ func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) er return err } - return sess.Commit() + return committer.Commit() } // ChangeProjectStatus toggle a project between opened and closed func ChangeProjectStatus(p *Project, isClosed bool) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := changeProjectStatus(db.GetEngine(ctx), p, isClosed); err != nil { return err } - if err := changeProjectStatus(sess, p, isClosed); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func changeProjectStatus(e db.Engine, p *Project, isClosed bool) error { @@ -273,17 +273,17 @@ func changeProjectStatus(e db.Engine, p *Project, isClosed bool) error { // DeleteProjectByID deletes a project from a repository. func DeleteProjectByID(id int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := deleteProjectByID(db.GetEngine(ctx), id); err != nil { return err } - if err := deleteProjectByID(sess, id); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func deleteProjectByID(e db.Engine, id int64) error { diff --git a/models/project_board.go b/models/project_board.go index e6c9f03386..2d422a203b 100644 --- a/models/project_board.go +++ b/models/project_board.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" - "xorm.io/xorm" ) type ( @@ -69,7 +68,7 @@ func IsProjectBoardTypeValid(p ProjectBoardType) bool { } } -func createBoardsForProjectsType(sess *xorm.Session, project *Project) error { +func createBoardsForProjectsType(sess db.Engine, project *Project) error { var items []string switch project.BoardType { @@ -117,17 +116,17 @@ func NewProjectBoard(board *ProjectBoard) error { // DeleteProjectBoardByID removes all issues references to the project board. func DeleteProjectBoardByID(boardID int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := deleteProjectBoardByID(db.GetEngine(ctx), boardID); err != nil { return err } - if err := deleteProjectBoardByID(sess, boardID); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func deleteProjectBoardByID(e db.Engine, boardID int64) error { diff --git a/models/project_issue.go b/models/project_issue.go index 75e74295b5..6f314ca931 100644 --- a/models/project_issue.go +++ b/models/project_issue.go @@ -185,11 +185,12 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *User, newPro // MoveIssueAcrossProjectBoards move a card from one board to another func MoveIssueAcrossProjectBoards(issue *Issue, board *ProjectBoard) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) var pis ProjectIssue has, err := sess.Where("issue_id=?", issue.ID).Get(&pis) @@ -206,7 +207,7 @@ func MoveIssueAcrossProjectBoards(issue *Issue, board *ProjectBoard) error { return err } - return sess.Commit() + return committer.Commit() } func (pb *ProjectBoard) removeIssues(e db.Engine) error { diff --git a/models/pull.go b/models/pull.go index 3bfebee118..1e1dd13c57 100644 --- a/models/pull.go +++ b/models/pull.go @@ -285,11 +285,12 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) // Note: This doesn't page as we only expect a very limited number of reviews reviews, err := findReviews(sess, FindReviewOptions{ @@ -326,7 +327,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error { } reviewersWritten++ } - return sess.Commit() + return committer.Commit() } // GetDefaultSquashMessage returns default message used when squash and merging pull request diff --git a/models/repo.go b/models/repo.go index 5921441afa..1347de3045 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1276,17 +1276,17 @@ func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err } } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { - return fmt.Errorf("sess.Begin: %v", err) + ctx, committer, err := db.TxContext() + if err != nil { + return err } + defer committer.Close() - if err := newRepoRedirect(sess, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil { + if err := newRepoRedirect(db.GetEngine(ctx), repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil { return err } - return sess.Commit() + return committer.Commit() } func getRepositoriesByForkID(e db.Engine, forkID int64) ([]*Repository, error) { @@ -1367,17 +1367,17 @@ func UpdateRepositoryCtx(ctx context.Context, repo *Repository, visibilityChange // UpdateRepository updates a repository func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if err = updateRepository(sess, repo, visibilityChanged); err != nil { + if err = updateRepository(db.GetEngine(ctx), repo, visibilityChanged); err != nil { return fmt.Errorf("updateRepository: %v", err) } - return sess.Commit() + return committer.Commit() } // UpdateRepositoryOwnerNames updates repository owner_names (this should only be used when the ownerName has changed case) @@ -1385,19 +1385,19 @@ func UpdateRepositoryOwnerNames(ownerID int64, ownerName string) error { if ownerID == 0 { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if _, err := sess.Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{ + if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{ OwnerName: ownerName, }); err != nil { return err } - return sess.Commit() + return committer.Commit() } // UpdateRepositoryUpdatedTime updates a repository's updated time @@ -1408,38 +1408,39 @@ func UpdateRepositoryUpdatedTime(repoID int64, updateTime time.Time) error { // UpdateRepositoryUnits updates a repository's units func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() // Delete existing settings of units before adding again for _, u := range units { deleteUnitTypes = append(deleteUnitTypes, u.Type) } - if _, err = sess.Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil { + if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil { return err } if len(units) > 0 { - if _, err = sess.Insert(units); err != nil { + if err = db.Insert(ctx, units); err != nil { return err } } - return sess.Commit() + return committer.Commit() } // DeleteRepository deletes a repository for a user or organization. // make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock) func DeleteRepository(doer *User, uid, repoID int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) // In case is a organization. org, err := getUserByID(sess, uid) @@ -1639,11 +1640,11 @@ func DeleteRepository(doer *User, uid, repoID int64) error { return err } - if err = sess.Commit(); err != nil { + if err = committer.Commit(); err != nil { return err } - sess.Close() + committer.Close() // We should always delete the files after the database transaction succeed. If // we delete the file but the database rollback, the repository will be broken. @@ -1769,15 +1770,14 @@ func GetUserRepositories(opts *SearchRepoOptions) ([]*Repository, int64, error) cond = cond.And(builder.In("lower_name", opts.LowerNames)) } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + sess := db.GetEngine(db.DefaultContext) count, err := sess.Where(cond).Count(new(Repository)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } - sess.Where(cond).OrderBy(opts.OrderBy.String()) + sess = sess.Where(cond).OrderBy(opts.OrderBy.String()) repos := make([]*Repository, 0, opts.PageSize) return repos, count, db.SetSessionPagination(sess, opts).Find(&repos) } @@ -2136,32 +2136,36 @@ func (repo *Repository) GetTrustModel() TrustModelType { return trustModel } +func updateUserStarNumbers(users []User) error { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + for _, user := range users { + if _, err = db.Exec(ctx, "UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil { + return err + } + } + + return committer.Commit() +} + // DoctorUserStarNum recalculate Stars number for all user func DoctorUserStarNum() (err error) { const batchSize = 100 - sess := db.NewSession(db.DefaultContext) - defer sess.Close() for start := 0; ; start += batchSize { users := make([]User, 0, batchSize) - if err = sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil { + if err = db.GetEngine(db.DefaultContext).Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil { return } if len(users) == 0 { break } - if err = sess.Begin(); err != nil { - return - } - - for _, user := range users { - if _, err = sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil { - return - } - } - - if err = sess.Commit(); err != nil { + if err = updateUserStarNumbers(users); err != nil { return } } diff --git a/models/repo_avatar.go b/models/repo_avatar.go index 6c83e11a53..1d9705fe99 100644 --- a/models/repo_avatar.go +++ b/models/repo_avatar.go @@ -129,18 +129,18 @@ func (repo *Repository) UploadAvatar(data []byte) error { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() oldAvatarPath := repo.CustomAvatarRelativePath() // Users can upload the same image to other repo - prefix it with ID // Then repo will be removed - only it avatar file will be removed repo.Avatar = newAvatar - if _, err := sess.ID(repo.ID).Cols("avatar").Update(repo); err != nil { + if _, err := db.GetEngine(ctx).ID(repo.ID).Cols("avatar").Update(repo); err != nil { return fmt.Errorf("UploadAvatar: Update repository avatar: %v", err) } @@ -159,7 +159,7 @@ func (repo *Repository) UploadAvatar(data []byte) error { } } - return sess.Commit() + return committer.Commit() } // DeleteAvatar deletes the repos's custom avatar. @@ -172,14 +172,14 @@ func (repo *Repository) DeleteAvatar() error { avatarPath := repo.CustomAvatarRelativePath() log.Trace("DeleteAvatar[%d]: %s", repo.ID, avatarPath) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() repo.Avatar = "" - if _, err := sess.ID(repo.ID).Cols("avatar").Update(repo); err != nil { + if _, err := db.GetEngine(ctx).ID(repo.ID).Cols("avatar").Update(repo); err != nil { return fmt.Errorf("DeleteAvatar: Update repository avatar: %v", err) } @@ -187,5 +187,5 @@ func (repo *Repository) DeleteAvatar() error { return fmt.Errorf("DeleteAvatar: Failed to remove %s: %v", avatarPath, err) } - return sess.Commit() + return committer.Commit() } diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index dd362406cf..6502d7959c 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -53,17 +53,17 @@ func (repo *Repository) addCollaborator(e db.Engine, u *User) error { // AddCollaborator adds new collaboration to a repository with default access mode. func (repo *Repository) AddCollaborator(u *User) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := repo.addCollaborator(db.GetEngine(ctx), u); err != nil { return err } - if err := repo.addCollaborator(sess, u); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } func (repo *Repository) getCollaborations(e db.Engine, listOptions db.ListOptions) ([]*Collaboration, error) { @@ -176,17 +176,17 @@ func (repo *Repository) changeCollaborationAccessMode(e db.Engine, uid int64, mo // ChangeCollaborationAccessMode sets new access mode for the collaboration. func (repo *Repository) ChangeCollaborationAccessMode(uid int64, mode AccessMode) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := repo.changeCollaborationAccessMode(db.GetEngine(ctx), uid, mode); err != nil { return err } - if err := repo.changeCollaborationAccessMode(sess, uid, mode); err != nil { - return err - } - - return sess.Commit() + return committer.Commit() } // DeleteCollaboration removes collaboration relation between the user and repository. @@ -196,11 +196,13 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) { UserID: uid, } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + + sess := db.GetEngine(ctx) if has, err := sess.Delete(collaboration); err != nil || has == 0 { return err @@ -221,7 +223,7 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) { return err } - return sess.Commit() + return committer.Commit() } func (repo *Repository) reconsiderIssueAssignees(e db.Engine, uid int64) error { diff --git a/models/repo_language_stats.go b/models/repo_language_stats.go index 2f126aa3d2..79de42ce0c 100644 --- a/models/repo_language_stats.go +++ b/models/repo_language_stats.go @@ -112,11 +112,12 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error) // UpdateLanguageStats updates the language statistics for repository func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]int64) error { - sess := db.NewSession(db.DefaultContext) - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } - defer sess.Close() + defer committer.Close() + sess := db.GetEngine(ctx) oldstats, err := repo.getLanguageStats(sess) if err != nil { @@ -178,16 +179,18 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]in return err } - return sess.Commit() + return committer.Commit() } // CopyLanguageStat Copy originalRepo language stat information to destRepo (use for forked repo) func CopyLanguageStat(originalRepo, destRepo *Repository) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) + RepoLang := make(LanguageStatList, 0, 6) if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil { return err @@ -207,5 +210,5 @@ func CopyLanguageStat(originalRepo, destRepo *Repository) error { return err } } - return sess.Commit() + return committer.Commit() } diff --git a/models/repo_list.go b/models/repo_list.go index 6804a997c8..511b446711 100644 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/modules/util" "xorm.io/builder" - "xorm.io/xorm" ) // RepositoryListDefaultPageSize is the default number of repositories @@ -373,7 +372,6 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa if err != nil { return nil, 0, err } - defer sess.Close() defaultSize := 50 if opts.PageSize > 0 { @@ -397,7 +395,7 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa return repos, count, nil } -func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (*xorm.Session, int64, error) { +func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) { if opts.Page <= 0 { opts.Page = 1 } @@ -410,7 +408,7 @@ func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (*x opts.OrderBy = SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = %d THEN 0 ELSE owner_id END, %s", opts.PriorityOwnerID, opts.OrderBy)) } - sess := db.NewSession(db.DefaultContext) + sess := db.GetEngine(db.DefaultContext) var count int64 if opts.PageSize > 0 { @@ -419,14 +417,13 @@ func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (*x Where(cond). Count(new(Repository)) if err != nil { - _ = sess.Close() return nil, 0, fmt.Errorf("Count: %v", err) } } - sess.Where(cond).OrderBy(opts.OrderBy.String()) + sess = sess.Where(cond).OrderBy(opts.OrderBy.String()) if opts.PageSize > 0 { - sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) + sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) } return sess, count, nil } @@ -495,7 +492,6 @@ func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) { if err != nil { return nil, 0, err } - defer sess.Close() defaultSize := 50 if opts.PageSize > 0 { diff --git a/models/repo_permission.go b/models/repo_permission.go index 3db7200470..a6304cf1aa 100644 --- a/models/repo_permission.go +++ b/models/repo_permission.go @@ -279,8 +279,7 @@ func IsUserRealRepoAdmin(repo *Repository, user *User) (bool, error) { return true, nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() + sess := db.GetEngine(db.DefaultContext) if err := repo.getOwner(sess); err != nil { return false, err diff --git a/models/repo_transfer.go b/models/repo_transfer.go index 7b766ff4c7..3b5ac21b09 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -118,11 +118,12 @@ func deleteRepositoryTransfer(e db.Engine, repoID int64) error { // CancelRepositoryTransfer marks the repository as ready and remove pending transfer entry, // thus cancel the transfer process. func CancelRepositoryTransfer(repo *Repository) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) repo.Status = RepositoryReady if err := updateRepositoryCols(sess, repo, "status"); err != nil { @@ -133,7 +134,7 @@ func CancelRepositoryTransfer(repo *Repository) error { return err } - return sess.Commit() + return committer.Commit() } // TestRepositoryReadyForTransfer make sure repo is ready to transfer @@ -150,11 +151,12 @@ func TestRepositoryReadyForTransfer(status RepositoryStatus) error { // CreatePendingRepositoryTransfer transfer a repo from one owner to a new one. // it marks the repository transfer as "pending" func CreatePendingRepositoryTransfer(doer, newOwner *User, repoID int64, teams []*Team) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) repo, err := getRepositoryByID(sess, repoID) if err != nil { @@ -191,11 +193,11 @@ func CreatePendingRepositoryTransfer(doer, newOwner *User, repoID int64, teams [ transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID) } - if _, err := sess.Insert(transfer); err != nil { + if err := db.Insert(ctx, transfer); err != nil { return err } - return sess.Commit() + return committer.Commit() } // TransferOwnership transfers all corresponding repository items from old user to new one. @@ -232,11 +234,13 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e } }() - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { - return fmt.Errorf("sess.Begin: %v", err) + ctx, committer, err := db.TxContext() + if err != nil { + return err } + defer committer.Close() + + sess := db.GetEngine(ctx) newOwner, err := getUserByName(sess, newOwnerName) if err != nil { @@ -408,5 +412,5 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e return fmt.Errorf("newRepoRedirect: %v", err) } - return sess.Commit() + return committer.Commit() } diff --git a/models/repo_watch.go b/models/repo_watch.go index 55fb08a426..fb1b1086aa 100644 --- a/models/repo_watch.go +++ b/models/repo_watch.go @@ -290,17 +290,17 @@ func NotifyWatchers(actions ...*Action) error { // NotifyWatchersActions creates batch of actions for every watcher. func NotifyWatchersActions(acts []*Action) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() for _, act := range acts { - if err := notifyWatchers(sess, act); err != nil { + if err := notifyWatchers(db.GetEngine(ctx), act); err != nil { return err } } - return sess.Commit() + return committer.Commit() } func watchIfAuto(e db.Engine, userID, repoID int64, isWrite bool) error { diff --git a/models/review.go b/models/review.go index 62172bac01..00906c7a27 100644 --- a/models/review.go +++ b/models/review.go @@ -472,11 +472,7 @@ func SubmitReview(doer *User, issue *Issue, reviewType ReviewType, content, comm func GetReviewersByIssueID(issueID int64) ([]*Review, error) { reviews := make([]*Review, 0, 10) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { - return nil, err - } + sess := db.GetEngine(db.DefaultContext) // Get latest review of each reviewer, sorted in order they were made if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC", @@ -590,12 +586,12 @@ func DismissReview(review *Review, isDismiss bool) (err error) { // InsertReviews inserts review and review comments func InsertReviews(reviews []*Review) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) for _, review := range reviews { if _, err := sess.NoAutoTime().Insert(review); err != nil { @@ -627,7 +623,7 @@ func InsertReviews(reviews []*Review) error { } } - return sess.Commit() + return committer.Commit() } // AddReviewRequest add a review request from one reviewer @@ -920,12 +916,12 @@ func CanMarkConversation(issue *Issue, doer *User) (permResult bool, err error) // DeleteReview delete a review and it's code comments func DeleteReview(r *Review) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) if r.ID == 0 { return fmt.Errorf("review is not allowed to be 0") @@ -959,7 +955,7 @@ func DeleteReview(r *Review) error { return err } - return sess.Commit() + return committer.Commit() } // GetCodeCommentsCount return count of CodeComments a Review has diff --git a/models/ssh_key.go b/models/ssh_key.go index baa0d2a54f..21d5b7d496 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -96,11 +96,12 @@ func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*Pu return nil, err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() + sess := db.GetEngine(ctx) if err := checkKeyFingerprint(sess, fingerprint); err != nil { return nil, err @@ -129,7 +130,7 @@ func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*Pu return nil, fmt.Errorf("addKey: %v", err) } - return key, sess.Commit() + return key, committer.Commit() } // GetPublicKeyByID returns public key by given ID. @@ -334,20 +335,20 @@ func DeletePublicKey(doer *User, id int64) (err error) { return ErrKeyAccessDenied{doer.ID, key.ID, "public"} } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = deletePublicKeys(db.GetEngine(ctx), id); err != nil { return err } - if err = deletePublicKeys(sess, id); err != nil { + if err = committer.Commit(); err != nil { return err } - - if err = sess.Commit(); err != nil { - return err - } - sess.Close() + committer.Close() if key.Type == KeyTypePrincipal { return RewriteAllPrincipalKeys() @@ -359,11 +360,12 @@ func DeletePublicKey(doer *User, id int64) (err error) { // deleteKeysMarkedForDeletion returns true if ssh keys needs update func deleteKeysMarkedForDeletion(keys []string) (bool, error) { // Start session - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return false, err } + defer committer.Close() + sess := db.GetEngine(ctx) // Delete keys marked for deletion var sshKeysNeedUpdate bool @@ -380,7 +382,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) { sshKeysNeedUpdate = true } - if err := sess.Commit(); err != nil { + if err := committer.Commit(); err != nil { return false, err } diff --git a/models/ssh_key_deploy.go b/models/ssh_key_deploy.go index 4e3910d556..c31379dcb4 100644 --- a/models/ssh_key_deploy.go +++ b/models/ssh_key_deploy.go @@ -12,7 +12,6 @@ import ( "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" - "xorm.io/xorm" ) // ________ .__ ____ __. @@ -90,7 +89,7 @@ func checkDeployKey(e db.Engine, keyID, repoID int64, name string) error { } // addDeployKey adds new key-repo relation. -func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string, mode AccessMode) (*DeployKey, error) { +func addDeployKey(e db.Engine, keyID, repoID int64, name, fingerprint string, mode AccessMode) (*DeployKey, error) { if err := checkDeployKey(e, keyID, repoID, name); err != nil { return nil, err } @@ -126,11 +125,13 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey accessMode = AccessModeWrite } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() + + sess := db.GetEngine(ctx) pkey := &PublicKey{ Fingerprint: fingerprint, @@ -160,7 +161,7 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey return nil, err } - return key, sess.Commit() + return key, committer.Commit() } // GetDeployKeyByID returns deploy key by given ID. @@ -212,15 +213,16 @@ func UpdateDeployKey(key *DeployKey) error { // DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed. func DeleteDeployKey(doer *User, id int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } - if err := deleteDeployKey(sess, doer, id); err != nil { + defer committer.Close() + + if err := deleteDeployKey(db.GetEngine(ctx), doer, id); err != nil { return err } - return sess.Commit() + return committer.Commit() } func deleteDeployKey(sess db.Engine, doer *User, id int64) error { diff --git a/models/ssh_key_principals.go b/models/ssh_key_principals.go index 50456b72db..55d8e40397 100644 --- a/models/ssh_key_principals.go +++ b/models/ssh_key_principals.go @@ -25,11 +25,12 @@ import ( // AddPrincipalKey adds new principal to database and authorized_principals file. func AddPrincipalKey(ownerID int64, content string, loginSourceID int64) (*PublicKey, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() + sess := db.GetEngine(ctx) // Principals cannot be duplicated. has, err := sess. @@ -53,11 +54,11 @@ func AddPrincipalKey(ownerID int64, content string, loginSourceID int64) (*Publi return nil, fmt.Errorf("addKey: %v", err) } - if err = sess.Commit(); err != nil { + if err = committer.Commit(); err != nil { return nil, err } - sess.Close() + committer.Close() return key, RewriteAllPrincipalKeys() } diff --git a/models/star.go b/models/star.go index ee7791513d..baf724d7e0 100644 --- a/models/star.go +++ b/models/star.go @@ -23,44 +23,44 @@ func init() { // StarRepo or unstar repository. func StarRepo(userID, repoID int64, star bool) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + staring := isStaring(db.GetEngine(ctx), userID, repoID) if star { - if isStaring(sess, userID, repoID) { + if staring { return nil } - if _, err := sess.Insert(&Star{UID: userID, RepoID: repoID}); err != nil { + if err := db.Insert(ctx, &Star{UID: userID, RepoID: repoID}); err != nil { return err } - if _, err := sess.Exec("UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoID); err != nil { + if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoID); err != nil { return err } - if _, err := sess.Exec("UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", userID); err != nil { + if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", userID); err != nil { return err } } else { - if !isStaring(sess, userID, repoID) { + if !staring { return nil } - if _, err := sess.Delete(&Star{UID: userID, RepoID: repoID}); err != nil { + if _, err := db.DeleteByBean(ctx, &Star{UID: userID, RepoID: repoID}); err != nil { return err } - if _, err := sess.Exec("UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoID); err != nil { + if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoID); err != nil { return err } - if _, err := sess.Exec("UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", userID); err != nil { + if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", userID); err != nil { return err } } - return sess.Commit() + return committer.Commit() } // IsStaring checks if user has starred given repository. diff --git a/models/task.go b/models/task.go index c8af1a4967..9bff00cd8c 100644 --- a/models/task.go +++ b/models/task.go @@ -253,14 +253,6 @@ func FinishMigrateTask(task *Task) error { } task.PayloadContent = string(confBytes) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { - return err - } - if _, err := sess.ID(task.ID).Cols("status", "end_time", "payload_content").Update(task); err != nil { - return err - } - - return sess.Commit() + _, err = db.GetEngine(db.DefaultContext).ID(task.ID).Cols("status", "end_time", "payload_content").Update(task) + return err } diff --git a/models/topic.go b/models/topic.go index 6eb8c67b8d..79c47e2331 100644 --- a/models/topic.go +++ b/models/topic.go @@ -225,11 +225,12 @@ func getRepoTopicByName(e db.Engine, repoID int64, topicName string) (*Topic, er // AddTopic adds a topic name to a repository (if it does not already have it) func AddTopic(repoID int64, topicName string) (*Topic, error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return nil, err } + defer committer.Close() + sess := db.GetEngine(ctx) topic, err := getRepoTopicByName(sess, repoID, topicName) if err != nil { @@ -258,7 +259,7 @@ func AddTopic(repoID int64, topicName string) (*Topic, error) { return nil, err } - return topic, sess.Commit() + return topic, committer.Commit() } // DeleteTopic removes a topic name from a repository (if it has it) @@ -286,12 +287,12 @@ func SaveTopics(repoID int64, topicNames ...string) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) var addedTopicNames []string for _, topicName := range topicNames { @@ -352,5 +353,5 @@ func SaveTopics(repoID int64, topicNames ...string) error { return err } - return sess.Commit() + return committer.Commit() } diff --git a/models/upload.go b/models/upload.go index 503220db57..4a64ff34e3 100644 --- a/models/upload.go +++ b/models/upload.go @@ -109,23 +109,23 @@ func DeleteUploads(uploads ...*Upload) (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() ids := make([]int64, len(uploads)) for i := 0; i < len(uploads); i++ { ids[i] = uploads[i].ID } - if _, err = sess. + if _, err = db.GetEngine(ctx). In("id", ids). Delete(new(Upload)); err != nil { return fmt.Errorf("delete uploads: %v", err) } - if err = sess.Commit(); err != nil { + if err = committer.Commit(); err != nil { return err } diff --git a/models/user.go b/models/user.go index db2345cb37..4231597d42 100644 --- a/models/user.go +++ b/models/user.go @@ -1105,11 +1105,13 @@ func updateUserCols(e db.Engine, u *User, cols ...string) error { // UpdateUserSetting updates user's settings. func UpdateUserSetting(u *User) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) + if !u.IsOrganization() { if err = checkDupEmail(sess, u); err != nil { return err @@ -1118,7 +1120,7 @@ func UpdateUserSetting(u *User) (err error) { if err = updateUser(sess, u); err != nil { return err } - return sess.Commit() + return committer.Commit() } // deleteBeans deletes all given beans, beans should contain delete conditions. @@ -1533,7 +1535,7 @@ type SearchUserOptions struct { IsProhibitLogin util.OptionalBool } -func (opts *SearchUserOptions) toSearchQueryBase() (sess *xorm.Session) { +func (opts *SearchUserOptions) toSearchQueryBase() *xorm.Session { var cond builder.Cond = builder.Eq{"type": opts.Type} if len(opts.Keyword) > 0 { lowerKeyword := strings.ToLower(opts.Keyword) @@ -1599,19 +1601,21 @@ func (opts *SearchUserOptions) toSearchQueryBase() (sess *xorm.Session) { cond = cond.And(builder.Eq{"prohibit_login": opts.IsProhibitLogin.IsTrue()}) } - sess = db.NewSession(db.DefaultContext) - if !opts.IsTwoFactorEnabled.IsNone() { - // 2fa filter uses LEFT JOIN to check whether a user has a 2fa record - // TODO: bad performance here, maybe there will be a column "is_2fa_enabled" in the future - if opts.IsTwoFactorEnabled.IsTrue() { - cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL")) - } else { - cond = cond.And(builder.Expr("two_factor.uid IS NULL")) - } - sess = sess.Join("LEFT OUTER", "two_factor", "two_factor.uid = `user`.id") + e := db.GetEngine(db.DefaultContext) + if opts.IsTwoFactorEnabled.IsNone() { + return e.Where(cond) } - sess = sess.Where(cond) - return sess + + // 2fa filter uses LEFT JOIN to check whether a user has a 2fa record + // TODO: bad performance here, maybe there will be a column "is_2fa_enabled" in the future + if opts.IsTwoFactorEnabled.IsTrue() { + cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL")) + } else { + cond = cond.And(builder.Expr("two_factor.uid IS NULL")) + } + + return e.Join("LEFT OUTER", "two_factor", "two_factor.uid = `user`.id"). + Where(cond) } // SearchUsers takes options i.e. keyword and part of user name to search, diff --git a/models/user/follow.go b/models/user/follow.go index 89675b5078..6b02486c43 100644 --- a/models/user/follow.go +++ b/models/user/follow.go @@ -33,24 +33,24 @@ func FollowUser(userID, followID int64) (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err = db.Insert(ctx, &Follow{UserID: userID, FollowID: followID}); err != nil { return err } - if _, err = sess.Insert(&Follow{UserID: userID, FollowID: followID}); err != nil { + if _, err = db.Exec(ctx, "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", followID); err != nil { return err } - if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", followID); err != nil { + if _, err = db.Exec(ctx, "UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", userID); err != nil { return err } - - if _, err = sess.Exec("UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", userID); err != nil { - return err - } - return sess.Commit() + return committer.Commit() } // UnfollowUser unmarks someone as another's follower. @@ -59,22 +59,22 @@ func UnfollowUser(userID, followID int64) (err error) { return nil } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if _, err = db.DeleteByBean(ctx, &Follow{UserID: userID, FollowID: followID}); err != nil { return err } - if _, err = sess.Delete(&Follow{UserID: userID, FollowID: followID}); err != nil { + if _, err = db.Exec(ctx, "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil { return err } - if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil { + if _, err = db.Exec(ctx, "UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil { return err } - - if _, err = sess.Exec("UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil { - return err - } - return sess.Commit() + return committer.Commit() } diff --git a/models/user_avatar.go b/models/user_avatar.go index f96f66f930..50998514e0 100644 --- a/models/user_avatar.go +++ b/models/user_avatar.go @@ -109,11 +109,11 @@ func (u *User) UploadAvatar(data []byte) error { return err } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() u.UseCustomAvatar = true // Different users can upload same image as avatar @@ -121,7 +121,7 @@ func (u *User) UploadAvatar(data []byte) error { // Otherwise, if any of the users delete his avatar // Other users will lose their avatars too. u.Avatar = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", u.ID, md5.Sum(data))))) - if err = updateUserCols(sess, u, "use_custom_avatar", "avatar"); err != nil { + if err = updateUserCols(db.GetEngine(ctx), u, "use_custom_avatar", "avatar"); err != nil { return fmt.Errorf("updateUser: %v", err) } @@ -134,7 +134,7 @@ func (u *User) UploadAvatar(data []byte) error { return fmt.Errorf("Failed to create dir %s: %v", u.CustomAvatarRelativePath(), err) } - return sess.Commit() + return committer.Commit() } // IsUploadAvatarChanged returns true if the current user's avatar would be changed with the provided data diff --git a/models/user_email.go b/models/user_email.go index bd0da65405..d9e63bfc54 100644 --- a/models/user_email.go +++ b/models/user_email.go @@ -17,15 +17,15 @@ import ( // ActivateEmail activates the email address to given user. func ActivateEmail(email *user_model.EmailAddress) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } - if err := updateActivation(sess, email, true); err != nil { + defer committer.Close() + if err := updateActivation(db.GetEngine(ctx), email, true); err != nil { return err } - return sess.Commit() + return committer.Commit() } func updateActivation(e db.Engine, email *user_model.EmailAddress, activate bool) error { @@ -64,11 +64,12 @@ func MakeEmailPrimary(email *user_model.EmailAddress) error { return ErrUserNotExist{email.UID, "", 0} } - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() + sess := db.GetEngine(ctx) // 1. Update user table user.Email = email.Email @@ -89,7 +90,7 @@ func MakeEmailPrimary(email *user_model.EmailAddress) error { return err } - return sess.Commit() + return committer.Commit() } // SearchEmailOrderBy is used to sort the results from SearchEmails() diff --git a/models/user_test.go b/models/user_test.go index 2da5519d74..7f29f5c849 100644 --- a/models/user_test.go +++ b/models/user_test.go @@ -269,9 +269,8 @@ func TestGetOrgRepositoryIDs(t *testing.T) { func TestNewGitSig(t *testing.T) { users := make([]*User, 0, 20) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - sess.Find(&users) + err := db.GetEngine(db.DefaultContext).Find(&users) + assert.NoError(t, err) for _, user := range users { sig := user.NewGitSig() @@ -284,9 +283,8 @@ func TestNewGitSig(t *testing.T) { func TestDisplayName(t *testing.T) { users := make([]*User, 0, 20) - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - sess.Find(&users) + err := db.GetEngine(db.DefaultContext).Find(&users) + assert.NoError(t, err) for _, user := range users { displayName := user.DisplayName() diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go index de8bd5e338..d01f548eed 100644 --- a/models/webhook/webhook.go +++ b/models/webhook/webhook.go @@ -507,21 +507,21 @@ func UpdateWebhookLastStatus(w *Webhook) error { // deleteWebhook uses argument bean as query condition, // ID must be specified and do not assign unnecessary fields. func deleteWebhook(bean *Webhook) (err error) { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err = sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - if count, err := sess.Delete(bean); err != nil { + if count, err := db.DeleteByBean(ctx, bean); err != nil { return err } else if count == 0 { return ErrWebhookNotExist{ID: bean.ID} - } else if _, err = sess.Delete(&HookTask{HookID: bean.ID}); err != nil { + } else if _, err = db.DeleteByBean(ctx, &HookTask{HookID: bean.ID}); err != nil { return err } - return sess.Commit() + return committer.Commit() } // DeleteWebhookByRepoID deletes webhook of repository by given ID. @@ -542,13 +542,13 @@ func DeleteWebhookByOrgID(orgID, id int64) error { // DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0) func DeleteDefaultSystemWebhook(id int64) error { - sess := db.NewSession(db.DefaultContext) - defer sess.Close() - if err := sess.Begin(); err != nil { + ctx, committer, err := db.TxContext() + if err != nil { return err } + defer committer.Close() - count, err := sess. + count, err := db.GetEngine(ctx). Where("repo_id=? AND org_id=?", 0, 0). Delete(&Webhook{ID: id}) if err != nil { @@ -557,11 +557,11 @@ func DeleteDefaultSystemWebhook(id int64) error { return ErrWebhookNotExist{ID: id} } - if _, err := sess.Delete(&HookTask{HookID: id}); err != nil { + if _, err := db.DeleteByBean(ctx, &HookTask{HookID: id}); err != nil { return err } - return sess.Commit() + return committer.Commit() } // CopyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo