You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

heads.go 2.8KB

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