mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-13 06:20:24 +00:00
chore: minor code cleanup in search (#10549)
Minor code cleanup for code/issue search. Mostly breaking up the common functionality into separate functions :) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10549 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com> Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
This commit is contained in:
parent
537a802125
commit
b1adc7d931
6 changed files with 113 additions and 106 deletions
|
|
@ -7,6 +7,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"html/template"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"forgejo.org/modules/highlight"
|
||||
|
|
@ -46,6 +47,19 @@ const (
|
|||
SearchModeFuzzy = internal.CodeSearchModeFuzzy
|
||||
)
|
||||
|
||||
type Results []*Result
|
||||
|
||||
// Get the set of repo IDs from a list of search results
|
||||
func (res Results) RepoIDs() []int64 {
|
||||
ids := make([]int64, len(res))
|
||||
for _, r := range res {
|
||||
if !slices.Contains(ids, r.RepoID) {
|
||||
ids = append(ids, r.RepoID)
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func indices(content string, selectionStartIndex, selectionEndIndex int) (int, int) {
|
||||
startIndex := selectionStartIndex
|
||||
numLinesBefore := 0
|
||||
|
|
@ -218,7 +232,7 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res
|
|||
}
|
||||
|
||||
// PerformSearch perform a search on a repository
|
||||
func PerformSearch(ctx context.Context, opts *SearchOptions) (int, []*Result, []*SearchResultLanguages, error) {
|
||||
func PerformSearch(ctx context.Context, opts *SearchOptions) (int, Results, []*SearchResultLanguages, error) {
|
||||
if opts == nil || len(opts.Keyword) == 0 {
|
||||
return 0, nil, nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,21 +233,19 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
}
|
||||
|
||||
var keywords []string
|
||||
if len(options.Tokens) != 0 {
|
||||
for _, token := range options.Tokens {
|
||||
if !token.Fuzzy {
|
||||
// to make it a phrase search, we have to quote the keyword(s)
|
||||
// https://www.meilisearch.com/docs/reference/api/search#phrase-search
|
||||
token.Term = doubleQuoteKeyword(token.Term)
|
||||
}
|
||||
|
||||
// internal.BoolOptShould (Default, requires no modifications)
|
||||
// internal.BoolOptMust (Not supported by meilisearch)
|
||||
if token.Kind == internal.BoolOptNot {
|
||||
token.Term = "-" + token.Term
|
||||
}
|
||||
keywords = append(keywords, token.Term)
|
||||
for _, token := range options.Tokens {
|
||||
if !token.Fuzzy {
|
||||
// to make it a phrase search, we have to quote the keyword(s)
|
||||
// https://www.meilisearch.com/docs/reference/api/search#phrase-search
|
||||
token.Term = doubleQuoteKeyword(token.Term)
|
||||
}
|
||||
|
||||
// internal.BoolOptShould (Default, requires no modifications)
|
||||
// internal.BoolOptMust (Not supported by meilisearch)
|
||||
if token.Kind == internal.BoolOptNot {
|
||||
token.Term = "-" + token.Term
|
||||
}
|
||||
keywords = append(keywords, token.Term)
|
||||
}
|
||||
|
||||
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).
|
||||
|
|
|
|||
55
routers/common/search.go
Normal file
55
routers/common/search.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
code_indexer "forgejo.org/modules/indexer/code"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/services/context"
|
||||
)
|
||||
|
||||
type CodeSearchOptions struct {
|
||||
Language, Keyword, Path string
|
||||
}
|
||||
|
||||
// Parses the common code search options from the context
|
||||
// This functions takes care of the following ctx.Data fields
|
||||
// - Keyword
|
||||
// - Language
|
||||
// - CodeSearchPath
|
||||
func InitCodeSearchOptions(ctx *context.Context) (opts CodeSearchOptions) {
|
||||
opts.Language = ctx.FormTrim("l")
|
||||
opts.Keyword = ctx.FormTrim("q")
|
||||
opts.Path = ctx.FormTrim("path")
|
||||
|
||||
ctx.Data["Keyword"] = opts.Keyword
|
||||
ctx.Data["Language"] = opts.Language
|
||||
ctx.Data["CodeSearchPath"] = opts.Path
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
// Returns the indexer mode to be used by the code indexer
|
||||
// Also sets the ctx.Data fields "CodeSearchMode" and "CodeSearchOptions"
|
||||
//
|
||||
// NOTE:
|
||||
// This is seperate from `InitCodeSearchOptions`
|
||||
// since this is specific the indexer and only used
|
||||
// where git-grep is not available.
|
||||
func CodeSearchIndexerMode(ctx *context.Context) (mode code_indexer.SearchMode) {
|
||||
mode = code_indexer.SearchModeExact
|
||||
if m := ctx.FormTrim("mode"); m == "union" {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
} else if m == "fuzzy" || ctx.FormBool("fuzzy") {
|
||||
if setting.Indexer.RepoIndexerEnableFuzzy {
|
||||
mode = code_indexer.SearchModeFuzzy
|
||||
} else {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
}
|
||||
}
|
||||
ctx.Data["CodeSearchOptions"] = code_indexer.CodeSearchOptions
|
||||
ctx.Data["CodeSearchMode"] = mode.String()
|
||||
|
||||
return mode
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package explore
|
||||
|
|
@ -11,6 +12,7 @@ import (
|
|||
"forgejo.org/modules/base"
|
||||
code_indexer "forgejo.org/modules/indexer/code"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/routers/common"
|
||||
"forgejo.org/services/context"
|
||||
)
|
||||
|
||||
|
|
@ -32,29 +34,12 @@ func Code(ctx *context.Context) {
|
|||
ctx.Data["Title"] = ctx.Tr("explore")
|
||||
ctx.Data["PageIsExplore"] = true
|
||||
ctx.Data["PageIsExploreCode"] = true
|
||||
|
||||
language := ctx.FormTrim("l")
|
||||
keyword := ctx.FormTrim("q")
|
||||
path := ctx.FormTrim("path")
|
||||
|
||||
mode := code_indexer.SearchModeExact
|
||||
if m := ctx.FormTrim("mode"); m == "union" {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
} else if m == "fuzzy" || ctx.FormBool("fuzzy") {
|
||||
if setting.Indexer.RepoIndexerEnableFuzzy {
|
||||
mode = code_indexer.SearchModeFuzzy
|
||||
} else {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["Language"] = language
|
||||
ctx.Data["CodeSearchOptions"] = code_indexer.CodeSearchOptions
|
||||
ctx.Data["CodeSearchMode"] = mode.String()
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
||||
if keyword == "" {
|
||||
opts := common.InitCodeSearchOptions(ctx)
|
||||
mode := common.CodeSearchIndexerMode(ctx)
|
||||
|
||||
if opts.Keyword == "" {
|
||||
ctx.HTML(http.StatusOK, tplExploreCode)
|
||||
return
|
||||
}
|
||||
|
|
@ -84,17 +69,17 @@ func Code(ctx *context.Context) {
|
|||
|
||||
var (
|
||||
total int
|
||||
searchResults []*code_indexer.Result
|
||||
searchResults code_indexer.Results
|
||||
searchResultLanguages []*code_indexer.SearchResultLanguages
|
||||
)
|
||||
|
||||
if (len(repoIDs) > 0) || isAdmin {
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
Keyword: opts.Keyword,
|
||||
Mode: mode,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Language: opts.Language,
|
||||
Filename: opts.Path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
|
@ -110,20 +95,7 @@ func Code(ctx *context.Context) {
|
|||
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
|
||||
}
|
||||
|
||||
loadRepoIDs := make([]int64, 0, len(searchResults))
|
||||
for _, result := range searchResults {
|
||||
var find bool
|
||||
for _, id := range loadRepoIDs {
|
||||
if id == result.RepoID {
|
||||
find = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
loadRepoIDs = append(loadRepoIDs, result.RepoID)
|
||||
}
|
||||
}
|
||||
|
||||
loadRepoIDs := searchResults.RepoIDs()
|
||||
repoMaps, err := repo_model.GetRepositoriesMapByIDs(ctx, loadRepoIDs)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepositoriesMapByIDs", err)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
|
@ -12,6 +13,7 @@ import (
|
|||
"forgejo.org/modules/git"
|
||||
code_indexer "forgejo.org/modules/indexer/code"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/routers/common"
|
||||
"forgejo.org/services/context"
|
||||
)
|
||||
|
||||
|
|
@ -62,10 +64,7 @@ func (m searchMode) ToGitGrep() git.GrepMode {
|
|||
|
||||
// Search render repository search page
|
||||
func Search(ctx *context.Context) {
|
||||
language := ctx.FormTrim("l")
|
||||
keyword := ctx.FormTrim("q")
|
||||
|
||||
path := ctx.FormTrim("path")
|
||||
opts := common.InitCodeSearchOptions(ctx)
|
||||
mode := ExactSearchMode
|
||||
if modeStr := ctx.FormString("mode"); len(modeStr) > 0 {
|
||||
mode = searchModeFromString(modeStr)
|
||||
|
|
@ -73,9 +72,6 @@ func Search(ctx *context.Context) {
|
|||
mode = UnionSearchMode
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["Language"] = language
|
||||
ctx.Data["CodeSearchPath"] = path
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
ctx.Data["CodeIndexerDisabled"] = !setting.Indexer.RepoIndexerEnabled
|
||||
if setting.Indexer.RepoIndexerEnabled {
|
||||
|
|
@ -84,7 +80,7 @@ func Search(ctx *context.Context) {
|
|||
ctx.Data["CodeSearchOptions"] = git.GrepSearchOptions
|
||||
}
|
||||
|
||||
if keyword == "" {
|
||||
if opts.Keyword == "" {
|
||||
ctx.HTML(http.StatusOK, tplSearch)
|
||||
return
|
||||
}
|
||||
|
|
@ -104,10 +100,10 @@ func Search(ctx *context.Context) {
|
|||
var err error
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
Keyword: keyword,
|
||||
Keyword: opts.Keyword,
|
||||
Mode: m,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Language: opts.Language,
|
||||
Filename: opts.Path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
|
@ -126,10 +122,10 @@ func Search(ctx *context.Context) {
|
|||
m := mode.ToGitGrep()
|
||||
ctx.Data["CodeSearchMode"] = m.String()
|
||||
|
||||
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{
|
||||
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, opts.Keyword, git.GrepOptions{
|
||||
ContextLineNumber: 1,
|
||||
RefName: ctx.Repo.RefName,
|
||||
Filename: path,
|
||||
Filename: opts.Path,
|
||||
Mode: m,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
|
@ -11,6 +12,7 @@ import (
|
|||
"forgejo.org/modules/base"
|
||||
code_indexer "forgejo.org/modules/indexer/code"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/routers/common"
|
||||
shared_user "forgejo.org/routers/web/shared/user"
|
||||
"forgejo.org/services/context"
|
||||
)
|
||||
|
|
@ -35,30 +37,13 @@ func CodeSearch(ctx *context.Context) {
|
|||
|
||||
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
ctx.Data["IsCodePage"] = true
|
||||
ctx.Data["Title"] = ctx.Tr("explore.code")
|
||||
|
||||
language := ctx.FormTrim("l")
|
||||
keyword := ctx.FormTrim("q")
|
||||
path := ctx.FormTrim("path")
|
||||
opts := common.InitCodeSearchOptions(ctx)
|
||||
mode := common.CodeSearchIndexerMode(ctx)
|
||||
|
||||
mode := code_indexer.SearchModeExact
|
||||
if m := ctx.FormTrim("mode"); m == "union" {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
} else if m == "fuzzy" || ctx.FormBool("fuzzy") {
|
||||
if setting.Indexer.RepoIndexerEnableFuzzy {
|
||||
mode = code_indexer.SearchModeFuzzy
|
||||
} else {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["Language"] = language
|
||||
ctx.Data["CodeSearchOptions"] = code_indexer.CodeSearchOptions
|
||||
ctx.Data["CodeSearchMode"] = mode.String()
|
||||
ctx.Data["IsCodePage"] = true
|
||||
|
||||
if keyword == "" {
|
||||
if opts.Keyword == "" {
|
||||
ctx.HTML(http.StatusOK, tplUserCode)
|
||||
return
|
||||
}
|
||||
|
|
@ -81,17 +66,17 @@ func CodeSearch(ctx *context.Context) {
|
|||
|
||||
var (
|
||||
total int
|
||||
searchResults []*code_indexer.Result
|
||||
searchResults code_indexer.Results
|
||||
searchResultLanguages []*code_indexer.SearchResultLanguages
|
||||
)
|
||||
|
||||
if len(repoIDs) > 0 {
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
Keyword: opts.Keyword,
|
||||
Mode: mode,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Language: opts.Language,
|
||||
Filename: opts.Path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
|
@ -107,20 +92,7 @@ func CodeSearch(ctx *context.Context) {
|
|||
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
|
||||
}
|
||||
|
||||
loadRepoIDs := make([]int64, 0, len(searchResults))
|
||||
for _, result := range searchResults {
|
||||
var find bool
|
||||
for _, id := range loadRepoIDs {
|
||||
if id == result.RepoID {
|
||||
find = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
loadRepoIDs = append(loadRepoIDs, result.RepoID)
|
||||
}
|
||||
}
|
||||
|
||||
loadRepoIDs := searchResults.RepoIDs()
|
||||
repoMaps, err := repo_model.GetRepositoriesMapByIDs(ctx, loadRepoIDs)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepositoriesMapByIDs", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue