summaryrefslogtreecommitdiffstats
path: root/services/doctor/push_mirror_consistency.go
diff options
context:
space:
mode:
Diffstat (limited to 'services/doctor/push_mirror_consistency.go')
-rw-r--r--services/doctor/push_mirror_consistency.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/services/doctor/push_mirror_consistency.go b/services/doctor/push_mirror_consistency.go
new file mode 100644
index 0000000..68b96d6
--- /dev/null
+++ b/services/doctor/push_mirror_consistency.go
@@ -0,0 +1,91 @@
+// Copyright 2023 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package doctor
+
+import (
+ "context"
+ "strings"
+
+ "code.gitea.io/gitea/models/db"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/log"
+
+ "xorm.io/builder"
+)
+
+func FixPushMirrorsWithoutGitRemote(ctx context.Context, logger log.Logger, autofix bool) error {
+ var missingMirrors []*repo_model.PushMirror
+
+ err := db.Iterate(ctx, builder.Gt{"id": 0}, func(ctx context.Context, repo *repo_model.Repository) error {
+ pushMirrors, _, err := repo_model.GetPushMirrorsByRepoID(ctx, repo.ID, db.ListOptions{})
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < len(pushMirrors); i++ {
+ _, err = repo_model.GetPushMirrorRemoteAddress(repo.OwnerName, repo.Name, pushMirrors[i].RemoteName)
+ if err != nil {
+ if strings.Contains(err.Error(), "No such remote") {
+ missingMirrors = append(missingMirrors, pushMirrors[i])
+ } else if logger != nil {
+ logger.Warn("Unable to retrieve the remote address of a mirror: %s", err)
+ }
+ }
+ }
+
+ return nil
+ })
+ if err != nil {
+ if logger != nil {
+ logger.Critical("Unable to iterate across repounits to fix push mirrors without a git remote: Error %v", err)
+ }
+ return err
+ }
+
+ count := len(missingMirrors)
+ if !autofix {
+ if logger != nil {
+ if count == 0 {
+ logger.Info("Found no push mirrors with missing git remotes")
+ } else {
+ logger.Warn("Found %d push mirrors with missing git remotes", count)
+ }
+ }
+ return nil
+ }
+
+ for i := 0; i < len(missingMirrors); i++ {
+ if logger != nil {
+ logger.Info("Removing push mirror #%d (remote: %s), for repo: %s/%s",
+ missingMirrors[i].ID,
+ missingMirrors[i].RemoteName,
+ missingMirrors[i].GetRepository(ctx).OwnerName,
+ missingMirrors[i].GetRepository(ctx).Name)
+ }
+
+ err = repo_model.DeletePushMirrors(ctx, repo_model.PushMirrorOptions{
+ ID: missingMirrors[i].ID,
+ RepoID: missingMirrors[i].RepoID,
+ RemoteName: missingMirrors[i].RemoteName,
+ })
+ if err != nil {
+ if logger != nil {
+ logger.Critical("Error removing a push mirror (repo_id: %d, push_mirror: %d): %s", missingMirrors[i].Repo.ID, missingMirrors[i].ID, err)
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+func init() {
+ Register(&Check{
+ Title: "Check for push mirrors without a git remote configured",
+ Name: "fix-push-mirrors-without-git-remote",
+ IsDefault: false,
+ Run: FixPushMirrorsWithoutGitRemote,
+ Priority: 7,
+ })
+}