feat: filepath filter for code search (#6143)
Added support for searching content in a specific directory or file. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6143 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: 0ko <0ko@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
bb88e1daf8
commit
ee214cb886
19 changed files with 342 additions and 61 deletions
|
@ -36,13 +36,15 @@ const (
|
|||
RegExpGrepMode
|
||||
)
|
||||
|
||||
var GrepSearchOptions = [3]string{"exact", "union", "regexp"}
|
||||
|
||||
type GrepOptions struct {
|
||||
RefName string
|
||||
MaxResultLimit int
|
||||
MatchesPerFile int // >= git 2.38
|
||||
ContextLineNumber int
|
||||
Mode grepMode
|
||||
PathSpec []setting.Glob
|
||||
Filename string
|
||||
}
|
||||
|
||||
func (opts *GrepOptions) ensureDefaults() {
|
||||
|
@ -112,12 +114,38 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
|||
}
|
||||
|
||||
// pathspec
|
||||
files := make([]string, 0,
|
||||
len(setting.Indexer.IncludePatterns)+
|
||||
len(setting.Indexer.ExcludePatterns)+
|
||||
len(opts.PathSpec))
|
||||
for _, expr := range append(setting.Indexer.IncludePatterns, opts.PathSpec...) {
|
||||
files = append(files, ":"+expr.Pattern())
|
||||
includeLen := len(setting.Indexer.IncludePatterns)
|
||||
if len(opts.Filename) > 0 {
|
||||
includeLen = 1
|
||||
}
|
||||
files := make([]string, 0, len(setting.Indexer.ExcludePatterns)+includeLen)
|
||||
if len(opts.Filename) > 0 && len(setting.Indexer.IncludePatterns) > 0 {
|
||||
// if the both a global include pattern and the per search path is defined
|
||||
// we only include results where the path matches the globally set pattern
|
||||
// (eg, global pattern = "src/**" and path = "node_modules/")
|
||||
|
||||
// FIXME: this is a bit too restrictive, and fails to consider cases where the
|
||||
// gloabally set include pattern refers to a file than a directory
|
||||
// (eg, global pattern = "**.go" and path = "modules/git")
|
||||
exprMatched := false
|
||||
for _, expr := range setting.Indexer.IncludePatterns {
|
||||
if expr.Match(opts.Filename) {
|
||||
files = append(files, ":(literal)"+opts.Filename)
|
||||
exprMatched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exprMatched {
|
||||
log.Warn("git-grep: filepath %s does not match any include pattern", opts.Filename)
|
||||
}
|
||||
} else if len(opts.Filename) > 0 {
|
||||
// if the path is only set we just include results that matches it
|
||||
files = append(files, ":(literal)"+opts.Filename)
|
||||
} else {
|
||||
// otherwise if global include patterns are set include results that strictly match them
|
||||
for _, expr := range setting.Indexer.IncludePatterns {
|
||||
files = append(files, ":"+expr.Pattern())
|
||||
}
|
||||
}
|
||||
for _, expr := range setting.Indexer.ExcludePatterns {
|
||||
files = append(files, ":^"+expr.Pattern())
|
||||
|
|
|
@ -89,6 +89,20 @@ func TestGrepSearch(t *testing.T) {
|
|||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(context.Background(), repo, "world", GrepOptions{
|
||||
MatchesPerFile: 1,
|
||||
Filename: "java-hello/",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []*GrepResult{
|
||||
{
|
||||
Filename: "java-hello/main.java",
|
||||
LineNumbers: []int{1},
|
||||
LineCodes: []string{"public class HelloWorld"},
|
||||
HighlightedRanges: [][3]int{{0, 18, 23}},
|
||||
},
|
||||
}, res)
|
||||
|
||||
res, err = GrepSearch(context.Background(), repo, "no-such-content", GrepOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, res)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue