diff options
author | 6543 <6543@obermui.de> | 2023-10-19 15:20:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-19 15:20:52 +0200 |
commit | e83f2cbbacd2696f26dde7105d7f07833c0cc33e (patch) | |
tree | 35d87113518a7efc8c511e0361a7652fe6afaac3 /modules | |
parent | 3dc0c962bf3a74188bed02c01b4d34636112805a (diff) | |
download | gitea-e83f2cbbacd2696f26dde7105d7f07833c0cc33e.tar.gz gitea-e83f2cbbacd2696f26dde7105d7f07833c0cc33e.zip |
Add doctor dbconsistency fix to delete repos with no owner (#27290)
to address #27273
replace #24873
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..aa3f064ddd --- /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, 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, + }) +} |