diff --git a/routers/web/repo/search.go b/routers/web/repo/search.go
index 460378ce05..404d6f93f9 100644
--- a/routers/web/repo/search.go
+++ b/routers/web/repo/search.go
@@ -11,13 +11,17 @@ import (
 	code_indexer "code.gitea.io/gitea/modules/indexer/code"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/services/context"
-	"code.gitea.io/gitea/services/repository/files"
 )
 
 const tplSearch base.TplName = "repo/search"
 
 // Search render repository search page
 func Search(ctx *context.Context) {
+	if !setting.Indexer.RepoIndexerEnabled {
+		ctx.Redirect(ctx.Repo.RepoLink)
+		return
+	}
+
 	language := ctx.FormTrim("l")
 	keyword := ctx.FormTrim("q")
 
@@ -33,57 +37,32 @@ func Search(ctx *context.Context) {
 		return
 	}
 
-	ctx.Data["Repo"] = ctx.Repo.Repository
-
 	page := ctx.FormInt("page")
 	if page <= 0 {
 		page = 1
 	}
-
-	if setting.Indexer.RepoIndexerEnabled {
-		ctx.Data["CodeIndexerDisabled"] = false
-
-		total, searchResults, searchResultLanguages, err := code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
-			RepoIDs:        []int64{ctx.Repo.Repository.ID},
-			Keyword:        keyword,
-			IsKeywordFuzzy: isFuzzy,
-			Language:       language,
-			Paginator: &db.ListOptions{
-				Page:     page,
-				PageSize: setting.UI.RepoSearchPagingNum,
-			},
-		})
-		if err != nil {
-			if code_indexer.IsAvailable(ctx) {
-				ctx.ServerError("SearchResults", err)
-				return
-			}
-			ctx.Data["CodeIndexerUnavailable"] = true
-		} else {
-			ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
-		}
-
-		ctx.Data["SearchResults"] = searchResults
-		ctx.Data["SearchResultLanguages"] = searchResultLanguages
-
-		pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
-		pager.SetDefaultParams(ctx)
-		pager.AddParam(ctx, "l", "Language")
-		ctx.Data["Page"] = pager
-	} else {
-		data, err := files.NewRepoGrep(ctx, ctx.Repo.Repository, keyword)
-		if err != nil {
-			ctx.ServerError("NewRepoGrep", err)
+	
+	total, searchResults, searchResultLanguages, err := code_indexer.PerformSearch(ctx, []int64{ctx.Repo.Repository.ID},
+		language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
+	if err != nil {
+		if code_indexer.IsAvailable(ctx) {
+			ctx.ServerError("SearchResults", err)
 			return
 		}
-
-		ctx.Data["CodeIndexerDisabled"] = true
-		ctx.Data["SearchResults"] = data
-
-		pager := context.NewPagination(len(data), setting.UI.RepoSearchPagingNum, page, 5)
-		pager.SetDefaultParams(ctx)
-		ctx.Data["Page"] = pager
+		ctx.Data["CodeIndexerUnavailable"] = true
+	} else {
+		ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
 	}
 
+	ctx.Data["Repo"] = ctx.Repo.Repository
+	ctx.Data["SourcePath"] = ctx.Repo.Repository.Link()
+	ctx.Data["SearchResults"] = searchResults
+	ctx.Data["SearchResultLanguages"] = searchResultLanguages
+
+	pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
+	pager.SetDefaultParams(ctx)
+	pager.AddParam(ctx, "l", "Language")
+	ctx.Data["Page"] = pager
+
 	ctx.HTML(http.StatusOK, tplSearch)
 }
diff --git a/services/repository/files/search.go b/services/repository/files/search.go
deleted file mode 100644
index 09c3ab5bf3..0000000000
--- a/services/repository/files/search.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package files
-
-import (
-	"context"
-	"html/template"
-	"strconv"
-	"strings"
-
-	repo_model "code.gitea.io/gitea/models/repo"
-	"code.gitea.io/gitea/modules/git"
-	"code.gitea.io/gitea/modules/gitrepo"
-	"code.gitea.io/gitea/modules/highlight"
-	"code.gitea.io/gitea/modules/timeutil"
-
-	"github.com/go-enry/go-enry/v2"
-)
-
-type Result struct {
-	RepoID      int64 // ignored
-	Filename    string
-	CommitID    string             // branch
-	UpdatedUnix timeutil.TimeStamp // ignored
-	Language    string
-	Color       string
-	Lines       []ResultLine
-}
-
-type ResultLine struct {
-	Num              int64
-	FormattedContent template.HTML
-}
-
-const pHEAD = "HEAD:"
-
-func NewRepoGrep(ctx context.Context, repo *repo_model.Repository, keyword string) ([]*Result, error) {
-	t, _, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
-	if err != nil {
-		return nil, err
-	}
-
-	data := []*Result{}
-
-	stdout, _, err := git.NewCommand(ctx,
-		"grep",
-		"-1", // n before and after lines
-		"-z",
-		"--heading",
-		"--break",         // easier parsing
-		"--fixed-strings", // disallow regex for now
-		"-n",              // line nums
-		"-i",              // ignore case
-		"--full-name",     // full file path, rel to repo
-		//"--column",      // for adding better highlighting support
-		"-e", // for queries starting with "-"
-	).
-		AddDynamicArguments(keyword).
-		AddArguments("HEAD").
-		RunStdString(&git.RunOpts{Dir: t.Path})
-	if err != nil {
-		return data, nil // non zero exit code when there are no results
-	}
-
-	for _, block := range strings.Split(stdout, "\n\n") {
-		res := Result{CommitID: repo.DefaultBranch}
-
-		linenum := []int64{}
-		code := []string{}
-
-		for _, line := range strings.Split(block, "\n") {
-			if strings.HasPrefix(line, pHEAD) {
-				res.Filename = strings.TrimPrefix(line, pHEAD)
-				continue
-			}
-
-			if ln, after, ok := strings.Cut(line, "\x00"); ok {
-				i, err := strconv.ParseInt(ln, 10, 64)
-				if err != nil {
-					continue
-				}
-
-				linenum = append(linenum, i)
-				code = append(code, after)
-			}
-		}
-
-		if res.Filename == "" || len(code) == 0 || len(linenum) == 0 {
-			continue
-		}
-
-		var hl template.HTML
-
-		hl, res.Language = highlight.Code(res.Filename, "", strings.Join(code, "\n"))
-		res.Color = enry.GetColor(res.Language)
-
-		hlCode := strings.Split(string(hl), "\n")
-		n := min(len(hlCode), len(linenum))
-
-		res.Lines = make([]ResultLine, n)
-
-		for i := 0; i < n; i++ {
-			res.Lines[i] = ResultLine{
-				Num:              linenum[i],
-				FormattedContent: template.HTML(hlCode[i]),
-			}
-		}
-
-		data = append(data, &res)
-	}
-
-	return data, nil
-}
diff --git a/services/repository/files/search_test.go b/services/repository/files/search_test.go
deleted file mode 100644
index 2f2f87368d..0000000000
--- a/services/repository/files/search_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package files
-
-import (
-	"testing"
-
-	"code.gitea.io/gitea/models/unittest"
-	"code.gitea.io/gitea/services/contexttest"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewRepoGrep(t *testing.T) {
-	unittest.PrepareTestEnv(t)
-	ctx, _ := contexttest.MockContext(t, "user2/repo1")
-	ctx.SetParams(":id", "1")
-	contexttest.LoadRepo(t, ctx, 1)
-	contexttest.LoadRepoCommit(t, ctx)
-	contexttest.LoadUser(t, ctx, 2)
-	contexttest.LoadGitRepo(t, ctx)
-	defer ctx.Repo.GitRepo.Close()
-
-	t.Run("with result", func(t *testing.T) {
-		res, err := NewRepoGrep(ctx, ctx.Repo.Repository, "Description")
-		assert.NoError(t, err)
-
-		expected := []*Result{
-			{
-				RepoID:      0,
-				Filename:    "README.md",
-				CommitID:    "master",
-				UpdatedUnix: 0,
-				Language:    "Markdown",
-				Color:       "#083fa1",
-				Lines: []ResultLine{
-					{Num: 2, FormattedContent: ""},
-					{Num: 3, FormattedContent: "Description for repo1"},
-				},
-			},
-		}
-
-		assert.EqualValues(t, res, expected)
-	})
-
-	t.Run("empty result", func(t *testing.T) {
-		res, err := NewRepoGrep(ctx, ctx.Repo.Repository, "keyword that does not match in the repo")
-		assert.NoError(t, err)
-
-		assert.EqualValues(t, res, []*Result{})
-	})
-}
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index bfb5ab5232..fcaacfc010 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -11,21 +11,23 @@
 				{{if $description}}<span class="description">{{$description | RenderCodeBlock}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{ctx.Locale.Tr "repo.no_desc"}}</span>{{end}}
 				<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>
 			</div>
-			<div class="ui repo-search">
-				<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
-					<div class="field">
-						<div class="ui small action input{{if .CodeIndexerUnavailable}} disabled left icon{{end}}"{{if .CodeIndexerUnavailable}} data-tooltip-content="{{ctx.Locale.Tr "search.code_search_unavailable"}}"{{end}}>
-							<input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{ctx.Locale.Tr "search.code_kind"}}">
-							{{if .CodeIndexerUnavailable}}
-								<i class="icon">{{svg "octicon-alert"}}</i>
-							{{end}}
-							<button class="ui small icon button"{{if .CodeIndexerUnavailable}} disabled{{end}} type="submit">
-								{{svg "octicon-search"}}
-							</button>
+			{{if .RepoSearchEnabled}}
+				<div class="ui repo-search">
+					<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
+						<div class="field">
+							<div class="ui small action input{{if .CodeIndexerUnavailable}} disabled left icon{{end}}"{{if .CodeIndexerUnavailable}} data-tooltip-content="{{ctx.Locale.Tr "search.code_search_unavailable"}}"{{end}}>
+								<input name="q" value="{{.Keyword}}"{{if .CodeIndexerUnavailable}} disabled{{end}} placeholder="{{ctx.Locale.Tr "search.code_kind"}}">
+								{{if .CodeIndexerUnavailable}}
+									<i class="icon">{{svg "octicon-alert"}}</i>
+								{{end}}
+								<button class="ui small icon button"{{if .CodeIndexerUnavailable}} disabled{{end}} type="submit">
+									{{svg "octicon-search"}}
+								</button>
+							</div>
 						</div>
-					</div>
-				</form>
-			</div>
+					</form>
+				</div>
+			{{end}}
 		</div>
 		<div class="tw-flex tw-items-center tw-flex-wrap tw-gap-1" id="repo-topics">
 			{{range .Topics}}<a class="ui repo-topic large label topic gt-m-0" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
diff --git a/tests/integration/repo_search_test.go b/tests/integration/repo_search_test.go
index aecf75025d..56cc45d901 100644
--- a/tests/integration/repo_search_test.go
+++ b/tests/integration/repo_search_test.go
@@ -11,15 +11,14 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	code_indexer "code.gitea.io/gitea/modules/indexer/code"
 	"code.gitea.io/gitea/modules/setting"
-	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
 )
 
-func resultFilenames(t testing.TB, doc *goquery.Selection) []string {
-	filenameSelections := doc.Find(".header").Find("span.file")
+func resultFilenames(t testing.TB, doc *HTMLDoc) []string {
+	filenameSelections := doc.doc.Find(".repository.search").Find(".repo-search-result").Find(".header").Find("span.file")
 	result := make([]string, filenameSelections.Length())
 	filenameSelections.Each(func(i int, selection *goquery.Selection) {
 		result[i] = selection.Text()
@@ -27,66 +26,36 @@ func resultFilenames(t testing.TB, doc *goquery.Selection) []string {
 	return result
 }
 
-func checkResultLinks(t *testing.T, substr string, doc *goquery.Selection) {
-	t.Helper()
-	linkSelections := doc.Find("a[href]")
-	linkSelections.Each(func(i int, selection *goquery.Selection) {
-		assert.Contains(t, selection.AttrOr("href", ""), substr)
-	})
-}
-
-func testSearchRepo(t *testing.T, useExternalIndexer bool) {
+func TestSearchRepo(t *testing.T) {
 	defer tests.PrepareTestEnv(t)()
-	defer test.MockVariableValue(&setting.Indexer.RepoIndexerEnabled, useExternalIndexer)()
 
 	repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1")
 	assert.NoError(t, err)
 
-	gitReference := "/branch/" + repo.DefaultBranch
+	code_indexer.UpdateRepoIndexer(repo)
 
-	if useExternalIndexer {
-		gitReference = "/commit/"
-		code_indexer.UpdateRepoIndexer(repo)
-	}
+	testSearch(t, "/user2/repo1/search?q=Description&page=1", []string{"README.md"})
 
-	testSearch(t, "/user2/repo1/search?q=Description&page=1", gitReference, []string{"README.md"})
+	setting.Indexer.IncludePatterns = setting.IndexerGlobFromString("**.txt")
+	setting.Indexer.ExcludePatterns = setting.IndexerGlobFromString("**/y/**")
 
-	if useExternalIndexer {
-		setting.Indexer.IncludePatterns = setting.IndexerGlobFromString("**.txt")
-		setting.Indexer.ExcludePatterns = setting.IndexerGlobFromString("**/y/**")
+	repo, err = repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "glob")
+	assert.NoError(t, err)
 
-		repo, err = repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "glob")
-		assert.NoError(t, err)
+	code_indexer.UpdateRepoIndexer(repo)
 
-		code_indexer.UpdateRepoIndexer(repo)
-
-		testSearch(t, "/user2/glob/search?q=loren&page=1", gitReference, []string{"a.txt"})
-		testSearch(t, "/user2/glob/search?q=loren&page=1&t=match", gitReference, []string{"a.txt"})
-		testSearch(t, "/user2/glob/search?q=file3&page=1", gitReference, []string{"x/b.txt", "a.txt"})
-		testSearch(t, "/user2/glob/search?q=file3&page=1&t=match", gitReference, []string{"x/b.txt", "a.txt"})
-		testSearch(t, "/user2/glob/search?q=file4&page=1&t=match", gitReference, []string{"x/b.txt", "a.txt"})
-		testSearch(t, "/user2/glob/search?q=file5&page=1&t=match", gitReference, []string{"x/b.txt", "a.txt"})
-	}
+	testSearch(t, "/user2/glob/search?q=loren&page=1", []string{"a.txt"})
+	testSearch(t, "/user2/glob/search?q=loren&page=1&t=match", []string{"a.txt"})
+	testSearch(t, "/user2/glob/search?q=file3&page=1", []string{"x/b.txt", "a.txt"})
+	testSearch(t, "/user2/glob/search?q=file3&page=1&t=match", []string{"x/b.txt", "a.txt"})
+	testSearch(t, "/user2/glob/search?q=file4&page=1&t=match", []string{"x/b.txt", "a.txt"})
+	testSearch(t, "/user2/glob/search?q=file5&page=1&t=match", []string{"x/b.txt", "a.txt"})
 }
 
-func TestIndexerSearchRepo(t *testing.T) {
-	testSearchRepo(t, true)
-}
-
-func TestNoIndexerSearchRepo(t *testing.T) {
-	testSearchRepo(t, false)
-}
-
-func testSearch(t *testing.T, url, gitRef string, expected []string) {
+func testSearch(t *testing.T, url string, expected []string) {
 	req := NewRequest(t, "GET", url)
 	resp := MakeRequest(t, req, http.StatusOK)
 
-	doc := NewHTMLParser(t, resp.Body).doc.
-		Find(".repository.search").
-		Find(".repo-search-result")
-
-	filenames := resultFilenames(t, doc)
+	filenames := resultFilenames(t, NewHTMLParser(t, resp.Body))
 	assert.EqualValues(t, expected, filenames)
-
-	checkResultLinks(t, gitRef, doc)
 }