diff --git a/modules/repository/create.go b/modules/repository/create.go
index a53632bb57..a75598a84b 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -8,17 +8,9 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
-	"strings"
 
-	activities_model "code.gitea.io/gitea/models/activities"
-	"code.gitea.io/gitea/models/db"
 	git_model "code.gitea.io/gitea/models/git"
-	access_model "code.gitea.io/gitea/models/perm/access"
 	repo_model "code.gitea.io/gitea/models/repo"
-	issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
-	"code.gitea.io/gitea/modules/log"
-	api "code.gitea.io/gitea/modules/structs"
-	"code.gitea.io/gitea/modules/util"
 )
 
 const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
@@ -63,97 +55,3 @@ func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error {
 
 	return repo_model.UpdateRepoSize(ctx, repo.ID, size, lfsSize)
 }
-
-// CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
-func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
-	if err := repo.LoadOwner(ctx); err != nil {
-		return err
-	}
-
-	// Create/Remove git-daemon-export-ok for git-daemon...
-	daemonExportFile := filepath.Join(repo.RepoPath(), `git-daemon-export-ok`)
-
-	isExist, err := util.IsExist(daemonExportFile)
-	if err != nil {
-		log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err)
-		return err
-	}
-
-	isPublic := !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePublic
-	if !isPublic && isExist {
-		if err = util.Remove(daemonExportFile); err != nil {
-			log.Error("Failed to remove %s: %v", daemonExportFile, err)
-		}
-	} else if isPublic && !isExist {
-		if f, err := os.Create(daemonExportFile); err != nil {
-			log.Error("Failed to create %s: %v", daemonExportFile, err)
-		} else {
-			f.Close()
-		}
-	}
-
-	return nil
-}
-
-// UpdateRepository updates a repository with db context
-func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
-	repo.LowerName = strings.ToLower(repo.Name)
-
-	e := db.GetEngine(ctx)
-
-	if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
-		return fmt.Errorf("update: %w", err)
-	}
-
-	if err = UpdateRepoSize(ctx, repo); err != nil {
-		log.Error("Failed to update size for repository: %v", err)
-	}
-
-	if visibilityChanged {
-		if err = repo.LoadOwner(ctx); err != nil {
-			return fmt.Errorf("LoadOwner: %w", err)
-		}
-		if repo.Owner.IsOrganization() {
-			// Organization repository need to recalculate access table when visibility is changed.
-			if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
-				return fmt.Errorf("recalculateTeamAccesses: %w", err)
-			}
-		}
-
-		// If repo has become private, we need to set its actions to private.
-		if repo.IsPrivate {
-			_, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
-				IsPrivate: true,
-			})
-			if err != nil {
-				return err
-			}
-
-			if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
-				return err
-			}
-		}
-
-		// Create/Remove git-daemon-export-ok for git-daemon...
-		if err := CheckDaemonExportOK(ctx, repo); err != nil {
-			return err
-		}
-
-		forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
-		if err != nil {
-			return fmt.Errorf("getRepositoriesByForkID: %w", err)
-		}
-		for i := range forkRepos {
-			forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate
-			if err = UpdateRepository(ctx, forkRepos[i], true); err != nil {
-				return fmt.Errorf("updateRepository[%d]: %w", forkRepos[i].ID, err)
-			}
-		}
-
-		// If visibility is changed, we need to update the issue indexer.
-		// Since the data in the issue indexer have field to indicate if the repo is public or not.
-		issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
-	}
-
-	return nil
-}
diff --git a/modules/repository/create_test.go b/modules/repository/create_test.go
index e1f981ba3c..b85a10adad 100644
--- a/modules/repository/create_test.go
+++ b/modules/repository/create_test.go
@@ -6,7 +6,6 @@ package repository
 import (
 	"testing"
 
-	activities_model "code.gitea.io/gitea/models/activities"
 	"code.gitea.io/gitea/models/db"
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
@@ -14,26 +13,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
-	assert.NoError(t, unittest.PrepareTestDatabase())
-
-	// Get sample repo and change visibility
-	repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9)
-	assert.NoError(t, err)
-	repo.IsPrivate = true
-
-	// Update it
-	err = UpdateRepository(db.DefaultContext, repo, true)
-	assert.NoError(t, err)
-
-	// Check visibility of action has become private
-	act := activities_model.Action{}
-	_, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act)
-
-	assert.NoError(t, err)
-	assert.True(t, act.IsPrivate)
-}
-
 func TestGetDirectorySize(t *testing.T) {
 	assert.NoError(t, unittest.PrepareTestDatabase())
 	repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 1)
