mirror of
https://github.com/go-gitea/gitea.git
synced 2024-09-01 14:56:30 +00:00
144 lines
3.3 KiB
Go
144 lines
3.3 KiB
Go
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package explore
|
|
|
|
import (
|
|
"net/http"
|
|
"slices"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
code_indexer "code.gitea.io/gitea/modules/indexer/code"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
"code.gitea.io/gitea/services/context"
|
|
"code.gitea.io/gitea/services/convert"
|
|
)
|
|
|
|
// Code explore code
|
|
func Code(ctx *context.APIContext) {
|
|
// swagger:operation GET /explore/code explore codeSearch
|
|
// ---
|
|
// summary: Search for code
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: q
|
|
// in: query
|
|
// description: keyword
|
|
// type: string
|
|
// - name: page
|
|
// in: query
|
|
// description: page number of results to return (1-based)
|
|
// type: integer
|
|
// - name: fuzzy
|
|
// in: query
|
|
// description: whether to search fuzzy or strict (defaults to true)
|
|
// type: boolean
|
|
// responses:
|
|
// "200":
|
|
// description: "SearchResults of a successful search"
|
|
// schema:
|
|
// "$ref": "#/definitions/ExploreCodeResult"
|
|
if !setting.Indexer.RepoIndexerEnabled {
|
|
ctx.NotFound("Indexer not enabled")
|
|
return
|
|
}
|
|
|
|
keyword := ctx.FormTrim("q")
|
|
|
|
isFuzzy := ctx.FormOptionalBool("fuzzy").ValueOrDefault(true)
|
|
|
|
if keyword == "" {
|
|
ctx.JSON(http.StatusOK, api.ExploreCodeResult{
|
|
Total: 0,
|
|
Results: make([]api.ExploreCodeSearchItem, 0),
|
|
})
|
|
return
|
|
}
|
|
|
|
page := ctx.FormInt("page")
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
|
|
var (
|
|
repoIDs []int64
|
|
err error
|
|
isAdmin bool
|
|
)
|
|
if ctx.Doer != nil {
|
|
isAdmin = ctx.Doer.IsAdmin
|
|
}
|
|
|
|
if ctx.Doer == nil || !isAdmin {
|
|
repoIDs, err = repo_model.FindUserCodeAccessibleRepoIDs(ctx, ctx.Doer)
|
|
if err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, api.SearchError{
|
|
OK: false,
|
|
Error: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
var (
|
|
total int
|
|
searchResults []*code_indexer.Result
|
|
repoMaps map[int64]*repo_model.Repository
|
|
)
|
|
|
|
if (len(repoIDs) > 0) || isAdmin {
|
|
total, searchResults, _, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
|
RepoIDs: repoIDs,
|
|
Keyword: keyword,
|
|
IsKeywordFuzzy: isFuzzy,
|
|
IsHTMLSafe: false,
|
|
Paginator: &db.ListOptions{
|
|
Page: page,
|
|
PageSize: setting.API.DefaultPagingNum,
|
|
},
|
|
})
|
|
if err != nil {
|
|
if code_indexer.IsAvailable(ctx) {
|
|
ctx.JSON(http.StatusInternalServerError, api.SearchError{
|
|
OK: false,
|
|
Error: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
loadRepoIDs := make([]int64, 0, len(searchResults))
|
|
for _, result := range searchResults {
|
|
if !slices.Contains(loadRepoIDs, result.RepoID) {
|
|
loadRepoIDs = append(loadRepoIDs, result.RepoID)
|
|
}
|
|
}
|
|
|
|
repoMaps, err = repo_model.GetRepositoriesMapByIDs(ctx, loadRepoIDs)
|
|
if err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, api.SearchError{
|
|
OK: false,
|
|
Error: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
if len(loadRepoIDs) != len(repoMaps) {
|
|
// Remove deleted repos from search results
|
|
cleanedSearchResults := make([]*code_indexer.Result, 0, len(repoMaps))
|
|
for _, sr := range searchResults {
|
|
if _, found := repoMaps[sr.RepoID]; found {
|
|
cleanedSearchResults = append(cleanedSearchResults, sr)
|
|
}
|
|
}
|
|
|
|
searchResults = cleanedSearchResults
|
|
}
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, convert.ToExploreCodeSearchResults(total, searchResults, repoMaps))
|
|
}
|