2023-10-19 16:20:52 +03:00
// 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"
2023-12-16 15:17:39 +03:00
"code.gitea.io/gitea/modules/storage"
2023-10-19 16:20:52 +03:00
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 ) {
2023-11-24 17:46:19 +03:00
return db . CountOrphanedObjects ( ctx , "repository" , "user" , "repository.owner_id=`user`.id" )
2023-10-19 16:20:52 +03:00
}
// deleteOrphanedRepos delete repository where user of owner_id do not exist
func deleteOrphanedRepos ( ctx context . Context ) ( int64 , error ) {
2023-12-16 15:17:39 +03:00
if err := storage . Init ( ) ; err != nil {
return 0 , err
}
2023-10-19 16:20:52 +03:00
batchSize := db . MaxBatchInsertSize ( "repository" )
e := db . GetEngine ( ctx )
var deleted int64
adminUser := & user_model . User { IsAdmin : true }
for {
2023-10-21 05:05:29 +03:00
select {
case <- ctx . Done ( ) :
return deleted , ctx . Err ( )
default :
var ids [ ] int64
if err := e . Table ( "`repository`" ) .
2023-11-24 17:46:19 +03:00
Join ( "LEFT" , "`user`" , "repository.owner_id=`user`.id" ) .
2023-10-21 05:05:29 +03:00
Where ( builder . IsNull { "`user`.id" } ) .
Select ( "`repository`.id" ) . Limit ( batchSize ) . Find ( & ids ) ; err != nil {
return deleted , err
}
2023-10-19 16:20:52 +03:00
2023-10-21 05:05:29 +03:00
// if we don't get ids we have deleted them all
if len ( ids ) == 0 {
return deleted , nil
}
2023-10-19 16:20:52 +03:00
2023-10-21 05:05:29 +03:00
for _ , id := range ids {
if err := repo_service . DeleteRepositoryDirectly ( ctx , adminUser , id , true ) ; err != nil {
return deleted , err
}
deleted ++
2023-10-19 16:20:52 +03:00
}
}
}
}
func init ( ) {
Register ( & Check {
Title : "Deleted all content related to orphaned repos" ,
Name : "delete-orphaned-repos" ,
IsDefault : false ,
Run : handleDeleteOrphanedRepos ,
Priority : 4 ,
} )
}