mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 04:14:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			81 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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"
 | 
						|
	"code.gitea.io/gitea/modules/storage"
 | 
						|
	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) {
 | 
						|
	if err := storage.Init(); err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
 | 
						|
	batchSize := db.MaxBatchInsertSize("repository")
 | 
						|
	e := db.GetEngine(ctx)
 | 
						|
	var deleted int64
 | 
						|
	adminUser := &user_model.User{IsAdmin: true}
 | 
						|
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
		case <-ctx.Done():
 | 
						|
			return deleted, ctx.Err()
 | 
						|
		default:
 | 
						|
			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,
 | 
						|
	})
 | 
						|
}
 |