mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-13 12:28:02 +00:00
Adds GitHub-style code search endpoints and makes code search behave the
same in the web UI and the API, whether it runs on git grep, bleve or
Elasticsearch.
- `GET /repos/{owner}/{repo}/code/search` searches any branch, tag or
commit with git grep, so it works without the code indexer.
- `GET /search/code` searches the default branches of all accessible
repositories with the code indexer.
- One query syntax everywhere: every term must match a file's content or
path, case-insensitively. It supports `"phrases"`, `/regexp/` (git grep
only) and the `path:`, `language:`, `repo:`, `user:` and `org:`
qualifiers. Invalid queries return an error.
- All engines apply the same include, exclude, vendored and size rules,
and return every match. The web UI shows them as multiple snippets per
file with the matched text highlighted.
<img width="359" height="295" alt="image"
src="https://github.com/user-attachments/assets/59b7aa66-b1dc-4938-9ef9-66668ae08d7c"
/>
Fixes: https://github.com/go-gitea/gitea/issues/10706
Fixed: https://github.com/go-gitea/gitea/issues/15841
Fixes: https://github.com/go-gitea/gitea/issues/31375
Related: https://gitea.com/gitea/gitea-mcp/issues/280
Docs: https://gitea.com/gitea/docs/pulls/615
AI usage disclosure: Yes, I used AI to write code, review changes and
verify the factuality of the overview I provided. I take full
responsibility for the code in this PR.
---------
Co-authored-by: silverwind <me@silverwind.io>
45 lines
1.5 KiB
Go
45 lines
1.5 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package code
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gitea.dev/models/db"
|
|
"gitea.dev/models/unittest"
|
|
"gitea.dev/modules/indexer/code/bleve"
|
|
"gitea.dev/modules/indexer/code/internal"
|
|
|
|
_ "gitea.dev/models"
|
|
_ "gitea.dev/models/actions"
|
|
_ "gitea.dev/models/activities"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestMain(m *testing.M) { unittest.MainTest(m) }
|
|
|
|
func TestIndexRepository(t *testing.T) {
|
|
unittest.PrepareTestEnv(t)
|
|
idx := bleve.NewIndexer(t.TempDir())
|
|
_, err := idx.Init(t.Context())
|
|
require.NoError(t, err)
|
|
defer idx.Close()
|
|
require.NoError(t, index(t.Context(), idx, 1))
|
|
var indexer internal.Indexer = idx
|
|
previousIndexer := globalIndexer.Load()
|
|
defer globalIndexer.Store(previousIndexer)
|
|
globalIndexer.Store(&indexer)
|
|
total, results, _, err := PerformSearch(t.Context(), &SearchOptions{Terms: []string{"Description"}, Paginator: &db.ListOptions{Page: 1, PageSize: 1}})
|
|
require.NoError(t, err)
|
|
assert.Positive(t, total)
|
|
require.Len(t, results, 1)
|
|
assert.Equal(t, []*ResultFragment{{StartLine: 2, Content: "\nDescription for repo1", Matches: []MatchRange{{Start: 1, End: 12}}}}, BuildResultFragments(results[0].Content, results[0].ContentMatches))
|
|
require.NoError(t, idx.Delete(t.Context(), 1))
|
|
total, _, _, err = idx.Search(t.Context(), &internal.SearchOptions{Terms: []string{"Description"}, Paginator: &db.ListOptions{Page: 1, PageSize: 1}})
|
|
require.NoError(t, err)
|
|
assert.Zero(t, total)
|
|
}
|