diff --git a/cmd/admin.go b/cmd/admin.go
index e4210213c..7463b21d8 100644
--- a/cmd/admin.go
+++ b/cmd/admin.go
@@ -778,6 +778,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
 
 func getReleaseCount(id int64) (int64, error) {
 	return repo_model.GetReleaseCountByRepoID(
+		db.DefaultContext,
 		id,
 		repo_model.FindReleasesOptions{
 			IncludeTags: true,
diff --git a/models/issues/assignees.go b/models/issues/assignees.go
index d3a1f5ffe..159086bd0 100644
--- a/models/issues/assignees.go
+++ b/models/issues/assignees.go
@@ -102,7 +102,7 @@ func toggleIssueAssignee(ctx context.Context, issue *Issue, doer *user_model.Use
 		AssigneeID:      assigneeID,
 	}
 	// Comment
-	comment, err = CreateCommentCtx(ctx, opts)
+	comment, err = CreateComment(ctx, opts)
 	if err != nil {
 		return false, nil, fmt.Errorf("createComment: %w", err)
 	}
diff --git a/models/issues/comment.go b/models/issues/comment.go
index 2abe692a6..612f17aa5 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -779,8 +779,8 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
 	return err
 }
 
-// CreateCommentCtx creates comment with context
-func CreateCommentCtx(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) {
+// CreateComment creates comment with context
+func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) {
 	e := db.GetEngine(ctx)
 	var LabelID int64
 	if opts.Label != nil {
@@ -915,7 +915,7 @@ func createDeadlineComment(ctx context.Context, doer *user_model.User, issue *Is
 		Issue:   issue,
 		Content: content,
 	}
-	comment, err := CreateCommentCtx(ctx, opts)
+	comment, err := CreateComment(ctx, opts)
 	if err != nil {
 		return nil, err
 	}
@@ -940,7 +940,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
 		Issue:            issue,
 		DependentIssueID: dependentIssue.ID,
 	}
-	if _, err = CreateCommentCtx(ctx, opts); err != nil {
+	if _, err = CreateComment(ctx, opts); err != nil {
 		return
 	}
 
@@ -951,7 +951,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
 		Issue:            dependentIssue,
 		DependentIssueID: issue.ID,
 	}
-	_, err = CreateCommentCtx(ctx, opts)
+	_, err = CreateComment(ctx, opts)
 	return err
 }
 
@@ -993,55 +993,6 @@ type CreateCommentOptions struct {
 	Invalidated      bool
 }
 
-// CreateComment creates comment of issue or commit.
-func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
-	ctx, committer, err := db.TxContext(db.DefaultContext)
-	if err != nil {
-		return nil, err
-	}
-	defer committer.Close()
-
-	comment, err = CreateCommentCtx(ctx, opts)
-	if err != nil {
-		return nil, err
-	}
-
-	if err = committer.Commit(); err != nil {
-		return nil, err
-	}
-
-	return comment, nil
-}
-
-// CreateRefComment creates a commit reference comment to issue.
-func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *Issue, content, commitSHA string) error {
-	if len(commitSHA) == 0 {
-		return fmt.Errorf("cannot create reference with empty commit SHA")
-	}
-
-	// Check if same reference from same commit has already existed.
-	has, err := db.GetEngine(db.DefaultContext).Get(&Comment{
-		Type:      CommentTypeCommitRef,
-		IssueID:   issue.ID,
-		CommitSHA: commitSHA,
-	})
-	if err != nil {
-		return fmt.Errorf("check reference comment: %w", err)
-	} else if has {
-		return nil
-	}
-
-	_, err = CreateComment(&CreateCommentOptions{
-		Type:      CommentTypeCommitRef,
-		Doer:      doer,
-		Repo:      repo,
-		Issue:     issue,
-		CommitSHA: commitSHA,
-		Content:   content,
-	})
-	return err
-}
-
 // GetCommentByID returns the comment by given ID.
 func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
 	c := new(Comment)
@@ -1317,39 +1268,6 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID
 	return err
 }
 
