From e0e3ba6c12c4094dfb1ff0dc5f290214cf9bfe54 Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Thu, 16 Dec 2021 15:55:12 +0000
Subject: [PATCH] Add Reindex buttons to repository settings page (#17494)

This PR adds reindexing request buttons to the repository settings page.

Fix #3796

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 options/locale/locale_en-US.ini      |  6 ++++
 routers/web/repo/setting.go          | 47 ++++++++++++++++++++++++++++
 services/forms/repo_form.go          |  3 +-
 templates/repo/settings/options.tmpl | 41 +++++++++++++++++++++++-
 4 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 3f180ddbec..685b219ce1 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1726,6 +1726,12 @@ settings.pulls.default_delete_branch_after_merge = Delete pull request branch af
 settings.projects_desc = Enable Repository Projects
 settings.admin_settings = Administrator Settings
 settings.admin_enable_health_check = Enable Repository Health Checks (git fsck)
+settings.admin_code_indexer = Code Indexer
+settings.admin_stats_indexer = Code Statistics Indexer
+settings.admin_indexer_commit_sha = Last Indexed SHA
+settings.admin_indexer_unindexed = Unindexed
+settings.reindex_button = Add to Reindex Queue
+settings.reindex_requested=Reindex Requested
 settings.admin_enable_close_issues_via_commit_in_any_branch = Close an issue via a commit made in a non default branch
 settings.danger_zone = Danger Zone
 settings.new_owner_has_same_repo = The new owner already has a repository with same name. Please choose another name.
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index a6b1219954..ff38f61d8b 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -24,6 +24,8 @@ import (
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/indexer/code"
+	"code.gitea.io/gitea/modules/indexer/stats"
 	"code.gitea.io/gitea/modules/lfs"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/repository"
@@ -67,6 +69,23 @@ func Settings(ctx *context.Context) {
 	signing, _ := asymkey_service.SigningKey(ctx.Repo.Repository.RepoPath())
 	ctx.Data["SigningKeyAvailable"] = len(signing) > 0
 	ctx.Data["SigningSettings"] = setting.Repository.Signing
+	ctx.Data["CodeIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+	if ctx.User.IsAdmin {
+		if setting.Indexer.RepoIndexerEnabled {
+			status, err := repo_model.GetIndexerStatus(ctx.Repo.Repository, repo_model.RepoIndexerTypeCode)
+			if err != nil {
+				ctx.ServerError("repo.indexer_status", err)
+				return
+			}
+			ctx.Data["CodeIndexerStatus"] = status
+		}
+		status, err := repo_model.GetIndexerStatus(ctx.Repo.Repository, repo_model.RepoIndexerTypeStats)
+		if err != nil {
+			ctx.ServerError("repo.indexer_status", err)
+			return
+		}
+		ctx.Data["StatsIndexerStatus"] = status
+	}
 	pushMirrors, err := repo_model.GetPushMirrorsByRepoID(ctx.Repo.Repository.ID)
 	if err != nil {
 		ctx.ServerError("GetPushMirrorsByRepoID", err)
@@ -515,6 +534,34 @@ func SettingsPost(ctx *context.Context) {
 		ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
 		ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 
+	case "admin_index":
+		if !ctx.User.IsAdmin {
+			ctx.Error(http.StatusForbidden)
+			return
+		}
+
+		switch form.RequestReindexType {
+		case "stats":
+			if err := stats.UpdateRepoIndexer(ctx.Repo.Repository); err != nil {
+				ctx.ServerError("UpdateStatsRepondexer", err)
+				return
+			}
+		case "code":
+			if !setting.Indexer.RepoIndexerEnabled {
+				ctx.Error(http.StatusForbidden)
+				return
+			}
+			code.UpdateRepoIndexer(ctx.Repo.Repository)
+		default:
+			ctx.NotFound("", nil)
+			return
+		}
+
+		log.Trace("Repository reindex for %s requested: %s/%s", form.RequestReindexType, ctx.Repo.Owner.Name, repo.Name)
+
+		ctx.Flash.Success(ctx.Tr("repo.settings.reindex_requested"))
+		ctx.Redirect(ctx.Repo.RepoLink + "/settings")
+
 	case "convert":
 		if !ctx.Repo.IsOwner() {
 			ctx.Error(http.StatusNotFound)
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index 7c61be5e22..c571951bb9 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -161,7 +161,8 @@ type RepoSettingForm struct {
 	TrustModel string
 
 	// Admin settings
-	EnableHealthCheck bool
+	EnableHealthCheck  bool
+	RequestReindexType string
 }
 
 // Validate validates the fields
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl
index 5a4c8ace69..4389b63559 100644
--- a/templates/repo/settings/options.tmpl
+++ b/templates/repo/settings/options.tmpl
@@ -558,11 +558,50 @@
 					</div>
 				</div>
 
-				<div class="ui divider"></div>
 				<div class="field">
 					<button class="ui green button">{{$.i18n.Tr "repo.settings.update_settings"}}</button>
 				</div>
 			</form>
+
+			<div class="ui divider"></div>
+			<form class="ui form" method="post">
+				{{.CsrfTokenHtml}}
+				<input type="hidden" name="action" value="admin_index">
+				{{if .CodeIndexerEnabled}}
+					<h4 class="ui header">{{.i18n.Tr "repo.settings.admin_code_indexer"}}</h4>
+					<div class="inline fields">
+						<label>{{.i18n.Tr "repo.settings.admin_indexer_commit_sha"}}</label>
+						<span class="field">
+							{{if .CodeIndexerStatus}}
+								<a rel="nofollow" class="ui sha label" href="{{.RepoLink}}/commit/{{.CodeIndexerStatus.CommitSha}}">
+									<span class="shortsha">{{ShortSha .CodeIndexerStatus.CommitSha}}</span>
+								</a>
+							{{else}}
+									<span>{{.i18n.Tr "repo.settings.admin_indexer_unindexed"}}</span>
+							{{end}}
+						</span>
+						<div class="field">
+							<button class="ui green button" name="request_reindex_type" value="code">{{$.i18n.Tr "repo.settings.reindex_button"}}</button>
+						</div>
+					</div>
+				{{end}}
+				<h4 class="ui header">{{.i18n.Tr "repo.settings.admin_stats_indexer"}}</h4>
+				<div class="inline fields">
+					<label>{{.i18n.Tr "repo.settings.admin_indexer_commit_sha"}}</label>
+					<span class="field">
+						{{if .StatsIndexerStatus}}
+							<a rel="nofollow" class="ui sha label" href="{{.RepoLink}}/commit/{{.StatsIndexerStatus.CommitSha}}">
+								<span class="shortsha">{{ShortSha .StatsIndexerStatus.CommitSha}}</span>
+							</a>
+						{{else}}
+							<span>{{.i18n.Tr "repo.settings.admin_indexer_unindexed"}}</span>
+						{{end}}
+					</span>
+					<div class="field">
+						<button class="ui green button" name="request_reindex_type" value="stats">{{$.i18n.Tr "repo.settings.reindex_button"}}</button>
+					</div>
+				</div>
+			</form>
 		</div>
 		{{end}}