diff --git a/services/repository/adopt.go b/services/repository/adopt.go
index 6d5505c42c..7f1954145c 100644
--- a/services/repository/adopt.go
+++ b/services/repository/adopt.go
@@ -196,7 +196,7 @@ func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBr
 			return fmt.Errorf("setDefaultBranch: %w", err)
 		}
 	}
-	if err = repo_module.UpdateRepository(ctx, repo, false); err != nil {
+	if err = updateRepository(ctx, repo, false); err != nil {
 		return fmt.Errorf("updateRepository: %w", err)
 	}
 
diff --git a/services/repository/create.go b/services/repository/create.go
index 5a9b2ecd2a..897f2a1d14 100644
--- a/services/repository/create.go
+++ b/services/repository/create.go
@@ -464,7 +464,7 @@ func cleanupRepository(doer *user_model.User, repoID int64) {
 }
 
 func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) error {
-	if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil {
+	if err := checkDaemonExportOK(ctx, repo); err != nil {
 		return fmt.Errorf("checkDaemonExportOK: %w", err)
 	}
 
diff --git a/services/repository/fork.go b/services/repository/fork.go
index 1794cc18ab..c16c3d598a 100644
--- a/services/repository/fork.go
+++ b/services/repository/fork.go
@@ -227,7 +227,7 @@ func ConvertForkToNormalRepository(ctx context.Context, repo *repo_model.Reposit
 		repo.IsFork = false
 		repo.ForkID = 0
 
-		if err := repo_module.UpdateRepository(ctx, repo, false); err != nil {
+		if err := updateRepository(ctx, repo, false); err != nil {
 			log.Error("Unable to update repository %-v whilst converting from fork. Error: %v", repo, err)
 			return err
 		}
diff --git a/services/repository/repository.go b/services/repository/repository.go
index cd56010546..90aad4f9d8 100644
--- a/services/repository/repository.go
+++ b/services/repository/repository.go
@@ -7,20 +7,27 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
 
+	activities_model "code.gitea.io/gitea/models/activities"
 	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/models/git"
 	issues_model "code.gitea.io/gitea/models/issues"
 	"code.gitea.io/gitea/models/organization"
+	access_model "code.gitea.io/gitea/models/perm/access"
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unit"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/graceful"
+	issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/queue"
 	repo_module "code.gitea.io/gitea/modules/repository"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/modules/util"
 	notify_service "code.gitea.io/gitea/services/notify"
 	pull_service "code.gitea.io/gitea/services/pull"
 )
@@ -109,42 +116,32 @@ func Init(ctx context.Context) error {
 
 // UpdateRepository updates a repository
 func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
-	ctx, committer, err := db.TxContext(ctx)
-	if err != nil {
-		return err
-	}
-	defer committer.Close()
-
-	if err = repo_module.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
-		return fmt.Errorf("updateRepository: %w", err)
-	}
-
-	return committer.Commit()
-}
-
-func UpdateRepositoryVisibility(ctx context.Context, repo *repo_model.Repository, isPrivate bool) (err error) {
-	ctx, committer, err := db.TxContext(ctx)
-	if err != nil {
-		return err
-	}
-
-	defer committer.Close()
-
-	repo.IsPrivate = isPrivate
-
-	if err = repo_module.UpdateRepository(ctx, repo, true); err != nil {
-		return fmt.Errorf("UpdateRepositoryVisibility: %w", err)
-	}
-
-	return committer.Commit()
+	return db.WithTx(ctx, func(ctx context.Context) error {
+		if err = updateRepository(ctx, repo, visibilityChanged); err != nil {
+			return fmt.Errorf("updateRepository: %w", err)
+		}
+		return nil
+	})
 }
 
 func MakeRepoPublic(ctx context.Context, repo *repo_model.Repository) (err error) {
-	return UpdateRepositoryVisibility(ctx, repo, false)
+	return db.WithTx(ctx, func(ctx context.Context) error {
+		repo.IsPrivate = false
+		if err = updateRepository(ctx, repo, true); err != nil {
+			return fmt.Errorf("MakeRepoPublic: %w", err)
+		}
+		return nil
+	})
 }
 
 func MakeRepoPrivate(ctx context.Context, repo *repo_model.Repository) (err error) {
-	return UpdateRepositoryVisibility(ctx, repo, true)
+	return db.WithTx(ctx, func(ctx context.Context) error {
+		repo.IsPrivate = true
+		if err = updateRepository(ctx, repo, true); err != nil {
+			return fmt.Errorf("MakeRepoPrivate: %w", err)
+		}
+		return nil
+	})
 }
 
 // LinkedRepository returns the linked repo if any
@@ -170,3 +167,97 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode
 	}
 	return nil, -1, nil
 }
