gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package doctor
  4. import (
  5. "context"
  6. repo_model "code.gitea.io/gitea/models/repo"
  7. "code.gitea.io/gitea/modules/git"
  8. "code.gitea.io/gitea/modules/git/gitcmd"
  9. "code.gitea.io/gitea/modules/log"
  10. )
  11. func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) error {
  12. numRepos := 0
  13. numHeadsBroken := 0
  14. numDefaultBranchesBroken := 0
  15. numReposUpdated := 0
  16. err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
  17. numRepos++
  18. _, _, defaultBranchErr := gitcmd.NewCommand("rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
  19. head, _, headErr := gitcmd.NewCommand("symbolic-ref", "--short", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
  20. // what we expect: default branch is valid, and HEAD points to it
  21. if headErr == nil && defaultBranchErr == nil && head == repo.DefaultBranch {
  22. return nil
  23. }
  24. if headErr != nil {
  25. numHeadsBroken++
  26. }
  27. if defaultBranchErr != nil {
  28. numDefaultBranchesBroken++
  29. }
  30. // if default branch is broken, let the user fix that in the UI
  31. if defaultBranchErr != nil {
  32. logger.Warn("Default branch for %s/%s doesn't point to a valid commit", repo.OwnerName, repo.Name)
  33. return nil
  34. }
  35. // if we're not autofixing, that's all we can do
  36. if !autofix {
  37. return nil
  38. }
  39. // otherwise, let's try fixing HEAD
  40. err := gitcmd.NewCommand("symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
  41. if err != nil {
  42. logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err)
  43. return nil
  44. }
  45. numReposUpdated++
  46. return nil
  47. })
  48. if err != nil {
  49. logger.Critical("Error when fixing repo HEADs: %v", err)
  50. }
  51. if autofix {
  52. logger.Info("Out of %d repos, HEADs for %d are now fixed and HEADS for %d are still broken", numRepos, numReposUpdated, numDefaultBranchesBroken+numHeadsBroken-numReposUpdated)
  53. } else {
  54. if numHeadsBroken == 0 && numDefaultBranchesBroken == 0 {
  55. logger.Info("All %d repos have their HEADs in the correct state", numRepos)
  56. } else {
  57. if numHeadsBroken == 0 && numDefaultBranchesBroken != 0 {
  58. logger.Critical("Default branches are broken for %d/%d repos", numDefaultBranchesBroken, numRepos)
  59. } else if numHeadsBroken != 0 && numDefaultBranchesBroken == 0 {
  60. logger.Warn("HEADs are broken for %d/%d repos", numHeadsBroken, numRepos)
  61. } else {
  62. logger.Critical("Out of %d repos, HEADS are broken for %d and default branches are broken for %d", numRepos, numHeadsBroken, numDefaultBranchesBroken)
  63. }
  64. }
  65. }
  66. return err
  67. }
  68. func init() {
  69. Register(&Check{
  70. Title: "Synchronize repo HEADs",
  71. Name: "synchronize-repo-heads",
  72. IsDefault: true,
  73. Run: synchronizeRepoHeads,
  74. Priority: 7,
  75. })
  76. }