Преглед изворни кода

Add doctor dbconsistency fix to delete repos with no owner (#27290)

to address #27273
replace #24873
tags/v1.22.0-rc0
6543 пре 7 месеци
родитељ
комит
e83f2cbbac
No account linked to committer's email address
2 измењених фајлова са 79 додато и 6 уклоњено
  1. 70
    0
      modules/doctor/repository.go
  2. 9
    6
      services/repository/delete.go

+ 70
- 0
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,
})
}

+ 9
- 6
services/repository/delete.go Прегледај датотеку

@@ -33,7 +33,7 @@ import (

// DeleteRepository deletes a repository for a user or organization.
// make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock)
func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID int64) error {
func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID int64, ignoreOrgTeams ...bool) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
@@ -65,10 +65,13 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
return fmt.Errorf("list actions artifacts of repo %v: %w", repoID, err)
}

// In case is a organization.
org, err := user_model.GetUserByID(ctx, repo.OwnerID)
if err != nil {
return err
// In case owner is a organization, we have to change repo specific teams
// if ignoreOrgTeams is not true
var org *user_model.User
if len(ignoreOrgTeams) == 0 || !ignoreOrgTeams[0] {
if org, err = user_model.GetUserByID(ctx, repo.OwnerID); err != nil {
return err
}
}

// Delete Deploy Keys
@@ -93,7 +96,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
}
}

if org.IsOrganization() {
if org != nil && org.IsOrganization() {
teams, err := organization.FindOrgTeams(ctx, org.ID)
if err != nil {
return err

Loading…
Откажи
Сачувај