gitea源码

repository.go 2.0KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package doctor
  4. import (
  5. "context"
  6. "code.gitea.io/gitea/models/db"
  7. "code.gitea.io/gitea/modules/log"
  8. "code.gitea.io/gitea/modules/storage"
  9. repo_service "code.gitea.io/gitea/services/repository"
  10. "xorm.io/builder"
  11. )
  12. func handleDeleteOrphanedRepos(ctx context.Context, logger log.Logger, autofix bool) error {
  13. test := &consistencyCheck{
  14. Name: "Repos with no existing owner",
  15. Counter: countOrphanedRepos,
  16. Fixer: deleteOrphanedRepos,
  17. FixedMessage: "Deleted all content related to orphaned repos",
  18. }
  19. return test.Run(ctx, logger, autofix)
  20. }
  21. // countOrphanedRepos count repository where user of owner_id do not exist
  22. func countOrphanedRepos(ctx context.Context) (int64, error) {
  23. return db.CountOrphanedObjects(ctx, "repository", "user", "repository.owner_id=`user`.id")
  24. }
  25. // deleteOrphanedRepos delete repository where user of owner_id do not exist
  26. func deleteOrphanedRepos(ctx context.Context) (int64, error) {
  27. if err := storage.Init(); err != nil {
  28. return 0, err
  29. }
  30. batchSize := db.MaxBatchInsertSize("repository")
  31. e := db.GetEngine(ctx)
  32. var deleted int64
  33. for {
  34. select {
  35. case <-ctx.Done():
  36. return deleted, ctx.Err()
  37. default:
  38. var ids []int64
  39. if err := e.Table("`repository`").
  40. Join("LEFT", "`user`", "repository.owner_id=`user`.id").
  41. Where(builder.IsNull{"`user`.id"}).
  42. Select("`repository`.id").Limit(batchSize).Find(&ids); err != nil {
  43. return deleted, err
  44. }
  45. // if we don't get ids we have deleted them all
  46. if len(ids) == 0 {
  47. return deleted, nil
  48. }
  49. for _, id := range ids {
  50. if err := repo_service.DeleteRepositoryDirectly(ctx, id, true); err != nil {
  51. return deleted, err
  52. }
  53. deleted++
  54. }
  55. }
  56. }
  57. }
  58. func init() {
  59. Register(&Check{
  60. Title: "Deleted all content related to orphaned repos",
  61. Name: "delete-orphaned-repos",
  62. IsDefault: false,
  63. Run: handleDeleteOrphanedRepos,
  64. Priority: 4,
  65. })
  66. }