From 2111741a4871a7876f49e5bfde380edaa0f9accf Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Sat, 25 Jun 2022 20:02:29 +0100
Subject: [PATCH] Add doctor command to write commit-graphs (#20007)

This PR adds a doctor command to write the commit-graphs for the repositories:

`gitea doctor --run check-commit-graphs --fix`

Signed-off-by: Andrew Thornton <art27@cantab.net>
---
 modules/doctor/mergebase.go |  3 ++
 modules/doctor/misc.go      | 76 +++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/modules/doctor/mergebase.go b/modules/doctor/mergebase.go
index 46369290a1..2da91cdcc3 100644
--- a/modules/doctor/mergebase.go
+++ b/modules/doctor/mergebase.go
@@ -30,6 +30,9 @@ func iteratePRs(ctx context.Context, repo *repo_model.Repository, each func(*rep
 }
 
 func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) error {
+	if err := git.InitOnceWithSync(ctx); err != nil {
+		return err
+	}
 	numRepos := 0
 	numPRs := 0
 	numPRsUpdated := 0
diff --git a/modules/doctor/misc.go b/modules/doctor/misc.go
index 9bee78303e..24175fcaf4 100644
--- a/modules/doctor/misc.go
+++ b/modules/doctor/misc.go
@@ -189,6 +189,75 @@ func checkDaemonExport(ctx context.Context, logger log.Logger, autofix bool) err
 	return nil
 }
 
+func checkCommitGraph(ctx context.Context, logger log.Logger, autofix bool) error {
+	if err := git.InitOnceWithSync(ctx); err != nil {
+		return err
+	}
+
+	numRepos := 0
+	numNeedUpdate := 0
+	numWritten := 0
+	if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
+		numRepos++
+
+		commitGraphExists := func() (bool, error) {
+			// Check commit-graph exists
+			commitGraphFile := path.Join(repo.RepoPath(), `objects/info/commit-graph`)
+			isExist, err := util.IsExist(commitGraphFile)
+			if err != nil {
+				logger.Error("Unable to check if %s exists. Error: %v", commitGraphFile, err)
+				return false, err
+			}
+
+			if !isExist {
+				commitGraphsDir := path.Join(repo.RepoPath(), `objects/info/commit-graphs`)
+				isExist, err = util.IsExist(commitGraphsDir)
+				if err != nil {
+					logger.Error("Unable to check if %s exists. Error: %v", commitGraphsDir, err)
+					return false, err
+				}
+			}
+			return isExist, nil
+		}
+
+		isExist, err := commitGraphExists()
+		if err != nil {
+			return err
+		}
+		if !isExist {
+			numNeedUpdate++
+			if autofix {
+				if err := git.WriteCommitGraph(ctx, repo.RepoPath()); err != nil {
+					logger.Error("Unable to write commit-graph in %s. Error: %v", repo.FullName(), err)
+					return err
+				}
+				isExist, err := commitGraphExists()
+				if err != nil {
+					return err
+				}
+				if isExist {
+					numWritten++
+					logger.Info("Commit-graph written:    %s", repo.FullName())
+				} else {
+					logger.Warn("No commit-graph written: %s", repo.FullName())
+				}
+			}
+		}
+		return nil
+	}); err != nil {
+		logger.Critical("Unable to checkCommitGraph: %v", err)
+		return err
+	}
+
+	if autofix {
+		logger.Info("Wrote commit-graph files for %d of %d repositories.", numWritten, numRepos)
+	} else {
+		logger.Info("Checked %d repositories, %d without commit-graphs.", numRepos, numNeedUpdate)
+	}
+
+	return nil
+}
+
 func init() {
 	Register(&Check{
 		Title:     "Check if SCRIPT_TYPE is available",
@@ -225,4 +294,11 @@ func init() {
 		Run:       checkDaemonExport,
 		Priority:  8,
 	})
+	Register(&Check{
+		Title:     "Check commit-graphs",
+		Name:      "check-commit-graphs",
+		IsDefault: false,
+		Run:       checkCommitGraph,
+		Priority:  9,
+	})
 }