+
+// checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
+func checkDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
+	if err := repo.LoadOwner(ctx); err != nil {
+		return err
+	}
+
+	// Create/Remove git-daemon-export-ok for git-daemon...
+	daemonExportFile := filepath.Join(repo.RepoPath(), `git-daemon-export-ok`)
+
+	isExist, err := util.IsExist(daemonExportFile)
+	if err != nil {
+		log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err)
+		return err
+	}
+
+	isPublic := !repo.IsPrivate && repo.Owner.Visibility == structs.VisibleTypePublic
+	if !isPublic && isExist {
+		if err = util.Remove(daemonExportFile); err != nil {
+			log.Error("Failed to remove %s: %v", daemonExportFile, err)
+		}
+	} else if isPublic && !isExist {
+		if f, err := os.Create(daemonExportFile); err != nil {
+			log.Error("Failed to create %s: %v", daemonExportFile, err)
+		} else {
+			f.Close()
+		}
+	}
+
+	return nil
+}
+
+// updateRepository updates a repository with db context
+func updateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
+	repo.LowerName = strings.ToLower(repo.Name)
+
+	e := db.GetEngine(ctx)
+
+	if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
+		return fmt.Errorf("update: %w", err)
+	}
+
+	if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
+		log.Error("Failed to update size for repository: %v", err)
+	}
+
+	if visibilityChanged {
+		if err = repo.LoadOwner(ctx); err != nil {
+			return fmt.Errorf("LoadOwner: %w", err)
+		}
+		if repo.Owner.IsOrganization() {
+			// Organization repository need to recalculate access table when visibility is changed.
+			if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
+				return fmt.Errorf("recalculateTeamAccesses: %w", err)
+			}
+		}
+
+		// If repo has become private, we need to set its actions to private.
+		if repo.IsPrivate {
+			_, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
+				IsPrivate: true,
+			})
+			if err != nil {
+				return err
+			}
+
+			if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
+				return err
+			}
+		}
+
+		// Create/Remove git-daemon-export-ok for git-daemon...
+		if err := checkDaemonExportOK(ctx, repo); err != nil {
+			return err
+		}
+
+		forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
+		if err != nil {
+			return fmt.Errorf("getRepositoriesByForkID: %w", err)
+		}
+		for i := range forkRepos {
+			forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == structs.VisibleTypePrivate
+			if err = updateRepository(ctx, forkRepos[i], true); err != nil {
+				return fmt.Errorf("updateRepository[%d]: %w", forkRepos[i].ID, err)
+			}
+		}
+
+		// If visibility is changed, we need to update the issue indexer.
+		// Since the data in the issue indexer have field to indicate if the repo is public or not.
+		issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
+	}
+
+	return nil
+}
diff --git a/services/repository/repository_test.go b/services/repository/repository_test.go
index 892a11a23e..8f9fdf8fa1 100644
--- a/services/repository/repository_test.go
+++ b/services/repository/repository_test.go
@@ -6,6 +6,7 @@ package repository
 import (
 	"testing"
 
+	activities_model "code.gitea.io/gitea/models/activities"
 	"code.gitea.io/gitea/models/db"
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unit"
@@ -40,3 +41,23 @@ func TestLinkedRepository(t *testing.T) {
 		})
 	}
 }
+
+func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
+	assert.NoError(t, unittest.PrepareTestDatabase())
+
+	// Get sample repo and change visibility
+	repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9)
+	assert.NoError(t, err)
+	repo.IsPrivate = true
+
+	// Update it
+	err = updateRepository(db.DefaultContext, repo, true)
+	assert.NoError(t, err)
+
+	// Check visibility of action has become private
+	act := activities_model.Action{}
+	_, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act)
+
+	assert.NoError(t, err)
+	assert.True(t, act.IsPrivate)
+}