-// CreatePushPullComment create push code to pull base comment
-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
-	}
-
-	ops := &CreateCommentOptions{
-		Type: CommentTypePullRequestPush,
-		Doer: pusher,
-		Repo: pr.BaseRepo,
-	}
-
-	var data PushActionContent
-
-	data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
-	if err != nil {
-		return nil, err
-	}
-
-	ops.Issue = pr.Issue
-
-	dataJSON, err := json.Marshal(data)
-	if err != nil {
-		return nil, err
-	}
-
-	ops.Content = string(dataJSON)
-
-	comment, err = CreateComment(ops)
-
-	return comment, err
-}
-
 // CreateAutoMergeComment is a internal function, only use it for CommentTypePRScheduledToAutoMerge and CommentTypePRUnScheduledToAutoMerge CommentTypes
 func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullRequest, doer *user_model.User) (comment *Comment, err error) {
 	if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge {
@@ -1363,7 +1281,7 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
 		return
 	}
 
-	comment, err = CreateCommentCtx(ctx, &CreateCommentOptions{
+	comment, err = CreateComment(ctx, &CreateCommentOptions{
 		Type:  typ,
 		Doer:  doer,
 		Repo:  pr.BaseRepo,
@@ -1372,120 +1290,6 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
 	return comment, err
 }
 
-// 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(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) {
-	repoPath := repo.RepoPath()
-	gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath)
-	if err != nil {
-		return nil, false, err
-	}
-	defer closer.Close()
-
-	oldCommit, err := gitRepo.GetCommit(oldCommitID)
-	if err != nil {
-		return nil, false, err
-	}
-
-	if err = oldCommit.LoadBranchName(); err != nil {
-		return nil, false, err
-	}
-
-	if len(oldCommit.Branch) == 0 {
-		commitIDs = make([]string, 2)
-		commitIDs[0] = oldCommitID
-		commitIDs[1] = newCommitID
-
-		return commitIDs, true, err
-	}
-
-	newCommit, err := gitRepo.GetCommit(newCommitID)
-	if err != nil {
-		return nil, false, err
-	}
-
-	commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
-	if err != nil {
-		return nil, false, err
-	}
-
-	commitIDs = make([]string, 0, len(commits))
-	commitChecks := make(map[string]*commitBranchCheckItem)
-
-	for _, commit := range commits {
-		commitChecks[commit.ID.String()] = &commitBranchCheckItem{
-			Commit:  commit,
-			Checked: false,
-		}
-	}
-
-	if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
-		return
-	}
-
-	for i := len(commits) - 1; i >= 0; i-- {
-		commitID := commits[i].ID.String()
-		if item, ok := commitChecks[commitID]; ok && item.Checked {
-			commitIDs = append(commitIDs, commitID)
-		}
-	}
-
-	return commitIDs, isForcePush, err
-}
-
-type commitBranchCheckItem struct {
-	Commit  *git.Commit
-	Checked bool
-}
-
-func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
-	if startCommit.ID.String() == endCommitID {
-		return nil
-	}
-
-	checkStack := make([]string, 0, 10)
-	checkStack = append(checkStack, startCommit.ID.String())
-
-	for len(checkStack) > 0 {
-		commitID := checkStack[0]
-		checkStack = checkStack[1:]
-
-		item, ok := commitList[commitID]
-		if !ok {
-			continue
-		}
-
-		if item.Commit.ID.String() == endCommitID {
-			continue
-		}
-
-		if err := item.Commit.LoadBranchName(); err != nil {
-			return err
-		}
-
-		if item.Commit.Branch == baseBranch {
-			continue
-		}
-
-		if item.Checked {
-			continue
-		}
-
-		item.Checked = true
-
-		parentNum := item.Commit.ParentCount()
-		for i := 0; i < parentNum; i++ {
-			parentCommit, err := item.Commit.Parent(i)
-			if err != nil {
-				return err
-			}
-			checkStack = append(checkStack, parentCommit.ID.String())
-		}
-	}
-	return nil
-}
-
 // RemapExternalUser ExternalUserRemappable interface
 func (c *Comment) RemapExternalUser(externalName string, externalID, userID int64) error {
 	c.OriginalAuthor = externalName
diff --git a/models/issues/comment_test.go b/models/issues/comment_test.go
index 6a647474d..0d0570ae3 100644
--- a/models/issues/comment_test.go
+++ b/models/issues/comment_test.go
@@ -24,7 +24,7 @@ func TestCreateComment(t *testing.T) {
 	doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
 	now := time.Now().Unix()
-	comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{
+	comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
 		Type:    issues_model.CommentTypeComment,
 		Doer:    doer,
 		Repo:    repo,
diff --git a/models/issues/issue.go b/models/issues/issue.go
index 3ab6d204b..fc93fcf45 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -202,16 +202,12 @@ func (issue *Issue) LoadRepo(ctx context.Context) (err error) {
 }
 
 // IsTimetrackerEnabled returns true if the repo enables timetracking
-func (issue *Issue) IsTimetrackerEnabled() bool {
-	return issue.isTimetrackerEnabled(db.DefaultContext)
-}
-
-func (issue *Issue) isTimetrackerEnabled(ctx context.Context) bool {
+func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool {
 	if err := issue.LoadRepo(ctx); err != nil {
 		log.Error(fmt.Sprintf("loadRepo: %v", err))
 		return false
 	}
-	return issue.Repo.IsTimetrackerEnabledCtx(ctx)
+	return issue.Repo.IsTimetrackerEnabled(ctx)
 }
 
 // GetPullRequest returns the issue pull request
@@ -404,7 +400,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
 	if err = CommentList(issue.Comments).loadAttributes(ctx); err != nil {
 		return err
 	}
-	if issue.isTimetrackerEnabled(ctx) {
+	if issue.IsTimetrackerEnabled(ctx) {
 		if err = issue.LoadTotalTimes(ctx); err != nil {
 			return err
 		}
@@ -673,7 +669,7 @@ func changeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User,
 
 func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, isMergePull bool) (*Comment, error) {
 	// Check for open dependencies
-	if issue.IsClosed && issue.Repo.IsDependenciesEnabledCtx(ctx) {
+	if issue.IsClosed && issue.Repo.IsDependenciesEnabled(ctx) {
 		// only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies
 		noDeps, err := IssueNoDependenciesLeft(ctx, issue)
 		if err != nil {
@@ -725,7 +721,7 @@ func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.Use
 		cmtType = CommentTypeMergePull
 	}
 
-	return CreateCommentCtx(ctx, &CreateCommentOptions{
+	return CreateComment(ctx, &CreateCommentOptions{
 		Type:  cmtType,
 		Doer:  doer,
 		Repo:  issue.Repo,
@@ -769,7 +765,7 @@ func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err
 		OldTitle: oldTitle,
 		NewTitle: issue.Title,
 	}
-	if _, err = CreateCommentCtx(ctx, opts); err != nil {
+	if _, err = CreateComment(ctx, opts); err != nil {
 		return fmt.Errorf("createComment: %w", err)
 	}
 	if err = issue.AddCrossReferences(ctx, doer, true); err != nil {
@@ -805,7 +801,7 @@ func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err err
 		OldRef: oldRefFriendly,
 		NewRef: newRefFriendly,
 	}
-	if _, err = CreateCommentCtx(ctx, opts); err != nil {
+	if _, err = CreateComment(ctx, opts); err != nil {
 		return fmt.Errorf("createComment: %w", err)
 	}
 
@@ -825,7 +821,7 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo *
 		Issue:  issue,
 		OldRef: branchName,
 	}
-	_, err = CreateCommentCtx(ctx, opts)
+	_, err = CreateComment(ctx, opts)
 	return err
 }
 
@@ -992,7 +988,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue
 			OldMilestoneID: 0,
 			MilestoneID:    opts.Issue.MilestoneID,
 		}
-		if _, err = CreateCommentCtx(ctx, opts); err != nil {
+		if _, err = CreateComment(ctx, opts); err != nil {
 			return err
 		}
 	}
@@ -2000,7 +1996,7 @@ func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment
 			OldTitle: currentIssue.Title,
 			NewTitle: issue.Title,
 		}
-		_, err := CreateCommentCtx(ctx, opts)
+		_, err := CreateComment(ctx, opts)
 		if err != nil {
 			return nil, false, fmt.Errorf("createComment: %w", err)
 		}
diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go
index 35a0c1f0e..e22e48c0b 100644
--- a/models/issues/issue_list.go
+++ b/models/issues/issue_list.go
@@ -461,7 +461,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
 
 	ids := make([]int64, 0, len(issues))
 	for _, issue := range issues {
-		if issue.Repo.IsTimetrackerEnabled() {
+		if issue.Repo.IsTimetrackerEnabled(ctx) {
 			ids = append(ids, issue.ID)
 		}
 	}
diff --git a/models/issues/issue_lock.go b/models/issues/issue_lock.go
index 1376ffcad..19cd6d316 100644
--- a/models/issues/issue_lock.go
+++ b/models/issues/issue_lock.go
@@ -56,7 +56,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
 		Type:    commentType,
 		Content: opts.Reason,
 	}
-	if _, err := CreateCommentCtx(ctx, opt); err != nil {
+	if _, err := CreateComment(ctx, opt); err != nil {
 		return err
 	}
 
diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go
index a366a92fa..8e559f13c 100644
--- a/models/issues/issue_project.go
+++ b/models/issues/issue_project.go
@@ -145,7 +145,7 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U
 	}
 
 	if oldProjectID > 0 || newProjectID > 0 {
-		if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+		if _, err := CreateComment(ctx, &CreateCommentOptions{
 			Type:         CommentTypeProject,
 			Doer:         doer,
 			Repo:         issue.Repo,
diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go
index 267ccc73a..21ee24210 100644
--- a/models/issues/issue_xref.go
+++ b/models/issues/issue_xref.go
@@ -121,7 +121,7 @@ func (issue *Issue) createCrossReferences(stdCtx context.Context, ctx *crossRefe
 			RefAction:    xref.Action,
 			RefIsPull:    ctx.OrigIssue.IsPull,
 		}
-		_, err := CreateCommentCtx(stdCtx, opts)
+		_, err := CreateComment(stdCtx, opts)
 		if err != nil {
 			return err
 		}
diff --git a/models/issues/label.go b/models/issues/label.go
index e5583ff00..dbb7a139e 100644
--- a/models/issues/label.go
+++ b/models/issues/label.go
@@ -613,7 +613,7 @@ func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
 		Label:   label,
 		Content: "1",
 	}
-	if _, err = CreateCommentCtx(ctx, opts); err != nil {
+	if _, err = CreateComment(ctx, opts); err != nil {
 		return err
 	}
 
@@ -714,7 +714,7 @@ func deleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
 		Issue: issue,
 		Label: label,
 	}
-	if _, err = CreateCommentCtx(ctx, opts); err != nil {
+	if _, err = CreateComment(ctx, opts); err != nil {
 		return err
 	}
 
diff --git a/models/issues/review.go b/models/issues/review.go
index db2d2686c..7dee28fe9 100644
--- a/models/issues/review.go
+++ b/models/issues/review.go
@@ -294,7 +294,7 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio
 	}
 
 	if !pr.ProtectedBranch.EnableApprovalsWhitelist {
-		return team.UnitAccessModeCtx(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil
+		return team.UnitAccessMode(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil
 	}
 
 	return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil
@@ -436,7 +436,7 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co
 		}
 	}
 
-	comm, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	comm, err := CreateComment(ctx, &CreateCommentOptions{
 		Type:        CommentTypeReview,
 		Doer:        doer,
 		Content:     review.Content,
@@ -692,7 +692,7 @@ func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment,
 		return nil, err
 	}
 
-	comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	comment, err := CreateComment(ctx, &CreateCommentOptions{
 		Type:            CommentTypeReviewRequest,
 		Doer:            doer,
 		Repo:            issue.Repo,
@@ -746,7 +746,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Commen
 		}
 	}
 
-	comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	comment, err := CreateComment(ctx, &CreateCommentOptions{
 		Type:            CommentTypeReviewRequest,
 		Doer:            doer,
 		Repo:            issue.Repo,
@@ -804,7 +804,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_
 		}
 	}
 
-	comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	comment, err := CreateComment(ctx, &CreateCommentOptions{
 		Type:            CommentTypeReviewRequest,
 		Doer:            doer,
 		Repo:            issue.Repo,
@@ -814,7 +814,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_
 		ReviewID:        review.ID,
 	})
 	if err != nil {
-		return nil, fmt.Errorf("CreateCommentCtx(): %w", err)
+		return nil, fmt.Errorf("CreateComment(): %w", err)
 	}
 
 	return comment, committer.Commit()
@@ -864,7 +864,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us
 		return nil, committer.Commit()
 	}
 
-	comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	comment, err := CreateComment(ctx, &CreateCommentOptions{
 		Type:            CommentTypeReviewRequest,
 		Doer:            doer,
 		Repo:            issue.Repo,
@@ -873,7 +873,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us
 		AssigneeTeamID:  reviewer.ID, // Use AssigneeTeamID as reviewer team ID
 	})
 	if err != nil {
-		return nil, fmt.Errorf("CreateCommentCtx(): %w", err)
+		return nil, fmt.Errorf("CreateComment(): %w", err)
 	}
 
 	return comment, committer.Commit()
diff --git a/models/issues/stopwatch.go b/models/issues/stopwatch.go
index 8a8fdca33..6bf936c5d 100644
--- a/models/issues/stopwatch.go
+++ b/models/issues/stopwatch.go
@@ -196,7 +196,7 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
 		return err
 	}
 
-	if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	if _, err := CreateComment(ctx, &CreateCommentOptions{
 		Doer:    user,
 		Issue:   issue,
 		Repo:    issue.Repo,
@@ -246,7 +246,7 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
 		return err
 	}
 
-	if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	if _, err := CreateComment(ctx, &CreateCommentOptions{
 		Doer:  user,
 		Issue: issue,
 		Repo:  issue.Repo,
@@ -287,7 +287,7 @@ func cancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) e
 			return err
 		}
 
-		if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+		if _, err := CreateComment(ctx, &CreateCommentOptions{
 			Doer:  user,
 			Issue: issue,
 			Repo:  issue.Repo,
diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go
index 554b01bd4..ac65d654f 100644
--- a/models/issues/tracked_time.go
+++ b/models/issues/tracked_time.go
@@ -172,7 +172,7 @@ func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Tim
 		return nil, err
 	}
 
-	if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	if _, err := CreateComment(ctx, &CreateCommentOptions{
 		Issue:   issue,
 		Repo:    issue.Repo,
 		Doer:    user,
@@ -250,7 +250,7 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
 	if err := issue.LoadRepo(ctx); err != nil {
 		return err
 	}
-	if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	if _, err := CreateComment(ctx, &CreateCommentOptions{
 		Issue:   issue,
 		Repo:    issue.Repo,
 		Doer:    user,
@@ -279,7 +279,7 @@ func DeleteTime(t *TrackedTime) error {
 		return err
 	}
 
-	if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{
+	if _, err := CreateComment(ctx, &CreateCommentOptions{
 		Issue:   t.Issue,
 		Repo:    t.Issue.Repo,
 		Doer:    t.User,
diff --git a/models/organization/org.go b/models/organization/org.go
index a5b07d5aa..b3d77b4ec 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -106,7 +106,7 @@ func (org *Organization) IsOrgMember(uid int64) (bool, error) {
 
 // CanCreateOrgRepo returns true if given user can create repo in organization
 func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) {
-	return CanCreateOrgRepo(org.ID, uid)
+	return CanCreateOrgRepo(db.DefaultContext, org.ID, uid)
 }
 
 func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) {
diff --git a/models/organization/org_user.go b/models/organization/org_user.go
index d514e401b..e5cbfe6c0 100644
--- a/models/organization/org_user.go
+++ b/models/organization/org_user.go
@@ -73,8 +73,8 @@ func IsPublicMembership(orgID, uid int64) (bool, error) {
 }
 
 // CanCreateOrgRepo returns true if user can create repo in organization
-func CanCreateOrgRepo(orgID, uid int64) (bool, error) {
-	return db.GetEngine(db.DefaultContext).
+func CanCreateOrgRepo(ctx context.Context, orgID, uid int64) (bool, error) {
+	return db.GetEngine(ctx).
 		Where(builder.Eq{"team.can_create_org_repo": true}).
 		Join("INNER", "team_user", "team_user.team_id = team.id").
 		And("team_user.uid = ?", uid).
diff --git a/models/organization/team.go b/models/organization/team.go
index 86ea30c80..55d3f1727 100644
--- a/models/organization/team.go
+++ b/models/organization/team.go
@@ -242,18 +242,12 @@ func (t *Team) LoadMembers(ctx context.Context) (err error) {
 }
 
 // UnitEnabled returns if the team has the given unit type enabled
-func (t *Team) UnitEnabled(tp unit.Type) bool {
-	return t.UnitAccessMode(tp) > perm.AccessModeNone
+func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool {
+	return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone
 }
 
 // UnitAccessMode returns if the team has the given unit type enabled
-// it is called in templates, should not be replaced by `UnitAccessModeCtx(ctx ...)`
-func (t *Team) UnitAccessMode(tp unit.Type) perm.AccessMode { // Notice: It will be used in template, don't remove it directly
-	return t.UnitAccessModeCtx(db.DefaultContext, tp)
-}
-
-// UnitAccessModeCtx returns if the team has the given unit type enabled
-func (t *Team) UnitAccessModeCtx(ctx context.Context, tp unit.Type) perm.AccessMode {
+func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode {
 	if err := t.getUnits(ctx); err != nil {
 		log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
 	}
diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go
index 88437dc4b..a6bf9b674 100644
--- a/models/perm/access/repo_permission.go
+++ b/models/perm/access/repo_permission.go
@@ -244,7 +244,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
 	for _, u := range repo.Units {
 		var found bool
 		for _, team := range teams {
-			teamMode := team.UnitAccessModeCtx(ctx, u.Type)
+			teamMode := team.UnitAccessMode(ctx, u.Type)
 			if teamMode > perm_model.AccessModeNone {
 				m := perm.UnitsMode[u.Type]
 				if m < teamMode {
diff --git a/models/project/project.go b/models/project/project.go
index 384f51c5a..bcf116640 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -298,44 +298,32 @@ func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error {
 	return updateRepositoryProjectCount(ctx, p.RepoID)
 }
 
-// DeleteProjectByID deletes a project from a repository.
-func DeleteProjectByID(id int64) error {
-	ctx, committer, err := db.TxContext(db.DefaultContext)
-	if err != nil {
-		return err
-	}
-	defer committer.Close()
-
-	if err := DeleteProjectByIDCtx(ctx, id); err != nil {
-		return err
-	}
-
-	return committer.Commit()
-}
-
-// DeleteProjectByIDCtx deletes a project from a repository.
-func DeleteProjectByIDCtx(ctx context.Context, id int64) error {
-	p, err := GetProjectByID(ctx, id)
-	if err != nil {
-		if IsErrProjectNotExist(err) {
-			return nil
+// DeleteProjectByID deletes a project from a repository. if it's not in a database
+// transaction, it will start a new database transaction
+func DeleteProjectByID(ctx context.Context, id int64) error {
+	return db.AutoTx(ctx, func(ctx context.Context) error {
+		p, err := GetProjectByID(ctx, id)
+		if err != nil {
+			if IsErrProjectNotExist(err) {
+				return nil
+			}
+			return err
 		}
-		return err
-	}
 
-	if err := deleteProjectIssuesByProjectID(ctx, id); err != nil {
-		return err
-	}
+		if err := deleteProjectIssuesByProjectID(ctx, id); err != nil {
+			return err
+		}
 
-	if err := deleteBoardByProjectID(ctx, id); err != nil {
-		return err
-	}
+		if err := deleteBoardByProjectID(ctx, id); err != nil {
+			return err
+		}
 
-	if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Project)); err != nil {
-		return err
-	}
+		if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Project)); err != nil {
+			return err
+		}
 
-	return updateRepositoryProjectCount(ctx, p.RepoID)
+		return updateRepositoryProjectCount(ctx, p.RepoID)
+	})
 }
 
 func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {
diff --git a/models/repo/collaboration.go b/models/repo/collaboration.go
index bd49b9aec..29bcab70f 100644
--- a/models/repo/collaboration.go
+++ b/models/repo/collaboration.go
@@ -99,55 +99,42 @@ func getCollaborations(ctx context.Context, repoID int64, listOptions db.ListOpt
 }
 
 // ChangeCollaborationAccessMode sets new access mode for the collaboration.
-func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error {
+func ChangeCollaborationAccessMode(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error {
 	// Discard invalid input
 	if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner {
 		return nil
 	}
 
-	e := db.GetEngine(ctx)
+	return db.AutoTx(ctx, func(ctx context.Context) error {
+		e := db.GetEngine(ctx)
+
+		collaboration := &Collaboration{
+			RepoID: repo.ID,
+			UserID: uid,
+		}
+		has, err := e.Get(collaboration)
+		if err != nil {
+			return fmt.Errorf("get collaboration: %w", err)
+		} else if !has {
+			return nil
+		}
+
+		if collaboration.Mode == mode {
+			return nil
+		}
+		collaboration.Mode = mode
+
+		if _, err = e.
+			ID(collaboration.ID).
+			Cols("mode").
+			Update(collaboration); err != nil {
+			return fmt.Errorf("update collaboration: %w", err)
+		} else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil {
+			return fmt.Errorf("update access table: %w", err)
+		}
 
-	collaboration := &Collaboration{
-		RepoID: repo.ID,
-		UserID: uid,
-	}
-	has, err := e.Get(collaboration)
-	if err != nil {
-		return fmt.Errorf("get collaboration: %w", err)
-	} else if !has {
 		return nil
-	}
-
-	if collaboration.Mode == mode {
-		return nil
-	}
-	collaboration.Mode = mode
-
-	if _, err = e.
-		ID(collaboration.ID).
-		Cols("mode").
-		Update(collaboration); err != nil {
-		return fmt.Errorf("update collaboration: %w", err)
-	} else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil {
-		return fmt.Errorf("update access table: %w", err)
-	}
-
-	return nil
-}
-
-// ChangeCollaborationAccessMode sets new access mode for the collaboration.
-func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error {
-	ctx, committer, err := db.TxContext(db.DefaultContext)
-	if err != nil {
-		return err
-	}
-	defer committer.Close()
-
-	if err := ChangeCollaborationAccessModeCtx(ctx, repo, uid, mode); err != nil {
-		return err
-	}
-
-	return committer.Commit()
+	})
 }
 
 // IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository
diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go
index d240e9cbe..0a6444de8 100644
--- a/models/repo/collaboration_test.go
+++ b/models/repo/collaboration_test.go
@@ -54,7 +54,7 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
 	assert.NoError(t, unittest.PrepareTestDatabase())
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
 
 	collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4})
 	assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode)
@@ -62,9 +62,9 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
 	access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID})
 	assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
 
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
 
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, unittest.NonexistentID, perm.AccessModeAdmin))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
 
 	unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
 }
diff --git a/models/repo/issue.go b/models/repo/issue.go
index e27179caf..6f6b565a0 100644
--- a/models/repo/issue.go
+++ b/models/repo/issue.go
@@ -6,7 +6,6 @@ package repo
 import (
 	"context"
 
-	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/models/unit"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
@@ -26,44 +25,34 @@ func (repo *Repository) CanEnableTimetracker() bool {
 }
 
 // IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
-func (repo *Repository) IsTimetrackerEnabled() bool { // Notice: It will be used in template so don't remove directly
-	return repo.IsTimetrackerEnabledCtx(db.DefaultContext)
-}
-
-// IsTimetrackerEnabledCtx returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
-func (repo *Repository) IsTimetrackerEnabledCtx(ctx context.Context) bool {
+func (repo *Repository) IsTimetrackerEnabled(ctx context.Context) bool {
 	if !setting.Service.EnableTimetracking {
 		return false
 	}
 
 	var u *RepoUnit
 	var err error
-	if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil {
+	if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
 		return setting.Service.DefaultEnableTimetracking
 	}
 	return u.IssuesConfig().EnableTimetracker
 }
 
 // AllowOnlyContributorsToTrackTime returns value of IssuesConfig or the default value
-func (repo *Repository) AllowOnlyContributorsToTrackTime() bool {
+func (repo *Repository) AllowOnlyContributorsToTrackTime(ctx context.Context) bool {
 	var u *RepoUnit
 	var err error
-	if u, err = repo.GetUnit(unit.TypeIssues); err != nil {
+	if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
 		return setting.Service.DefaultAllowOnlyContributorsToTrackTime
 	}
 	return u.IssuesConfig().AllowOnlyContributorsToTrackTime
 }
 
 // IsDependenciesEnabled returns if dependencies are enabled and returns the default setting if not set.
-func (repo *Repository) IsDependenciesEnabled() bool {
-	return repo.IsDependenciesEnabledCtx(db.DefaultContext)
-}
-
-// IsDependenciesEnabledCtx returns if dependencies are enabled and returns the default setting if not set.
-func (repo *Repository) IsDependenciesEnabledCtx(ctx context.Context) bool {
+func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool {
 	var u *RepoUnit
 	var err error
-	if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil {
+	if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
 		log.Trace("%s", err)
 		return setting.Service.DefaultEnableDependencies
 	}
diff --git a/models/repo/release.go b/models/repo/release.go
index c6cb75534..25eba10e0 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -286,8 +286,8 @@ func GetReleasesByRepoIDAndNames(ctx context.Context, repoID int64, tagNames []s
 }
 
 // GetReleaseCountByRepoID returns the count of releases of repository
-func GetReleaseCountByRepoID(repoID int64, opts FindReleasesOptions) (int64, error) {
-	return db.GetEngine(db.DefaultContext).Where(opts.toConds(repoID)).Count(&Release{})
+func GetReleaseCountByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) {
+	return db.GetEngine(ctx).Where(opts.toConds(repoID)).Count(&Release{})
 }
 
 type releaseMetaSearch struct {
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 7cb713852..e5e1ac43b 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -315,12 +315,7 @@ func (repo *Repository) LoadUnits(ctx context.Context) (err error) {
 }
 
 // UnitEnabled if this repository has the given unit enabled
-func (repo *Repository) UnitEnabled(tp unit.Type) (result bool) { // Notice: Don't remove this function directly, because it has been used in go template.
-	return repo.UnitEnabledCtx(db.DefaultContext, tp)
-}
-
-// UnitEnabled if this repository has the given unit enabled
-func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool {
+func (repo *Repository) UnitEnabled(ctx context.Context, tp unit.Type) bool {
 	if err := repo.LoadUnits(ctx); err != nil {
 		log.Warn("Error loading repository (ID: %d) units: %s", repo.ID, err.Error())
 	}
@@ -333,8 +328,8 @@ func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool {
 }
 
 // MustGetUnit always returns a RepoUnit object
-func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit {
-	ru, err := repo.GetUnit(tp)
+func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit {
+	ru, err := repo.GetUnit(ctx, tp)
 	if err == nil {
 		return ru
 	}
@@ -367,12 +362,7 @@ func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit {
 }
 
 // GetUnit returns a RepoUnit object
-func (repo *Repository) GetUnit(tp unit.Type) (*RepoUnit, error) {
-	return repo.GetUnitCtx(db.DefaultContext, tp)
-}
-
-// GetUnitCtx returns a RepoUnit object
-func (repo *Repository) GetUnitCtx(ctx context.Context, tp unit.Type) (*RepoUnit, error) {
+func (repo *Repository) GetUnit(ctx context.Context, tp unit.Type) (*RepoUnit, error) {
 	if err := repo.LoadUnits(ctx); err != nil {
 		return nil, err
 	}
@@ -419,7 +409,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
 			"mode":     "comment",
 		}
 
-		unit, err := repo.GetUnit(unit.TypeExternalTracker)
+		unit, err := repo.GetUnit(db.DefaultContext, unit.TypeExternalTracker)
 		if err == nil {
 			metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
 			switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
@@ -518,7 +508,7 @@ func (repo *Repository) CanEnablePulls() bool {
 
 // AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
 func (repo *Repository) AllowsPulls() bool {
-	return repo.CanEnablePulls() && repo.UnitEnabled(unit.TypePullRequests)
+	return repo.CanEnablePulls() && repo.UnitEnabled(db.DefaultContext, unit.TypePullRequests)
 }
 
 // CanEnableEditor returns true if repository meets the requirements of web editor.
diff --git a/models/repo_transfer.go b/models/repo_transfer.go
index 362253bdc..19e6c0662 100644
--- a/models/repo_transfer.go
+++ b/models/repo_transfer.go
@@ -39,9 +39,9 @@ func init() {
 }
 
 // LoadAttributes fetches the transfer recipient from the database
-func (r *RepoTransfer) LoadAttributes() error {
+func (r *RepoTransfer) LoadAttributes(ctx context.Context) error {
 	if r.Recipient == nil {
-		u, err := user_model.GetUserByID(db.DefaultContext, r.RecipientID)
+		u, err := user_model.GetUserByID(ctx, r.RecipientID)
 		if err != nil {
 			return err
 		}
@@ -51,7 +51,7 @@ func (r *RepoTransfer) LoadAttributes() error {
 
 	if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) {
 		for _, v := range r.TeamIDs {
-			team, err := organization.GetTeamByID(db.DefaultContext, v)
+			team, err := organization.GetTeamByID(ctx, v)
 			if err != nil {
 				return err
 			}
@@ -65,7 +65,7 @@ func (r *RepoTransfer) LoadAttributes() error {
 	}
 
 	if r.Doer == nil {
-		u, err := user_model.GetUserByID(db.DefaultContext, r.DoerID)
+		u, err := user_model.GetUserByID(ctx, r.DoerID)
 		if err != nil {
 			return err
 		}
@@ -80,7 +80,7 @@ func (r *RepoTransfer) LoadAttributes() error {
 // For user, it checks if it's himself
 // For organizations, it checks if the user is able to create repos
 func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
-	if err := r.LoadAttributes(); err != nil {
+	if err := r.LoadAttributes(db.DefaultContext); err != nil {
 		log.Error("LoadAttributes: %v", err)
 		return false
 	}
@@ -89,7 +89,7 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
 		return r.RecipientID == u.ID
 	}
 
-	allowed, err := organization.CanCreateOrgRepo(r.RecipientID, u.ID)
+	allowed, err := organization.CanCreateOrgRepo(db.DefaultContext, r.RecipientID, u.ID)
 	if err != nil {
 		log.Error("CanCreateOrgRepo: %v", err)
 		return false
@@ -100,10 +100,10 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
 
 // GetPendingRepositoryTransfer fetches the most recent and ongoing transfer
 // process for the repository
-func GetPendingRepositoryTransfer(repo *repo_model.Repository) (*RepoTransfer, error) {
+func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Repository) (*RepoTransfer, error) {
 	transfer := new(RepoTransfer)
 
-	has, err := db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repo.ID).Get(transfer)
+	has, err := db.GetEngine(ctx).Where("repo_id = ? ", repo.ID).Get(transfer)
 	if err != nil {
 		return nil, err
 	}
@@ -154,56 +154,48 @@ func TestRepositoryReadyForTransfer(status repo_model.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_model.User, repoID int64, teams []*organization.Team) error {
-	ctx, committer, err := db.TxContext(db.DefaultContext)
-	if err != nil {
-		return err
-	}
-	defer committer.Close()
-
-	repo, err := repo_model.GetRepositoryByID(ctx, repoID)
-	if err != nil {
-		return err
-	}
-
-	// Make sure repo is ready to transfer
-	if err := TestRepositoryReadyForTransfer(repo.Status); err != nil {
-		return err
-	}
-
-	repo.Status = repo_model.RepositoryPendingTransfer
-	if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
-		return err
-	}
-
-	// Check if new owner has repository with same name.
-	if has, err := repo_model.IsRepositoryExist(ctx, newOwner, repo.Name); err != nil {
-		return fmt.Errorf("IsRepositoryExist: %w", err)
-	} else if has {
-		return repo_model.ErrRepoAlreadyExist{
-			Uname: newOwner.LowerName,
-			Name:  repo.Name,
+func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error {
+	return db.AutoTx(ctx, func(ctx context.Context) error {
+		repo, err := repo_model.GetRepositoryByID(ctx, repoID)
+		if err != nil {
+			return err
 		}
-	}
 
-	transfer := &RepoTransfer{
-		RepoID:      repo.ID,
-		RecipientID: newOwner.ID,
-		CreatedUnix: timeutil.TimeStampNow(),
-		UpdatedUnix: timeutil.TimeStampNow(),
-		DoerID:      doer.ID,
-		TeamIDs:     make([]int64, 0, len(teams)),
-	}
+		// Make sure repo is ready to transfer
+		if err := TestRepositoryReadyForTransfer(repo.Status); err != nil {
+			return err
+		}
 
-	for k := range teams {
-		transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID)
-	}
+		repo.Status = repo_model.RepositoryPendingTransfer
+		if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil {
+			return err
+		}
 
-	if err := db.Insert(ctx, transfer); err != nil {
-		return err
-	}
+		// Check if new owner has repository with same name.
+		if has, err := repo_model.IsRepositoryExist(ctx, newOwner, repo.Name); err != nil {
+			return fmt.Errorf("IsRepositoryExist: %w", err)
+		} else if has {
+			return repo_model.ErrRepoAlreadyExist{
+				Uname: newOwner.LowerName,
+				Name:  repo.Name,
+			}
+		}
 
-	return committer.Commit()
+		transfer := &RepoTransfer{
+			RepoID:      repo.ID,
+			RecipientID: newOwner.ID,
+			CreatedUnix: timeutil.TimeStampNow(),
+			UpdatedUnix: timeutil.TimeStampNow(),
+			DoerID:      doer.ID,
+			TeamIDs:     make([]int64, 0, len(teams)),
+		}
+
+		for k := range teams {
+			transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID)
+		}
+
+		return db.Insert(ctx, transfer)
+	})
 }
 
 // TransferOwnership transfers all corresponding repository items from old user to new one.
diff --git a/models/repo_transfer_test.go b/models/repo_transfer_test.go
index 9720071a9..8352adc94 100644
--- a/models/repo_transfer_test.go
+++ b/models/repo_transfer_test.go
@@ -6,6 +6,7 @@ package models
 import (
 	"testing"
 
+	"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"
@@ -19,36 +20,36 @@ func TestRepositoryTransfer(t *testing.T) {
 	doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
 
-	transfer, err := GetPendingRepositoryTransfer(repo)
+	transfer, err := GetPendingRepositoryTransfer(db.DefaultContext, repo)
 	assert.NoError(t, err)
 	assert.NotNil(t, transfer)
 
 	// Cancel transfer
 	assert.NoError(t, CancelRepositoryTransfer(repo))
 
-	transfer, err = GetPendingRepositoryTransfer(repo)
+	transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo)
 	assert.Error(t, err)
 	assert.Nil(t, transfer)
 	assert.True(t, IsErrNoPendingTransfer(err))
 
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
-	assert.NoError(t, CreatePendingRepositoryTransfer(doer, user2, repo.ID, nil))
+	assert.NoError(t, CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil))
 
-	transfer, err = GetPendingRepositoryTransfer(repo)
+	transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo)
 	assert.Nil(t, err)
-	assert.NoError(t, transfer.LoadAttributes())
+	assert.NoError(t, transfer.LoadAttributes(db.DefaultContext))
 	assert.Equal(t, "user2", transfer.Recipient.Name)
 
 	user6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	// Only transfer can be started at any given time
-	err = CreatePendingRepositoryTransfer(doer, user6, repo.ID, nil)
+	err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, user6, repo.ID, nil)
 	assert.Error(t, err)
 	assert.True(t, IsErrRepoTransferInProgress(err))
 
 	// Unknown user
-	err = CreatePendingRepositoryTransfer(doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil)
+	err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil)
 	assert.Error(t, err)
 
 	// Cancel transfer
diff --git a/modules/context/package.go b/modules/context/package.go
index 65a9d74b7..2a55db3a7 100644
--- a/modules/context/package.go
+++ b/modules/context/package.go
@@ -110,7 +110,7 @@ func determineAccessMode(ctx *Context) (perm.AccessMode, error) {
 					return accessMode, err
 				}
 				for _, t := range teams {
-					perm := t.UnitAccessModeCtx(ctx, unit.TypePackages)
+					perm := t.UnitAccessMode(ctx, unit.TypePackages)
 					if accessMode < perm {
 						accessMode = perm
 					}
diff --git a/modules/context/repo.go b/modules/context/repo.go
index a50cb15ab..71a2b3c0c 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -163,13 +163,13 @@ func (r *Repository) CanUseTimetracker(issue *issues_model.Issue, user *user_mod
 	// 1. Is timetracker enabled
 	// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
 	isAssigned, _ := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user)
-	return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() ||
+	return r.Repository.IsTimetrackerEnabled(db.DefaultContext) && (!r.Repository.AllowOnlyContributorsToTrackTime(db.DefaultContext) ||
 		r.Permission.CanWriteIssuesOrPulls(issue.IsPull) || issue.IsPoster(user.ID) || isAssigned)
 }
 
 // CanCreateIssueDependencies returns whether or not a user can create dependencies.
 func (r *Repository) CanCreateIssueDependencies(user *user_model.User, isPull bool) bool {
-	return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull)
+	return r.Repository.IsDependenciesEnabled(db.DefaultContext) && r.Permission.CanWriteIssuesOrPulls(isPull)
 }
 
 // GetCommitsCount returns cached commit count for current view
@@ -528,12 +528,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 	ctx.Data["RepoLink"] = ctx.Repo.RepoLink
 	ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
 
-	unit, err := ctx.Repo.Repository.GetUnit(unit_model.TypeExternalTracker)
+	unit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeExternalTracker)
 	if err == nil {
 		ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL
 	}
 
-	ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{
+	ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{
 		IncludeDrafts: true,
 		IncludeTags:   true,
 		HasSha1:       util.OptionalBoolTrue, // only draft releases which are created with existing tags
@@ -542,7 +542,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 		ctx.ServerError("GetReleaseCountByRepoID", err)
 		return
 	}
-	ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
+	ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
 	if err != nil {
 		ctx.ServerError("GetReleaseCountByRepoID", err)
 		return
@@ -723,13 +723,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 	ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
 
 	if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
-		repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+		repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
 		if err != nil {
 			ctx.ServerError("GetPendingRepositoryTransfer", err)
 			return
 		}
 
-		if err := repoTransfer.LoadAttributes(); err != nil {
+		if err := repoTransfer.LoadAttributes(ctx); err != nil {
 			ctx.ServerError("LoadRecipient", err)
 			return
 		}
diff --git a/modules/convert/issue_comment.go b/modules/convert/issue_comment.go
index 983354438..6044cbcf6 100644
--- a/modules/convert/issue_comment.go
+++ b/modules/convert/issue_comment.go
@@ -149,7 +149,7 @@ func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_
 			var err error
 			repo, err = repo_model.GetRepositoryByID(ctx, c.Label.RepoID)
 			if err != nil {
-				log.Error("GetRepositoryByIDCtx(%d): %v", c.Label.RepoID, err)
+				log.Error("GetRepositoryByID(%d): %v", c.Label.RepoID, err)
 				return nil
 			}
 		}
diff --git a/modules/convert/repository.go b/modules/convert/repository.go
index 843556e1b..ce53a6669 100644
--- a/modules/convert/repository.go
+++ b/modules/convert/repository.go
@@ -8,7 +8,6 @@ import (
 	"time"
 
 	"code.gitea.io/gitea/models"
-	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/models/perm"
 	repo_model "code.gitea.io/gitea/models/repo"
 	unit_model "code.gitea.io/gitea/models/unit"
@@ -44,7 +43,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 	hasIssues := false
 	var externalTracker *api.ExternalTracker
 	var internalTracker *api.InternalTracker
-	if unit, err := repo.GetUnit(unit_model.TypeIssues); err == nil {
+	if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err == nil {
 		config := unit.IssuesConfig()
 		hasIssues = true
 		internalTracker = &api.InternalTracker{
@@ -52,7 +51,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 			AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
 			EnableIssueDependencies:          config.EnableDependencies,
 		}
-	} else if unit, err := repo.GetUnit(unit_model.TypeExternalTracker); err == nil {
+	} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalTracker); err == nil {
 		config := unit.ExternalTrackerConfig()
 		hasIssues = true
 		externalTracker = &api.ExternalTracker{
@@ -64,9 +63,9 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 	}
 	hasWiki := false
 	var externalWiki *api.ExternalWiki
-	if _, err := repo.GetUnit(unit_model.TypeWiki); err == nil {
+	if _, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil {
 		hasWiki = true
-	} else if unit, err := repo.GetUnit(unit_model.TypeExternalWiki); err == nil {
+	} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil {
 		hasWiki = true
 		config := unit.ExternalWikiConfig()
 		externalWiki = &api.ExternalWiki{
@@ -82,7 +81,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 	allowRebaseUpdate := false
 	defaultDeleteBranchAfterMerge := false
 	defaultMergeStyle := repo_model.MergeStyleMerge
-	if unit, err := repo.GetUnit(unit_model.TypePullRequests); err == nil {
+	if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil {
 		config := unit.PullRequestsConfig()
 		hasPullRequests = true
 		ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
@@ -95,21 +94,21 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 		defaultMergeStyle = config.GetDefaultMergeStyle()
 	}
 	hasProjects := false
-	if _, err := repo.GetUnit(unit_model.TypeProjects); err == nil {
+	if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil {
 		hasProjects = true
 	}
 
-	if err := repo.GetOwner(db.DefaultContext); err != nil {
+	if err := repo.GetOwner(ctx); err != nil {
 		return nil
 	}
 
-	numReleases, _ := repo_model.GetReleaseCountByRepoID(repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false})
+	numReleases, _ := repo_model.GetReleaseCountByRepoID(ctx, repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false})
 
 	mirrorInterval := ""
 	var mirrorUpdated time.Time
 	if repo.IsMirror {
 		var err error
-		repo.Mirror, err = repo_model.GetMirrorByRepoID(db.DefaultContext, repo.ID)
+		repo.Mirror, err = repo_model.GetMirrorByRepoID(ctx, repo.ID)
 		if err == nil {
 			mirrorInterval = repo.Mirror.Interval.String()
 			mirrorUpdated = repo.Mirror.UpdatedUnix.AsTime()
@@ -118,11 +117,11 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
 
 	var transfer *api.RepoTransfer
 	if repo.Status == repo_model.RepositoryPendingTransfer {
-		t, err := models.GetPendingRepositoryTransfer(repo)
+		t, err := models.GetPendingRepositoryTransfer(ctx, repo)
 		if err != nil && !models.IsErrNoPendingTransfer(err) {
 			log.Warn("GetPendingRepositoryTransfer: %v", err)
 		} else {
-			if err := t.LoadAttributes(); err != nil {
+			if err := t.LoadAttributes(ctx); err != nil {
 				log.Warn("LoadAttributes of RepoTransfer: %v", err)
 			} else {
 				transfer = ToRepoTransfer(t)
diff --git a/modules/repository/collaborator.go b/modules/repository/collaborator.go
index 44c03f999..f2b951518 100644
--- a/modules/repository/collaborator.go
+++ b/modules/repository/collaborator.go
@@ -13,30 +13,25 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 )
 
-func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
-	collaboration := &repo_model.Collaboration{
-		RepoID: repo.ID,
-		UserID: u.ID,
-	}
+func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
+	return db.AutoTx(ctx, func(ctx context.Context) error {
+		collaboration := &repo_model.Collaboration{
+			RepoID: repo.ID,
+			UserID: u.ID,
+		}
 
-	has, err := db.GetByBean(ctx, collaboration)
-	if err != nil {
-		return err
-	} else if has {
-		return nil
-	}
-	collaboration.Mode = perm.AccessModeWrite
+		has, err := db.GetByBean(ctx, collaboration)
+		if err != nil {
+			return err
+		} else if has {
+			return nil
+		}
+		collaboration.Mode = perm.AccessModeWrite
 
-	if err = db.Insert(ctx, collaboration); err != nil {
-		return err
-	}
+		if err = db.Insert(ctx, collaboration); err != nil {
+			return err
+		}
 
-	return access_model.RecalculateUserAccess(ctx, repo, u.ID)
-}
-
-// AddCollaborator adds new collaboration to a repository with default access mode.
-func AddCollaborator(repo *repo_model.Repository, u *user_model.User) error {
-	return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
-		return addCollaborator(ctx, repo, u)
+		return access_model.RecalculateUserAccess(ctx, repo, u.ID)
 	})
 }
diff --git a/modules/repository/collaborator_test.go b/modules/repository/collaborator_test.go
index ad835ae4d..6cf239d0e 100644
--- a/modules/repository/collaborator_test.go
+++ b/modules/repository/collaborator_test.go
@@ -25,7 +25,7 @@ func TestRepository_AddCollaborator(t *testing.T) {
 		repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
 		assert.NoError(t, repo.GetOwner(db.DefaultContext))
 		user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
-		assert.NoError(t, AddCollaborator(repo, user))
+		assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
 		unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID})
 	}
 	testSuccess(1, 4)
@@ -50,7 +50,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) {
 	}
 
 	// change to collaborator
-	assert.NoError(t, AddCollaborator(repo, user))
+	assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -103,7 +103,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
 	}
 
 	// change to collaborator to default write access
-	assert.NoError(t, AddCollaborator(repo, user))
+	assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -111,7 +111,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
 		assert.True(t, perm.CanWrite(unit.Type))
 	}
 
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -155,7 +155,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) {
 	}
 
 	// change to collaborator to default write access
-	assert.NoError(t, AddCollaborator(repo, user))
+	assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -163,7 +163,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) {
 		assert.True(t, perm.CanWrite(unit.Type))
 	}
 
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -217,7 +217,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
 	}
 
 	// change to collaborator to default write access
-	assert.NoError(t, AddCollaborator(repo, user))
+	assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
@@ -225,7 +225,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
 		assert.True(t, perm.CanWrite(unit.Type))
 	}
 
-	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead))
+	assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
 	perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
 	assert.NoError(t, err)
 	for _, unit := range repo.Units {
diff --git a/modules/repository/create.go b/modules/repository/create.go
index 8bee890aa..1e157ec85 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -125,10 +125,10 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
 			return fmt.Errorf("IsUserRepoAdmin: %w", err)
 		} else if !isAdmin {
 			// Make creator repo admin if it wasn't assigned automatically
-			if err = addCollaborator(ctx, repo, doer); err != nil {
-				return fmt.Errorf("addCollaborator: %w", err)
+			if err = AddCollaborator(ctx, repo, doer); err != nil {
+				return fmt.Errorf("AddCollaborator: %w", err)
 			}
-			if err = repo_model.ChangeCollaborationAccessModeCtx(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil {
+			if err = repo_model.ChangeCollaborationAccessMode(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil {
 				return fmt.Errorf("ChangeCollaborationAccessModeCtx: %w", err)
 			}
 		}
diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go
index 383193daa..202418bd2 100644
--- a/routers/api/v1/repo/collaborators.go
+++ b/routers/api/v1/repo/collaborators.go
@@ -174,13 +174,13 @@ func AddCollaborator(ctx *context.APIContext) {
 		return
 	}
 
-	if err := repo_module.AddCollaborator(ctx.Repo.Repository, collaborator); err != nil {
+	if err := repo_module.AddCollaborator(ctx, ctx.Repo.Repository, collaborator); err != nil {
 		ctx.Error(http.StatusInternalServerError, "AddCollaborator", err)
 		return
 	}
 
 	if form.Permission != nil {
-		if err := repo_model.ChangeCollaborationAccessMode(ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil {
+		if err := repo_model.ChangeCollaborationAccessMode(ctx, ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil {
 			ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err)
 			return
 		}
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index a584a7a17..909700418 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -18,7 +18,7 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/routers/api/v1/utils"
-	comment_service "code.gitea.io/gitea/services/comments"
+	issue_service "code.gitea.io/gitea/services/issue"
 )
 
 // ListIssueComments list all the comments of an issue
@@ -362,7 +362,7 @@ func CreateIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil)
+	comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err)
 		return
@@ -556,7 +556,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
 
 	oldContent := comment.Content
 	comment.Content = form.Body
-	if err := comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
+	if err := issue_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
 		ctx.Error(http.StatusInternalServerError, "UpdateComment", err)
 		return
 	}
@@ -655,7 +655,7 @@ func deleteIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
+	if err = issue_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err)
 		return
 	}
diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go
index 60ea8d1b8..2198a6a33 100644
--- a/routers/api/v1/repo/issue_comment_attachment.go
+++ b/routers/api/v1/repo/issue_comment_attachment.go
@@ -15,7 +15,7 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/services/attachment"
-	comment_service "code.gitea.io/gitea/services/comments"
+	issue_service "code.gitea.io/gitea/services/issue"
 )
 
 // GetIssueCommentAttachment gets a single attachment of the comment
@@ -196,7 +196,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) {
 		return
 	}
 
-	if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, comment.Content); err != nil {
+	if err = issue_service.UpdateComment(ctx, comment, ctx.Doer, comment.Content); err != nil {
 		ctx.ServerError("UpdateComment", err)
 		return
 	}
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index 6786d23a9..ede60a2ed 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -71,7 +71,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 
-	if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+	if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 		ctx.NotFound("Timetracker is disabled")
 		return
 	}
@@ -190,7 +190,7 @@ func AddTime(ctx *context.APIContext) {
 	}
 
 	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
-		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+		if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 			ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
 			return
 		}
@@ -271,7 +271,7 @@ func ResetIssueTime(ctx *context.APIContext) {
 	}
 
 	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
-		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+		if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 			ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
 			return
 		}
@@ -342,7 +342,7 @@ func DeleteTime(ctx *context.APIContext) {
 	}
 
 	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
-		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+		if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 			ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
 			return
 		}
@@ -410,7 +410,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
 	//   "403":
 	//     "$ref": "#/responses/forbidden"
 
-	if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+	if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 		ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
 		return
 	}
@@ -498,7 +498,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
 	//   "403":
 	//     "$ref": "#/responses/forbidden"
 
-	if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+	if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 		ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
 		return
 	}
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 3b55b496a..349040507 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -731,7 +731,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 	var units []repo_model.RepoUnit
 	var deleteUnitTypes []unit_model.Type
 
-	currHasIssues := repo.UnitEnabledCtx(ctx, unit_model.TypeIssues)
+	currHasIssues := repo.UnitEnabled(ctx, unit_model.TypeIssues)
 	newHasIssues := currHasIssues
 	if opts.HasIssues != nil {
 		newHasIssues = *opts.HasIssues
@@ -771,7 +771,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 					AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime,
 					EnableDependencies:               opts.InternalTracker.EnableIssueDependencies,
 				}
-			} else if unit, err := repo.GetUnit(unit_model.TypeIssues); err != nil {
+			} else if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err != nil {
 				// Unit type doesn't exist so we make a new config file with default values
 				config = &repo_model.IssuesConfig{
 					EnableTimetracker:                true,
@@ -798,7 +798,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 		}
 	}
 
-	currHasWiki := repo.UnitEnabledCtx(ctx, unit_model.TypeWiki)
+	currHasWiki := repo.UnitEnabled(ctx, unit_model.TypeWiki)
 	newHasWiki := currHasWiki
 	if opts.HasWiki != nil {
 		newHasWiki = *opts.HasWiki
@@ -838,7 +838,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 		}
 	}
 
-	currHasPullRequests := repo.UnitEnabledCtx(ctx, unit_model.TypePullRequests)
+	currHasPullRequests := repo.UnitEnabled(ctx, unit_model.TypePullRequests)
 	newHasPullRequests := currHasPullRequests
 	if opts.HasPullRequests != nil {
 		newHasPullRequests = *opts.HasPullRequests
@@ -848,7 +848,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 			// We do allow setting individual PR settings through the API, so
 			// we get the config settings and then set them
 			// if those settings were provided in the opts.
-			unit, err := repo.GetUnit(unit_model.TypePullRequests)
+			unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests)
 			var config *repo_model.PullRequestsConfig
 			if err != nil {
 				// Unit type doesn't exist so we make a new config file with default values
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index fb15566a4..5154c5afa 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -105,7 +105,7 @@ func Transfer(ctx *context.APIContext) {
 
 	oldFullname := ctx.Repo.Repository.FullName()
 
-	if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
+	if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
 		if models.IsErrRepoTransferInProgress(err) {
 			ctx.Error(http.StatusConflict, "StartRepositoryTransfer", err)
 			return
@@ -207,7 +207,7 @@ func RejectTransfer(ctx *context.APIContext) {
 }
 
 func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
-	repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+	repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
 	if err != nil {
 		if models.IsErrNoPendingTransfer(err) {
 			ctx.NotFound()
@@ -216,7 +216,7 @@ func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
 		return err
 	}
 
-	if err := repoTransfer.LoadAttributes(); err != nil {
+	if err := repoTransfer.LoadAttributes(ctx); err != nil {
 		return err
 	}
 
@@ -226,7 +226,7 @@ func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
 	}
 
 	if accept {
-		return repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams)
+		return repo_service.TransferOwnership(ctx, repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams)
 	}
 
 	return models.CancelRepositoryTransfer(ctx.Repo.Repository)
diff --git a/routers/private/serv.go b/routers/private/serv.go
index a86f6c057..17f966e3e 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -382,7 +382,7 @@ func ServCommand(ctx *context.PrivateContext) {
 
 	if results.IsWiki {
 		// Ensure the wiki is enabled before we allow access to it
-		if _, err := repo.GetUnit(unit.TypeWiki); err != nil {
+		if _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
 			if repo_model.IsErrUnitTypeNotExist(err) {
 				ctx.JSON(http.StatusForbidden, private.ErrServCommand{
 					Results: results,
diff --git a/routers/web/repo/cherry_pick.go b/routers/web/repo/cherry_pick.go
index 2056ad1b3..48bc6959e 100644
--- a/routers/web/repo/cherry_pick.go
+++ b/routers/web/repo/cherry_pick.go
@@ -177,7 +177,7 @@ func CherryPickPost(ctx *context.Context) {
 		}
 	}
 
-	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) {
+	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
 	} else {
 		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName))
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index b2d8f8645..d95eeaecc 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -577,7 +577,7 @@ func PrepareCompareDiff(
 	if (headCommitID == ci.CompareInfo.MergeBase && !ci.DirectComparison) ||
 		headCommitID == ci.CompareInfo.BaseCommitID {
 		ctx.Data["IsNothingToCompare"] = true
-		if unit, err := repo.GetUnit(unit.TypePullRequests); err == nil {
+		if unit, err := repo.GetUnit(ctx, unit.TypePullRequests); err == nil {
 			config := unit.PullRequestsConfig()
 
 			if !config.AutodetectManualMerge {
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index 7b064adfc..e5ba4ad2c 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -328,7 +328,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
 		}
 	}
 
-	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) {
+	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
 	} else {
 		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
@@ -514,7 +514,7 @@ func DeleteFilePost(ctx *context.Context) {
 	}
 
 	ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
-	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) {
+	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
 	} else {
 		treePath := path.Dir(ctx.Repo.TreePath)
@@ -717,7 +717,7 @@ func UploadFilePost(ctx *context.Context) {
 		return
 	}
 
-	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) {
+	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
 	} else {
 		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go
index d2450066e..b2a49e3e3 100644
--- a/routers/web/repo/http.go
+++ b/routers/web/repo/http.go
@@ -258,7 +258,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
 
 	if isWiki {
 		// Ensure the wiki is enabled before we allow access to it
-		if _, err := repo.GetUnit(unit.TypeWiki); err != nil {
+		if _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
 			if repo_model.IsErrUnitTypeNotExist(err) {
 				ctx.PlainText(http.StatusForbidden, "repository wiki is disabled")
 				return
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index b11cc58e4..d315525da 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -47,7 +47,6 @@ import (
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/routers/utils"
 	asymkey_service "code.gitea.io/gitea/services/asymkey"
-	comment_service "code.gitea.io/gitea/services/comments"
 	"code.gitea.io/gitea/services/forms"
 	issue_service "code.gitea.io/gitea/services/issue"
 	pull_service "code.gitea.io/gitea/services/pull"
@@ -114,7 +113,7 @@ func MustEnableIssues(ctx *context.Context) {
 		return
 	}
 
-	unit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalTracker)
+	unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalTracker)
 	if err == nil {
 		ctx.Redirect(unit.ExternalTrackerConfig().ExternalTrackerURL)
 		return
@@ -1174,7 +1173,7 @@ func getBranchData(ctx *context.Context, issue *issues_model.Issue) {
 func ViewIssue(ctx *context.Context) {
 	if ctx.Params(":type") == "issues" {
 		// If issue was requested we check if repo has external tracker and redirect
-		extIssueUnit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalTracker)
+		extIssueUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalTracker)
 		if err == nil && extIssueUnit != nil {
 			if extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == markup.IssueNameStyleNumeric || extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == "" {
 				metas := ctx.Repo.Repository.ComposeMetas()
@@ -1375,7 +1374,7 @@ func ViewIssue(ctx *context.Context) {
 		comment      *issues_model.Comment
 		participants = make([]*user_model.User, 1, 10)
 	)
-	if ctx.Repo.Repository.IsTimetrackerEnabled() {
+	if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 		if ctx.IsSigned {
 			// Deal with the stopwatch
 			ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx.Doer.ID, issue.ID)
@@ -1636,7 +1635,7 @@ func ViewIssue(ctx *context.Context) {
 			}
 		}
 
-		prUnit, err := repo.GetUnit(unit.TypePullRequests)
+		prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests)
 		if err != nil {
 			ctx.ServerError("GetUnit", err)
 			return
@@ -2709,7 +2708,7 @@ func NewComment(ctx *context.Context) {
 		return
 	}
 
-	comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
+	comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
 	if err != nil {
 		ctx.ServerError("CreateIssueComment", err)
 		return
@@ -2749,8 +2748,7 @@ func UpdateCommentContent(ctx *context.Context) {
 		})
 		return
 	}
-
-	if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
+	if err = issue_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
 		ctx.ServerError("UpdateComment", err)
 		return
 	}
@@ -2806,7 +2804,7 @@ func DeleteComment(ctx *context.Context) {
 		return
 	}
 
-	if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
+	if err = issue_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
 		ctx.ServerError("DeleteComment", err)
 		return
 	}
diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go
index 042715639..d712df100 100644
--- a/routers/web/repo/milestone.go
+++ b/routers/web/repo/milestone.go
@@ -73,7 +73,7 @@ func Milestones(ctx *context.Context) {
 		ctx.ServerError("GetMilestones", err)
 		return
 	}
-	if ctx.Repo.Repository.IsTimetrackerEnabled() {
+	if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
 		if err := miles.LoadTotalTrackedTimes(); err != nil {
 			ctx.ServerError("LoadTotalTrackedTimes", err)
 			return
diff --git a/routers/web/repo/patch.go b/routers/web/repo/patch.go
index 27199ba41..12b26f38e 100644
--- a/routers/web/repo/patch.go
+++ b/routers/web/repo/patch.go
@@ -108,7 +108,7 @@ func NewDiffPatchPost(ctx *context.Context) {
 		}
 	}
 
-	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) {
+	if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
 	} else {
 		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 73f091634..75cd290b8 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -196,7 +196,7 @@ func DeleteProject(ctx *context.Context) {
 		return
 	}
 
-	if err := project_model.DeleteProjectByID(p.ID); err != nil {
+	if err := project_model.DeleteProjectByID(ctx, p.ID); err != nil {
 		ctx.Flash.Error("DeleteProjectByID: " + err.Error())
 	} else {
 		ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success"))
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index 0aa1fde8d..2047a1cfb 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -135,7 +135,7 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
 		return
 	}
 
-	count, err := repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, opts)
+	count, err := repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, opts)
 	if err != nil {
 		ctx.ServerError("GetReleaseCountByRepoID", err)
 		return
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index c57564d33..8856ee662 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -314,12 +314,12 @@ func Action(ctx *context.Context) {
 }
 
 func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
-	repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+	repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
 	if err != nil {
 		return err
 	}
 
-	if err := repoTransfer.LoadAttributes(); err != nil {
+	if err := repoTransfer.LoadAttributes(ctx); err != nil {
 		return err
 	}
 
@@ -333,7 +333,7 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
 			ctx.Repo.GitRepo = nil
 		}
 
-		if err := repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil {
+		if err := repo_service.TransferOwnership(ctx, repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil {
 			return err
 		}
 		ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success"))
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 9e47d0bb1..8ba5fc9e3 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -689,7 +689,7 @@ func SettingsPost(ctx *context.Context) {
 			ctx.Repo.GitRepo = nil
 		}
 
-		if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, repo, nil); err != nil {
+		if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil {
 			if repo_model.IsErrRepoAlreadyExist(err) {
 				ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
 			} else if models.IsErrRepoTransferInProgress(err) {
@@ -711,7 +711,7 @@ func SettingsPost(ctx *context.Context) {
 			return
 		}
 
-		repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+		repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
 		if err != nil {
 			if models.IsErrNoPendingTransfer(err) {
 				ctx.Flash.Error("repo.settings.transfer_abort_invalid")
@@ -723,7 +723,7 @@ func SettingsPost(ctx *context.Context) {
 			return
 		}
 
-		if err := repoTransfer.LoadAttributes(); err != nil {
+		if err := repoTransfer.LoadAttributes(ctx); err != nil {
 			ctx.ServerError("LoadRecipient", err)
 			return
 		}
@@ -929,7 +929,7 @@ func CollaborationPost(ctx *context.Context) {
 		}
 	}
 
-	if err = repo_module.AddCollaborator(ctx.Repo.Repository, u); err != nil {
+	if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
 		ctx.ServerError("AddCollaborator", err)
 		return
 	}
@@ -945,6 +945,7 @@ func CollaborationPost(ctx *context.Context) {
 // ChangeCollaborationAccessMode response for changing access of a collaboration
 func ChangeCollaborationAccessMode(ctx *context.Context) {
 	if err := repo_model.ChangeCollaborationAccessMode(
+		ctx,
 		ctx.Repo.Repository,
 		ctx.FormInt64("uid"),
 		perm.AccessMode(ctx.FormInt("mode"))); err != nil {
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 885f84543..b50a4be80 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -59,7 +59,7 @@ func MustEnableWiki(ctx *context.Context) {
 		return
 	}
 
-	unit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalWiki)
+	unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
 	if err == nil {
 		ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
 		return
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index fc4c919de..36d9d4f01 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -231,7 +231,7 @@ func Milestones(ctx *context.Context) {
 			return
 		}
 
-		if milestones[i].Repo.IsTimetrackerEnabled() {
+		if milestones[i].Repo.IsTimetrackerEnabled(ctx) {
 			err := milestones[i].LoadTotalTrackedTime()
 			if err != nil {
 				ctx.ServerError("LoadTotalTrackedTime", err)
diff --git a/services/agit/agit.go b/services/agit/agit.go
index b4f443879..b61cb6f3f 100644
--- a/services/agit/agit.go
+++ b/services/agit/agit.go
@@ -206,7 +206,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
 		if err != nil {
 			return nil, fmt.Errorf("Failed to load pull issue. Error: %w", err)
 		}
-		comment, err := issues_model.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i])
+		comment, err := pull_service.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i])
 		if err == nil && comment != nil {
 			notification.NotifyPullRequestPushCommits(ctx, pusher, pr, comment)
 		}
diff --git a/services/comments/comments.go b/services/issue/comments.go
similarity index 63%
rename from services/comments/comments.go
rename to services/issue/comments.go
index 21640d90b..46c0daf70 100644
--- a/services/comments/comments.go
+++ b/services/issue/comments.go
@@ -1,10 +1,11 @@
 // Copyright 2019 The Gitea Authors. All rights reserved.
 // SPDX-License-Identifier: MIT
 
-package comments
+package issue
 
 import (
 	"context"
+	"fmt"
 
 	"code.gitea.io/gitea/models/db"
 	issues_model "code.gitea.io/gitea/models/issues"
@@ -14,9 +15,58 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 )
 
+// CreateComment creates comment of issue or commit.
+func CreateComment(opts *issues_model.CreateCommentOptions) (comment *issues_model.Comment, err error) {
+	ctx, committer, err := db.TxContext(db.DefaultContext)
+	if err != nil {
+		return nil, err
+	}
+	defer committer.Close()
+
+	comment, err = issues_model.CreateComment(ctx, opts)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = committer.Commit(); err != nil {
+		return nil, err
+	}
+
+	return comment, nil
+}
+
+// CreateRefComment creates a commit reference comment to issue.
+func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error {
+	if len(commitSHA) == 0 {
+		return fmt.Errorf("cannot create reference with empty commit SHA")
+	}
+
+	// Check if same reference from same commit has already existed.
+	has, err := db.GetEngine(db.DefaultContext).Get(&issues_model.Comment{
+		Type:      issues_model.CommentTypeCommitRef,
+		IssueID:   issue.ID,
+		CommitSHA: commitSHA,
+	})
+	if err != nil {
+		return fmt.Errorf("check reference comment: %w", err)
+	} else if has {
+		return nil
+	}
+
+	_, err = CreateComment(&issues_model.CreateCommentOptions{
+		Type:      issues_model.CommentTypeCommitRef,
+		Doer:      doer,
+		Repo:      repo,
+		Issue:     issue,
+		CommitSHA: commitSHA,
+		Content:   content,
+	})
+	return err
+}
+
 // CreateIssueComment creates a plain issue comment.
 func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) {
-	comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{
+	comment, err := CreateComment(&issues_model.CreateCommentOptions{
 		Type:        issues_model.CommentTypeComment,
 		Doer:        doer,
 		Repo:        repo,
diff --git a/services/issue/commit.go b/services/issue/commit.go
index efbcd639a..db31fc66b 100644
--- a/services/issue/commit.go
+++ b/services/issue/commit.go
@@ -158,7 +158,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
 			}
 
 			message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0]))
-			if err = issues_model.CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
+			if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
 				return err
 			}
 
diff --git a/services/issue/milestone.go b/services/issue/milestone.go
index 6019a28a9..a9be8bd88 100644
--- a/services/issue/milestone.go
+++ b/services/issue/milestone.go
@@ -54,7 +54,7 @@ func changeMilestoneAssign(ctx context.Context, doer *user_model.User, issue *is
 			OldMilestoneID: oldMilestoneID,
 			MilestoneID:    issue.MilestoneID,
 		}
-		if _, err := issues_model.CreateCommentCtx(ctx, opts); err != nil {
+		if _, err := issues_model.CreateComment(ctx, opts); err != nil {
 			return err
 		}
 	}
diff --git a/services/pull/check.go b/services/pull/check.go
index 4f720f0a0..ed4b18107 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -236,7 +236,7 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool {
 		return false
 	}
 
-	if unit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests); err == nil {
+	if unit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests); err == nil {
 		config := unit.PullRequestsConfig()
 		if !config.AutodetectManualMerge {
 			return false
diff --git a/services/pull/comment.go b/services/pull/comment.go
new file mode 100644
index 000000000..068aca6cd
--- /dev/null
+++ b/services/pull/comment.go
@@ -0,0 +1,162 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+	"context"
+
+	issues_model "code.gitea.io/gitea/models/issues"
+	repo_model "code.gitea.io/gitea/models/repo"
+	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/json"
+	issue_service "code.gitea.io/gitea/services/issue"
+)
+
+type commitBranchCheckItem struct {
+	Commit  *git.Commit
+	Checked bool
+}
+
+func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
+	if startCommit.ID.String() == endCommitID {
+		return nil
+	}
+
+	checkStack := make([]string, 0, 10)
+	checkStack = append(checkStack, startCommit.ID.String())
+
+	for len(checkStack) > 0 {
+		commitID := checkStack[0]
+		checkStack = checkStack[1:]
+
+		item, ok := commitList[commitID]
+		if !ok {
+			continue
+		}
+
+		if item.Commit.ID.String() == endCommitID {
+			continue
+		}
+
+		if err := item.Commit.LoadBranchName(); err != nil {
+			return err
+		}
+
+		if item.Commit.Branch == baseBranch {
+			continue
+		}
+
+		if item.Checked {
+			continue
+		}
+
+		item.Checked = true
+
+		parentNum := item.Commit.ParentCount()
+		for i := 0; i < parentNum; i++ {
+			parentCommit, err := item.Commit.Parent(i)
+			if err != nil {
+				return err
+			}
+			checkStack = append(checkStack, parentCommit.ID.String())
+		}
+	}
+	return nil
+}
+
+// getCommitIDsFromRepo 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(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) {
+	repoPath := repo.RepoPath()
+	gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath)
+	if err != nil {
+		return nil, false, err
+	}
+	defer closer.Close()
+
+	oldCommit, err := gitRepo.GetCommit(oldCommitID)
+	if err != nil {
+		return nil, false, err
+	}
+
+	if err = oldCommit.LoadBranchName(); err != nil {
+		return nil, false, err
+	}
+
+	if len(oldCommit.Branch) == 0 {
+		commitIDs = make([]string, 2)
+		commitIDs[0] = oldCommitID
+		commitIDs[1] = newCommitID
+
+		return commitIDs, true, err
+	}
+
+	newCommit, err := gitRepo.GetCommit(newCommitID)
+	if err != nil {
+		return nil, false, err
+	}
+
+	commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
+	if err != nil {
+		return nil, false, err
+	}
+
+	commitIDs = make([]string, 0, len(commits))
+	commitChecks := make(map[string]*commitBranchCheckItem)
+
+	for _, commit := range commits {
+		commitChecks[commit.ID.String()] = &commitBranchCheckItem{
+			Commit:  commit,
+			Checked: false,
+		}
+	}
+
+	if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
+		return
+	}
+
+	for i := len(commits) - 1; i >= 0; i-- {
+		commitID := commits[i].ID.String()
+		if item, ok := commitChecks[commitID]; ok && item.Checked {
+			commitIDs = append(commitIDs, commitID)
+		}
+	}
+
+	return commitIDs, isForcePush, err
+}
+
+// CreatePushPullComment create push code to pull base comment
+func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (comment *issues_model.Comment, err error) {
+	if pr.HasMerged || oldCommitID == "" || newCommitID == "" {
+		return nil, nil
+	}
+
+	ops := &issues_model.CreateCommentOptions{
+		Type: issues_model.CommentTypePullRequestPush,
+		Doer: pusher,
+		Repo: pr.BaseRepo,
+	}
+
+	var data issues_model.PushActionContent
+
+	data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
+	if err != nil {
+		return nil, err
+	}
+
+	ops.Issue = pr.Issue
+
+	dataJSON, err := json.Marshal(data)
+	if err != nil {
+		return nil, err
+	}
+
+	ops.Content = string(dataJSON)
+
+	comment, err = issue_service.CreateComment(ops)
+
+	return comment, err
+}
diff --git a/services/pull/merge.go b/services/pull/merge.go
index 9270fb8cb..1c42c1c17 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -54,7 +54,7 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr
 		return "", err
 	}
 
-	isExternalTracker := pr.BaseRepo.UnitEnabled(unit.TypeExternalTracker)
+	isExternalTracker := pr.BaseRepo.UnitEnabled(ctx, unit.TypeExternalTracker)
 	issueReference := "#"
 	if isExternalTracker {
 		issueReference = "!"
@@ -145,11 +145,11 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
 	defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
 
 	// Removing an auto merge pull and ignore if not exist
-	if err := pull_model.DeleteScheduledAutoMerge(db.DefaultContext, pr.ID); err != nil && !db.IsErrNotExist(err) {
+	if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) {
 		return err
 	}
 
-	prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests)
+	prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
 	if err != nil {
 		log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err)
 		return err
@@ -828,7 +828,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit
 	defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
 
 	if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
-		prUnit, err := pr.BaseRepo.GetUnitCtx(ctx, unit.TypePullRequests)
+		prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
 		if err != nil {
 			return err
 		}
diff --git a/services/pull/patch.go b/services/pull/patch.go
index 2d495a3d7..809b75e6b 100644
--- a/services/pull/patch.go
+++ b/services/pull/patch.go
@@ -354,7 +354,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
 	}
 
 	// 5. Now get the pull request configuration to check if we need to ignore whitespace
-	prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests)
+	prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
 	if err != nil {
 		return false, err
 	}
diff --git a/services/pull/pull.go b/services/pull/pull.go
index fd907491d..afb0fa244 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -123,7 +123,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu
 			Content:     string(dataJSON),
 		}
 
-		_, _ = issues_model.CreateComment(ops)
+		_, _ = issue_service.CreateComment(ops)
 	}
 
 	return nil
@@ -222,7 +222,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
 		OldRef: oldBranch,
 		NewRef: targetBranch,
 	}
-	if _, err = issues_model.CreateComment(options); err != nil {
+	if _, err = issue_service.CreateComment(options); err != nil {
 		return fmt.Errorf("CreateChangeTargetBranchComment: %w", err)
 	}
 
@@ -317,7 +317,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
 			}
 
 			AddToTaskQueue(pr)
-			comment, err := issues_model.CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
+			comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
 			if err == nil && comment != nil {
 				notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment)
 			}
diff --git a/services/pull/review.go b/services/pull/review.go
index 1f2bc77e2..67a10d7aa 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -20,6 +20,7 @@ import (
 	"code.gitea.io/gitea/modules/notification"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/util"
+	issue_service "code.gitea.io/gitea/services/issue"
 )
 
 // CreateCodeComment creates a comment on the code line
@@ -202,7 +203,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo
 			return nil, err
 		}
 	}
-	return issues_model.CreateComment(&issues_model.CreateCommentOptions{
+	return issue_service.CreateComment(&issues_model.CreateCommentOptions{
 		Type:        issues_model.CommentTypeCode,
 		Doer:        doer,
 		Repo:        repo,
@@ -322,7 +323,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
 		return
 	}
 
-	comment, err = issues_model.CreateComment(&issues_model.CreateCommentOptions{
+	comment, err = issue_service.CreateComment(&issues_model.CreateCommentOptions{
 		Doer:     doer,
 		Content:  message,
 		Type:     issues_model.CommentTypeDismissReview,
diff --git a/services/pull/update.go b/services/pull/update.go
index bd6a37b27..e09dbf624 100644
--- a/services/pull/update.go
+++ b/services/pull/update.go
@@ -106,7 +106,7 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
 
 	// can't do rebase on protected branch because need force push
 	if pr.ProtectedBranch == nil {
-		prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests)
+		prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
 		if err != nil {
 			log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err)
 			return false, false, err
diff --git a/services/repository/repository.go b/services/repository/repository.go
index 41fae4b4c..3c3e7e82c 100644
--- a/services/repository/repository.go
+++ b/services/repository/repository.go
@@ -58,7 +58,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
 func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
 	if !authUser.IsAdmin {
 		if owner.IsOrganization() {
-			if ok, err := organization.CanCreateOrgRepo(owner.ID, authUser.ID); err != nil {
+			if ok, err := organization.CanCreateOrgRepo(db.DefaultContext, owner.ID, authUser.ID); err != nil {
 				return nil, err
 			} else if !ok {
 				return nil, fmt.Errorf("cannot push-create repository for org")
diff --git a/services/repository/transfer.go b/services/repository/transfer.go
index 9fba9c44e..f4afb7e2d 100644
--- a/services/repository/transfer.go
+++ b/services/repository/transfer.go
@@ -4,6 +4,7 @@
 package repository
 
 import (
+	"context"
 	"fmt"
 
 	"code.gitea.io/gitea/models"
@@ -24,8 +25,8 @@ import (
 var repoWorkingPool = sync.NewExclusivePool()
 
 // TransferOwnership transfers all corresponding setting from old user to new one.
-func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
-	if err := repo.GetOwner(db.DefaultContext); err != nil {
+func TransferOwnership(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
+	if err := repo.GetOwner(ctx); err != nil {
 		return err
 	}
 	for _, team := range teams {
@@ -43,18 +44,18 @@ func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Reposit
 	}
 	repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
 
-	newRepo, err := repo_model.GetRepositoryByID(db.DefaultContext, repo.ID)
+	newRepo, err := repo_model.GetRepositoryByID(ctx, repo.ID)
 	if err != nil {
 		return err
 	}
 
 	for _, team := range teams {
-		if err := models.AddRepository(db.DefaultContext, team, newRepo); err != nil {
+		if err := models.AddRepository(ctx, team, newRepo); err != nil {
 			return err
 		}
 	}
 
-	notification.NotifyTransferRepository(db.DefaultContext, doer, repo, oldOwner.Name)
+	notification.NotifyTransferRepository(ctx, doer, repo, oldOwner.Name)
 
 	return nil
 }
@@ -84,49 +85,49 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne
 
 // StartRepositoryTransfer transfer a repo from one owner to a new one.
 // it make repository into pending transfer state, if doer can not create repo for new owner.
-func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
+func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
 	if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
 		return err
 	}
 
 	// Admin is always allowed to transfer || user transfer repo back to his account
 	if doer.IsAdmin || doer.ID == newOwner.ID {
-		return TransferOwnership(doer, newOwner, repo, teams)
+		return TransferOwnership(ctx, doer, newOwner, repo, teams)
 	}
 
 	// If new owner is an org and user can create repos he can transfer directly too
 	if newOwner.IsOrganization() {
-		allowed, err := organization.CanCreateOrgRepo(newOwner.ID, doer.ID)
+		allowed, err := organization.CanCreateOrgRepo(ctx, newOwner.ID, doer.ID)
 		if err != nil {
 			return err
 		}
 		if allowed {
-			return TransferOwnership(doer, newOwner, repo, teams)
+			return TransferOwnership(ctx, doer, newOwner, repo, teams)
 		}
 	}
 
 	// In case the new owner would not have sufficient access to the repo, give access rights for read
-	hasAccess, err := access_model.HasAccess(db.DefaultContext, newOwner.ID, repo)
+	hasAccess, err := access_model.HasAccess(ctx, newOwner.ID, repo)
 	if err != nil {
 		return err
 	}
 	if !hasAccess {
-		if err := repo_module.AddCollaborator(repo, newOwner); err != nil {
+		if err := repo_module.AddCollaborator(ctx, repo, newOwner); err != nil {
 			return err
 		}
-		if err := repo_model.ChangeCollaborationAccessMode(repo, newOwner.ID, perm.AccessModeRead); err != nil {
+		if err := repo_model.ChangeCollaborationAccessMode(ctx, repo, newOwner.ID, perm.AccessModeRead); err != nil {
 			return err
 		}
 	}
 
 	// Make repo as pending for transfer
 	repo.Status = repo_model.RepositoryPendingTransfer
-	if err := models.CreatePendingRepositoryTransfer(doer, newOwner, repo.ID, teams); err != nil {
+	if err := models.CreatePendingRepositoryTransfer(ctx, doer, newOwner, repo.ID, teams); err != nil {
 		return err
 	}
 
 	// notify users who are able to accept / reject transfer
-	notification.NotifyRepoPendingTransfer(db.DefaultContext, doer, newOwner, repo)
+	notification.NotifyRepoPendingTransfer(ctx, doer, newOwner, repo)
 
 	return nil
 }
diff --git a/services/repository/transfer_test.go b/services/repository/transfer_test.go
index 2bbc5abbd..1299e66be 100644
--- a/services/repository/transfer_test.go
+++ b/services/repository/transfer_test.go
@@ -37,7 +37,7 @@ func TestTransferOwnership(t *testing.T) {
 	doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
 	repo.Owner = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
-	assert.NoError(t, TransferOwnership(doer, doer, repo, nil))
+	assert.NoError(t, TransferOwnership(db.DefaultContext, doer, doer, repo, nil))
 
 	transferredRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
 	assert.EqualValues(t, 2, transferredRepo.OwnerID)
@@ -70,7 +70,7 @@ func TestStartRepositoryTransferSetPermission(t *testing.T) {
 	assert.NoError(t, err)
 	assert.False(t, hasAccess)
 
-	assert.NoError(t, StartRepositoryTransfer(doer, recipient, repo, nil))
+	assert.NoError(t, StartRepositoryTransfer(db.DefaultContext, doer, recipient, repo, nil))
 
 	hasAccess, err = access_model.HasAccess(db.DefaultContext, recipient.ID, repo)
 	assert.NoError(t, err)
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index 982cfb280..de33c6c55 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -177,7 +177,7 @@
 					<dt>{{.locale.Tr "admin.config.default_enable_timetracking"}}</dt>
 					<dd>{{if .Service.DefaultEnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
 					<dt>{{.locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}</dt>
-					<dd>{{if .Service.DefaultAllowOnlyContributorsToTrackTime}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
+					<dd>{{if .Service.DefaultAllowOnlyContributorsToTrackTime $.Context}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
 				{{end}}
 				<dt>{{.locale.Tr "admin.config.default_visibility_organization"}}</dt>
 				<dd>{{.Service.DefaultOrgVisibility}}</dd>
diff --git a/templates/org/team/new.tmpl b/templates/org/team/new.tmpl
index f6786f3d8..10b5abda3 100644
--- a/templates/org/team/new.tmpl
+++ b/templates/org/team/new.tmpl
@@ -99,17 +99,17 @@
 													</td>
 													<td class="center aligned">
 														<div class="ui radio checkbox">
-															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="0"{{if or ($unit.Type.UnitGlobalDisabled) (eq ($.Team.UnitAccessMode $unit.Type) 0)}} checked{{end}}>
+															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="0"{{if or ($unit.Type.UnitGlobalDisabled) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 0)}} checked{{end}}>
 														</div>
 													</td>
 													<td class="center aligned">
 														<div class="ui radio checkbox">
-															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
+															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
 														</div>
 													</td>
 													<td class="center aligned">
 														<div class="ui radio checkbox">
-															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="2"{{if (eq ($.Team.UnitAccessMode $unit.Type) 2)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
+															<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="2"{{if (eq ($.Team.UnitAccessMode $.Context $unit.Type) 2)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
 														</div>
 													</td>
 												</tr>
@@ -121,7 +121,7 @@
 									{{if lt $unit.MaxPerm 2}}
 										<div {{if $unit.Type.UnitGlobalDisabled}}class="field tooltip" data-content="{{$.locale.Tr "repo.unit_disabled"}}"{{else}}class="field"{{end}}>
 											<div class="ui checkbox">
-												<input type="checkbox" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
+												<input type="checkbox" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
 												<label>{{$.locale.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{$.locale.Tr "org.team_unit_disabled"}}{{end}}</label>
 												<span class="help">{{$.locale.Tr $unit.DescKey}}</span>
 											</div>
diff --git a/templates/org/team/sidebar.tmpl b/templates/org/team/sidebar.tmpl
index 5d952b501..ab118a7e2 100644
--- a/templates/org/team/sidebar.tmpl
+++ b/templates/org/team/sidebar.tmpl
@@ -61,11 +61,11 @@
 								{{if and (lt $unit.MaxPerm 2) (not $unit.Type.UnitGlobalDisabled)}}
 									<tr>
 										<td><strong>{{$.locale.Tr $unit.NameKey}}</strong></td>
-										<td>{{if eq ($.Team.UnitAccessMode $unit.Type) 0 -}}
+										<td>{{if eq ($.Team.UnitAccessMode $.Context $unit.Type) 0 -}}
 										{{$.locale.Tr "org.teams.none_access"}}
-										{{- else if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1) -}}
+										{{- else if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1) -}}
 										{{$.locale.Tr "org.teams.read_access"}}
-										{{- else if eq ($.Team.UnitAccessMode $unit.Type) 2 -}}
+										{{- else if eq ($.Team.UnitAccessMode $.Context $unit.Type) 2 -}}
 										{{$.locale.Tr "org.teams.write_access"}}
 										{{- end}}</td>
 									</tr>
diff --git a/templates/repo/editor/commit_form.tmpl b/templates/repo/editor/commit_form.tmpl
index 95fcf2b85..8700f7740 100644
--- a/templates/repo/editor/commit_form.tmpl
+++ b/templates/repo/editor/commit_form.tmpl
@@ -40,8 +40,8 @@
 				</div>
 			</div>
 			<div class="field">
-				{{$pullRequestEnabled := .Repository.UnitEnabled $.UnitTypePullRequests}}
-				{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
+				{{$pullRequestEnabled := .Repository.UnitEnabled $.Context $.UnitTypePullRequests}}
+				{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}}
 				<div class="ui radio checkbox">
 					{{if $pullRequestEnabled}}
 						<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{.locale.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
diff --git a/templates/repo/graph/commits.tmpl b/templates/repo/graph/commits.tmpl
index 357c99b2b..fc4b1a1ea 100644
--- a/templates/repo/graph/commits.tmpl
+++ b/templates/repo/graph/commits.tmpl
@@ -37,7 +37,7 @@
 							{{if eq $refGroup "pull"}}
 								{{if or (not $.HidePRRefs) (containGeneric $.SelectedBranches .Name)}}
 									<!-- it's intended to use issues not pulls, if it's a pull you will get redirected -->
-									<a class="ui labelled icon button basic tiny mr-2" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
+									<a class="ui labelled icon button basic tiny mr-2" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
 										{{svg "octicon-git-pull-request" 16 "mr-2"}}#{{.ShortName}}
 									</a>
 								{{end}}
diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl
index c706e0077..4da91e424 100644
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -208,7 +208,7 @@
 				{{end}}
 
 				{{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}}
-					<a class="{{if .PageIsWiki}}active {{end}}item" href="{{.RepoLink}}/wiki" {{if and (.Permission.CanRead $.UnitTypeExternalWiki) (not (HasPrefix ((.Repository.MustGetUnit $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL) (.Repository.HTMLURL)))}} target="_blank" rel="noopener noreferrer" {{end}}>
+					<a class="{{if .PageIsWiki}}active {{end}}item" href="{{.RepoLink}}/wiki" {{if and (.Permission.CanRead $.UnitTypeExternalWiki) (not (HasPrefix ((.Repository.MustGetUnit $.Context $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL) (.Repository.HTMLURL)))}} target="_blank" rel="noopener noreferrer" {{end}}>
 						{{svg "octicon-book"}} {{.locale.Tr "repo.wiki"}}
 					</a>
 				{{end}}
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index 9e0909064..d68f3e541 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -330,7 +330,7 @@
 				{{end}}
 
 				{{if .AllowMerge}} {{/* user is allowed to merge */}}
-					{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
+					{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}}
 					{{$approvers := .Issue.PullRequest.GetApprovers}}
 					{{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowRebaseMerge $prUnit.PullRequestsConfig.AllowSquash}}
 						{{$hasPendingPullRequestMergeTip := ""}}
diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl
index af648387d..63b99136a 100644
--- a/templates/repo/issue/view_content/sidebar.tmpl
+++ b/templates/repo/issue/view_content/sidebar.tmpl
@@ -337,7 +337,7 @@
 				</div>
 			</div>
 		{{end}}
-		{{if .Repository.IsTimetrackerEnabled}}
+		{{if .Repository.IsTimetrackerEnabled $.Context}}
 			{{if and .CanUseTimetracker (not .Repository.IsArchived)}}
 				<div class="ui divider"></div>
 				<div class="ui timetrack">
@@ -444,7 +444,7 @@
 			{{end}}
 		</div>
 
-		{{if .Repository.IsDependenciesEnabled}}
+		{{if .Repository.IsDependenciesEnabled $.Context}}
 			<div class="ui divider"></div>
 
 			<div class="ui depending">
diff --git a/templates/repo/settings/collaboration.tmpl b/templates/repo/settings/collaboration.tmpl
index 342b260db..2f932b4c3 100644
--- a/templates/repo/settings/collaboration.tmpl
+++ b/templates/repo/settings/collaboration.tmpl
@@ -74,7 +74,7 @@
 						{{if or (eq .AccessMode 1) (eq .AccessMode 2)}}
 							{{$first := true}}
 							<div class="description">
-							Sections: {{range $u, $unit := $.Units}}{{if and ($.Repo.UnitEnabled $unit.Type) ($team.UnitEnabled $unit.Type)}}{{if $first}}{{$first = false}}{{else}}, {{end}}{{$.locale.Tr $unit.NameKey}}{{end}}{{end}} {{if $first}}None{{end}}
+							Sections: {{range $u, $unit := $.Units}}{{if and ($.Repo.UnitEnabled $.Context $unit.Type) ($team.UnitEnabled $.Context $unit.Type)}}{{if $first}}{{$first = false}}{{else}}, {{end}}{{$.locale.Tr $unit.NameKey}}{{end}}{{end}} {{if $first}}None{{end}}
 							</div>
 						{{end}}
 					</div>
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl
index 3c5996e90..aa79f7561 100644
--- a/templates/repo/settings/options.tmpl
+++ b/templates/repo/settings/options.tmpl
@@ -249,7 +249,7 @@
 				{{.CsrfTokenHtml}}
 				<input type="hidden" name="action" value="advanced">
 
-				{{$isWikiEnabled := or (.Repository.UnitEnabled $.UnitTypeWiki) (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}
+				{{$isWikiEnabled := or (.Repository.UnitEnabled $.Context $.UnitTypeWiki) (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}}
 				<div class="inline field">
 					<label>{{.locale.Tr "repo.wiki"}}</label>
 					{{if and (.UnitTypeWiki.UnitGlobalDisabled) (.UnitTypeExternalWiki.UnitGlobalDisabled)}}
@@ -268,7 +268,7 @@
 						{{else}}
 						<div class="ui radio checkbox">
 						{{end}}
-							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}checked{{end}}/>
+							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}}checked{{end}}/>
 							<label>{{.locale.Tr "repo.settings.use_internal_wiki"}}</label>
 						</div>
 					</div>
@@ -278,20 +278,20 @@
 						{{else}}
 						<div class="ui radio checkbox">
 						{{end}}
-							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.UnitTypeExternalWiki}}checked{{end}}/>
+							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.Context $.UnitTypeExternalWiki}}checked{{end}}/>
 							<label>{{.locale.Tr "repo.settings.use_external_wiki"}}</label>
 						</div>
 					</div>
-					<div class="field {{if not (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box">
+					<div class="field {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box">
 						<label for="external_wiki_url">{{.locale.Tr "repo.settings.external_wiki_url"}}</label>
-						<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}">
+						<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}">
 						<p class="help">{{.locale.Tr "repo.settings.external_wiki_url_desc"}}</p>
 					</div>
 				</div>
 
 				<div class="ui divider"></div>
 
-				{{$isIssuesEnabled := or (.Repository.UnitEnabled $.UnitTypeIssues) (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}
+				{{$isIssuesEnabled := or (.Repository.UnitEnabled $.Context $.UnitTypeIssues) (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}
 				<div class="inline field">
 					<label>{{.locale.Tr "repo.issues"}}</label>
 					{{if and (.UnitTypeIssues.UnitGlobalDisabled) (.UnitTypeExternalTracker.UnitGlobalDisabled)}}
@@ -310,28 +310,28 @@
 						{{else}}
 						<div class="ui radio checkbox">
 						{{end}}
-							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}checked{{end}}/>
+							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}checked{{end}}/>
 							<label>{{.locale.Tr "repo.settings.use_internal_issue_tracker"}}</label>
 						</div>
 					</div>
-					<div class="field {{if (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}disabled{{end}}" id="internal_issue_box">
+					<div class="field {{if (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}disabled{{end}}" id="internal_issue_box">
 						{{if .Repository.CanEnableTimetracker}}
 							<div class="field">
 								<div class="ui checkbox">
-									<input name="enable_timetracker" class="enable-system" data-target="#only_contributors" type="checkbox" {{if .Repository.IsTimetrackerEnabled}}checked{{end}}>
+									<input name="enable_timetracker" class="enable-system" data-target="#only_contributors" type="checkbox" {{if .Repository.IsTimetrackerEnabled $.Context}}checked{{end}}>
 									<label>{{.locale.Tr "repo.settings.enable_timetracker"}}</label>
 								</div>
 							</div>
-							<div class="field {{if not .Repository.IsTimetrackerEnabled}}disabled{{end}}" id="only_contributors">
+							<div class="field {{if not (.Repository.IsTimetrackerEnabled $.Context)}}disabled{{end}}" id="only_contributors">
 								<div class="ui checkbox">
-									<input name="allow_only_contributors_to_track_time" type="checkbox" {{if .Repository.AllowOnlyContributorsToTrackTime}}checked{{end}}>
+									<input name="allow_only_contributors_to_track_time" type="checkbox" {{if .Repository.AllowOnlyContributorsToTrackTime $.Context}}checked{{end}}>
 									<label>{{.locale.Tr "repo.settings.allow_only_contributors_to_track_time"}}</label>
 								</div>
 							</div>
 						{{end}}
 						<div class="field">
 							<div class="ui checkbox">
-								<input name="enable_issue_dependencies" type="checkbox" {{if (.Repository.IsDependenciesEnabled)}}checked{{end}}>
+								<input name="enable_issue_dependencies" type="checkbox" {{if (.Repository.IsDependenciesEnabled $.Context)}}checked{{end}}>
 								<label>{{.locale.Tr "repo.issues.dependency.setting"}}</label>
 							</div>
 						</div>
@@ -346,26 +346,26 @@
 						{{else}}
 						<div class="ui radio checkbox">
 						{{end}}
-							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.UnitTypeExternalTracker}}checked{{end}}/>
+							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.Context $.UnitTypeExternalTracker}}checked{{end}}/>
 							<label>{{.locale.Tr "repo.settings.use_external_issue_tracker"}}</label>
 						</div>
 					</div>
-					<div class="field {{if not (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box">
+					<div class="field {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box">
 						<div class="field">
 							<label for="external_tracker_url">{{.locale.Tr "repo.settings.external_tracker_url"}}</label>
-							<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}">
+							<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}">
 							<p class="help">{{.locale.Tr "repo.settings.external_tracker_url_desc"}}</p>
 						</div>
 						<div class="field">
 							<label for="tracker_url_format">{{.locale.Tr "repo.settings.tracker_url_format"}}</label>
-							<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}">
+							<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}">
 							<p class="help">{{.locale.Tr "repo.settings.tracker_url_format_desc" | Str2html}}</p>
 						</div>
 						<div class="inline fields">
 							<label for="issue_style">{{.locale.Tr "repo.settings.tracker_issue_style"}}</label>
 							<div class="field">
 								<div class="ui radio checkbox">
-								{{$externalTracker := (.Repository.MustGetUnit $.UnitTypeExternalTracker)}}
+								{{$externalTracker := (.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker)}}
 								{{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}}
 									<input class="js-tracker-issue-style" name="tracker_issue_style" type="radio" value="numeric" {{if eq $externalTrackerStyle "numeric"}}checked{{end}}>
 									<label>{{.locale.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">#1234</span></label>
@@ -386,7 +386,7 @@
 						</div>
 						<div class="field {{if ne $externalTrackerStyle "regexp"}}disabled{{end}}" id="tracker-issue-style-regex-box">
 							<label for="external_tracker_regexp_pattern">{{.locale.Tr "repo.settings.tracker_issue_style.regexp_pattern"}}</label>
-							<input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}">
+							<input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}">
 							<p class="help">{{.locale.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc" | Str2html}}</p>
 						</div>
 					</div>
@@ -394,7 +394,7 @@
 
 				<div class="ui divider"></div>
 
-				{{$isProjectsEnabled := .Repository.UnitEnabled $.UnitTypeProjects}}
+				{{$isProjectsEnabled := .Repository.UnitEnabled $.Context $.UnitTypeProjects}}
 				<div class="inline field">
 					<label>{{.locale.Tr "repo.project_board"}}</label>
 					{{if .UnitTypeProjects.UnitGlobalDisabled}}
@@ -407,7 +407,7 @@
 					</div>
 				</div>
 
-				{{$isPackagesEnabled := .Repository.UnitEnabled $.UnitTypePackages}}
+				{{$isPackagesEnabled := .Repository.UnitEnabled $.Context $.UnitTypePackages}}
 				<div class="inline field">
 					<label>{{.locale.Tr "repo.packages"}}</label>
 					{{if .UnitTypePackages.UnitGlobalDisabled}}
@@ -422,8 +422,8 @@
 
 				{{if not .IsMirror}}
 					<div class="ui divider"></div>
-					{{$pullRequestEnabled := .Repository.UnitEnabled $.UnitTypePullRequests}}
-					{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
+					{{$pullRequestEnabled := .Repository.UnitEnabled $.Context $.UnitTypePullRequests}}
+					{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}}
 					<div class="inline field">
 						<label>{{.locale.Tr "repo.pulls"}}</label>
 						{{if .UnitTypePullRequests.UnitGlobalDisabled}}
@@ -880,7 +880,7 @@
 		</div>
 	</div>
 
-	{{if .Repository.UnitEnabled $.UnitTypeWiki}}
+	{{if .Repository.UnitEnabled $.Context $.UnitTypeWiki}}
 	<div class="ui small modal" id="delete-wiki-modal">
 		<div class="header">
 			{{.locale.Tr "repo.settings.wiki_delete"}}
diff --git a/tests/integration/api_repo_edit_test.go b/tests/integration/api_repo_edit_test.go
index 47e07f8d4..716cebeb7 100644
--- a/tests/integration/api_repo_edit_test.go
+++ b/tests/integration/api_repo_edit_test.go
@@ -9,6 +9,7 @@ import (
 	"net/url"
 	"testing"
 
+	"code.gitea.io/gitea/models/db"
 	repo_model "code.gitea.io/gitea/models/repo"
 	unit_model "code.gitea.io/gitea/models/unit"
 	"code.gitea.io/gitea/models/unittest"
@@ -27,7 +28,7 @@ func getRepoEditOptionFromRepo(repo *repo_model.Repository) *api.EditRepoOption
 	hasIssues := false
 	var internalTracker *api.InternalTracker
 	var externalTracker *api.ExternalTracker
-	if unit, err := repo.GetUnit(unit_model.TypeIssues); err == nil {
+	if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypeIssues); err == nil {
 		config := unit.IssuesConfig()
 		hasIssues = true
 		internalTracker = &api.InternalTracker{
@@ -35,7 +36,7 @@ func getRepoEditOptionFromRepo(repo *repo_model.Repository) *api.EditRepoOption
 			AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
 			EnableIssueDependencies:          config.EnableDependencies,
 		}
-	} else if unit, err := repo.GetUnit(unit_model.TypeExternalTracker); err == nil {
+	} else if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypeExternalTracker); err == nil {
 		config := unit.ExternalTrackerConfig()
 		hasIssues = true
 		externalTracker = &api.ExternalTracker{
@@ -47,9 +48,9 @@ func getRepoEditOptionFromRepo(repo *repo_model.Repository) *api.EditRepoOption
 	}
 	hasWiki := false
 	var externalWiki *api.ExternalWiki
-	if _, err := repo.GetUnit(unit_model.TypeWiki); err == nil {
+	if _, err := repo.GetUnit(db.DefaultContext, unit_model.TypeWiki); err == nil {
 		hasWiki = true
-	} else if unit, err := repo.GetUnit(unit_model.TypeExternalWiki); err == nil {
+	} else if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypeExternalWiki); err == nil {
 		hasWiki = true
 		config := unit.ExternalWikiConfig()
 		externalWiki = &api.ExternalWiki{
@@ -63,7 +64,7 @@ func getRepoEditOptionFromRepo(repo *repo_model.Repository) *api.EditRepoOption
 	allowRebase := false
 	allowRebaseMerge := false
 	allowSquash := false
-	if unit, err := repo.GetUnit(unit_model.TypePullRequests); err == nil {
+	if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypePullRequests); err == nil {
 		config := unit.PullRequestsConfig()
 		hasPullRequests = true
 		ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go
index 753b7e766..1bd91a48b 100644
--- a/tests/integration/mirror_pull_test.go
+++ b/tests/integration/mirror_pull_test.go
@@ -7,6 +7,7 @@ import (
 	"context"
 	"testing"
 
+	"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"
@@ -57,7 +58,7 @@ func TestMirrorPull(t *testing.T) {
 	defer gitRepo.Close()
 
 	findOptions := repo_model.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
-	initCount, err := repo_model.GetReleaseCountByRepoID(mirror.ID, findOptions)
+	initCount, err := repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions)
 	assert.NoError(t, err)
 
 	assert.NoError(t, release_service.CreateRelease(gitRepo, &repo_model.Release{
@@ -80,7 +81,7 @@ func TestMirrorPull(t *testing.T) {
 	ok := mirror_service.SyncPullMirror(ctx, mirror.ID)
 	assert.True(t, ok)
 
-	count, err := repo_model.GetReleaseCountByRepoID(mirror.ID, findOptions)
+	count, err := repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions)
 	assert.NoError(t, err)
 	assert.EqualValues(t, initCount+1, count)
 
@@ -91,7 +92,7 @@ func TestMirrorPull(t *testing.T) {
 	ok = mirror_service.SyncPullMirror(ctx, mirror.ID)
 	assert.True(t, ok)
 
-	count, err = repo_model.GetReleaseCountByRepoID(mirror.ID, findOptions)
+	count, err = repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions)
 	assert.NoError(t, err)
 	assert.EqualValues(t, initCount, count)
 }