diff options
author | 6543 <6543@obermui.de> | 2023-10-22 02:21:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-22 02:21:41 +0200 |
commit | aabcf2d7ad247fb0bf8131ebdf8400fcf5292828 (patch) | |
tree | 552feecf1ac5d470b2a9072869d221bf2a099453 /modules | |
parent | 6919a02ab7acfa7939edc33cb5eb5fdb49d8721a (diff) | |
download | gitea-aabcf2d7ad247fb0bf8131ebdf8400fcf5292828.tar.gz gitea-aabcf2d7ad247fb0bf8131ebdf8400fcf5292828.zip |
Add doctor dbconsistency fix to delete repos with no owner (#27290) (#27693)
Backport #27290
Diffstat (limited to 'modules')
-rw-r--r-- | modules/doctor/repository.go | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/modules/doctor/repository.go b/modules/doctor/repository.go new file mode 100644 index 0000000000..6569378cbe --- /dev/null +++ b/modules/doctor/repository.go @@ -0,0 +1,70 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package doctor + +import ( + "context" + + "code.gitea.io/gitea/models/db" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + repo_service "code.gitea.io/gitea/services/repository" + + "xorm.io/builder" +) + +func handleDeleteOrphanedRepos(ctx context.Context, logger log.Logger, autofix bool) error { + test := &consistencyCheck{ + Name: "Repos with no existing owner", + Counter: countOrphanedRepos, + Fixer: deleteOrphanedRepos, + FixedMessage: "Deleted all content related to orphaned repos", + } + return test.Run(ctx, logger, autofix) +} + +// countOrphanedRepos count repository where user of owner_id do not exist +func countOrphanedRepos(ctx context.Context) (int64, error) { + return db.CountOrphanedObjects(ctx, "repository", "user", "repository.owner_id=user.id") +} + +// deleteOrphanedRepos delete repository where user of owner_id do not exist +func deleteOrphanedRepos(ctx context.Context) (int64, error) { + batchSize := db.MaxBatchInsertSize("repository") + e := db.GetEngine(ctx) + var deleted int64 + adminUser := &user_model.User{IsAdmin: true} + + for { + var ids []int64 + if err := e.Table("`repository`"). + Join("LEFT", "`user`", "repository.owner_id=user.id"). + Where(builder.IsNull{"`user`.id"}). + Select("`repository`.id").Limit(batchSize).Find(&ids); err != nil { + return deleted, err + } + + // if we don't get ids we have deleted them all + if len(ids) == 0 { + return deleted, nil + } + + for _, id := range ids { + if err := repo_service.DeleteRepositoryDirectly(ctx, adminUser, 0, id, true); err != nil { + return deleted, err + } + deleted++ + } + } +} + +func init() { + Register(&Check{ + Title: "Deleted all content related to orphaned repos", + Name: "delete-orphaned-repos", + IsDefault: false, + Run: handleDeleteOrphanedRepos, + Priority: 4, + }) +} |