Skip to content

Commit 1f9a9fa

Browse files
GiteaBotwxiaoguang
andauthored
Improve grep search (#30843) (#30850)
Backport #30843 by wxiaoguang Reduce the context line number to 1, make "git grep" search respect the include/exclude patter, and fix #30785 Co-authored-by: wxiaoguang <[email protected]>
1 parent 7ad2d03 commit 1f9a9fa

File tree

6 files changed

+95
-8
lines changed

6 files changed

+95
-8
lines changed

modules/git/grep.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type GrepOptions struct {
2929
ContextLineNumber int
3030
IsFuzzy bool
3131
MaxLineLength int // the maximum length of a line to parse, exceeding chars will be truncated
32+
PathspecList []string
3233
}
3334

3435
func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepOptions) ([]*GrepResult, error) {
@@ -62,6 +63,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
6263
cmd.AddOptionValues("-e", strings.TrimLeft(search, "-"))
6364
}
6465
cmd.AddDynamicArguments(util.IfZero(opts.RefName, "HEAD"))
66+
cmd.AddDashesAndList(opts.PathspecList...)
6567
opts.MaxResultLimit = util.IfZero(opts.MaxResultLimit, 50)
6668
stderr := bytes.Buffer{}
6769
err = cmd.Run(&RunOpts{

modules/git/grep_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ func TestGrepSearch(t *testing.T) {
3131
},
3232
}, res)
3333

34+
res, err = GrepSearch(context.Background(), repo, "void", GrepOptions{PathspecList: []string{":(glob)java-hello/*"}})
35+
assert.NoError(t, err)
36+
assert.Equal(t, []*GrepResult{
37+
{
38+
Filename: "java-hello/main.java",
39+
LineNumbers: []int{3},
40+
LineCodes: []string{" public static void main(String[] args)"},
41+
},
42+
}, res)
43+
44+
res, err = GrepSearch(context.Background(), repo, "void", GrepOptions{PathspecList: []string{":(glob,exclude)java-hello/*"}})
45+
assert.NoError(t, err)
46+
assert.Equal(t, []*GrepResult{
47+
{
48+
Filename: "main.vendor.java",
49+
LineNumbers: []int{3},
50+
LineCodes: []string{" public static void main(String[] args)"},
51+
},
52+
}, res)
53+
3454
res, err = GrepSearch(context.Background(), repo, "void", GrepOptions{MaxResultLimit: 1})
3555
assert.NoError(t, err)
3656
assert.Equal(t, []*GrepResult{

modules/setting/glob.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package setting
5+
6+
import "github.com/gobwas/glob"
7+
8+
type GlobMatcher struct {
9+
compiledGlob glob.Glob
10+
patternString string
11+
}
12+
13+
var _ glob.Glob = (*GlobMatcher)(nil)
14+
15+
func (g *GlobMatcher) Match(s string) bool {
16+
return g.compiledGlob.Match(s)
17+
}
18+
19+
func (g *GlobMatcher) PatternString() string {
20+
return g.patternString
21+
}
22+
23+
func GlobMatcherCompile(pattern string, separators ...rune) (*GlobMatcher, error) {
24+
g, err := glob.Compile(pattern, separators...)
25+
if err != nil {
26+
return nil, err
27+
}
28+
return &GlobMatcher{
29+
compiledGlob: g,
30+
patternString: pattern,
31+
}, nil
32+
}

modules/setting/indexer.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import (
1010
"time"
1111

1212
"code.gitea.io/gitea/modules/log"
13-
14-
"github.com/gobwas/glob"
1513
)
1614

1715
// Indexer settings
@@ -30,8 +28,8 @@ var Indexer = struct {
3028
RepoConnStr string
3129
RepoIndexerName string
3230
MaxIndexerFileSize int64
33-
IncludePatterns []glob.Glob
34-
ExcludePatterns []glob.Glob
31+
IncludePatterns []*GlobMatcher
32+
ExcludePatterns []*GlobMatcher
3533
ExcludeVendored bool
3634
}{
3735
IssueType: "bleve",
@@ -93,12 +91,12 @@ func loadIndexerFrom(rootCfg ConfigProvider) {
9391
}
9492

9593
// IndexerGlobFromString parses a comma separated list of patterns and returns a glob.Glob slice suited for repo indexing
96-
func IndexerGlobFromString(globstr string) []glob.Glob {
97-
extarr := make([]glob.Glob, 0, 10)
94+
func IndexerGlobFromString(globstr string) []*GlobMatcher {
95+
extarr := make([]*GlobMatcher, 0, 10)
9896
for _, expr := range strings.Split(strings.ToLower(globstr), ",") {
9997
expr = strings.TrimSpace(expr)
10098
if expr != "" {
101-
if g, err := glob.Compile(expr, '.', '/'); err != nil {
99+
if g, err := GlobMatcherCompile(expr, '.', '/'); err != nil {
102100
log.Info("Invalid glob expression '%s' (skipped): %v", expr, err)
103101
} else {
104102
extarr = append(extarr, g)

routers/web/repo/search.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ import (
1717

1818
const tplSearch base.TplName = "repo/search"
1919

20+
func indexSettingToGitGrepPathspecList() (list []string) {
21+
for _, expr := range setting.Indexer.IncludePatterns {
22+
list = append(list, ":(glob)"+expr.PatternString())
23+
}
24+
for _, expr := range setting.Indexer.ExcludePatterns {
25+
list = append(list, ":(glob,exclude)"+expr.PatternString())
26+
}
27+
return list
28+
}
29+
2030
// Search render repository search page
2131
func Search(ctx *context.Context) {
2232
language := ctx.FormTrim("l")
@@ -65,8 +75,14 @@ func Search(ctx *context.Context) {
6575
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
6676
}
6777
} else {
68-
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{ContextLineNumber: 3, IsFuzzy: isFuzzy})
78+
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{
79+
ContextLineNumber: 1,
80+
IsFuzzy: isFuzzy,
81+
RefName: git.RefNameFromBranch(ctx.Repo.BranchName).String(), // BranchName should be default branch or the first existing branch
82+
PathspecList: indexSettingToGitGrepPathspecList(),
83+
})
6984
if err != nil {
85+
// TODO: if no branch exists, it reports: exit status 128, fatal: this operation must be run in a work tree.
7086
ctx.ServerError("GrepSearch", err)
7187
return
7288
}

routers/web/repo/search_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package repo
5+
6+
import (
7+
"testing"
8+
9+
"code.gitea.io/gitea/modules/setting"
10+
"code.gitea.io/gitea/modules/test"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestIndexSettingToGitGrepPathspecList(t *testing.T) {
16+
defer test.MockVariableValue(&setting.Indexer.IncludePatterns, setting.IndexerGlobFromString("a"))()
17+
defer test.MockVariableValue(&setting.Indexer.ExcludePatterns, setting.IndexerGlobFromString("b"))()
18+
assert.Equal(t, []string{":(glob)a", ":(glob,exclude)b"}, indexSettingToGitGrepPathspecList())
19+
}

0 commit comments

Comments
 (0)