-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support repo code search without setting up an indexer (#29998)
By using git's ability, end users (especially small instance users) do not need to enable the indexer, they could also benefit from the code searching feature. Fix #29996 ![image](https://github.com/go-gitea/gitea/assets/2114189/11b7e458-88a4-480d-b4d7-72ee59406dd1) ![image](https://github.com/go-gitea/gitea/assets/2114189/0fe777d5-c95c-4288-a818-0427680805b6) --------- Co-authored-by: silverwind <[email protected]>
- Loading branch information
1 parent
90a4f9a
commit 4734d43
Showing
12 changed files
with
253 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package git | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strconv" | ||
"strings" | ||
|
||
"code.gitea.io/gitea/modules/util" | ||
) | ||
|
||
type GrepResult struct { | ||
Filename string | ||
LineNumbers []int | ||
LineCodes []string | ||
} | ||
|
||
type GrepOptions struct { | ||
RefName string | ||
ContextLineNumber int | ||
IsFuzzy bool | ||
} | ||
|
||
func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepOptions) ([]*GrepResult, error) { | ||
stdoutReader, stdoutWriter, err := os.Pipe() | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to create os pipe to grep: %w", err) | ||
} | ||
defer func() { | ||
_ = stdoutReader.Close() | ||
_ = stdoutWriter.Close() | ||
}() | ||
|
||
/* | ||
The output is like this ( "^@" means \x00): | ||
HEAD:.air.toml | ||
6^@bin = "gitea" | ||
HEAD:.changelog.yml | ||
2^@repo: go-gitea/gitea | ||
*/ | ||
var results []*GrepResult | ||
cmd := NewCommand(ctx, "grep", "--null", "--break", "--heading", "--fixed-strings", "--line-number", "--ignore-case", "--full-name") | ||
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber)) | ||
if opts.IsFuzzy { | ||
words := strings.Fields(search) | ||
for _, word := range words { | ||
cmd.AddOptionValues("-e", strings.TrimLeft(word, "-")) | ||
} | ||
} else { | ||
cmd.AddOptionValues("-e", strings.TrimLeft(search, "-")) | ||
} | ||
cmd.AddDynamicArguments(util.IfZero(opts.RefName, "HEAD")) | ||
stderr := bytes.Buffer{} | ||
err = cmd.Run(&RunOpts{ | ||
Dir: repo.Path, | ||
Stdout: stdoutWriter, | ||
Stderr: &stderr, | ||
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { | ||
_ = stdoutWriter.Close() | ||
defer stdoutReader.Close() | ||
|
||
isInBlock := false | ||
scanner := bufio.NewScanner(stdoutReader) | ||
var res *GrepResult | ||
for scanner.Scan() { | ||
line := scanner.Text() | ||
if !isInBlock { | ||
if _ /* ref */, filename, ok := strings.Cut(line, ":"); ok { | ||
isInBlock = true | ||
res = &GrepResult{Filename: filename} | ||
results = append(results, res) | ||
} | ||
continue | ||
} | ||
if line == "" { | ||
if len(results) >= 50 { | ||
cancel() | ||
break | ||
} | ||
isInBlock = false | ||
continue | ||
} | ||
if line == "--" { | ||
continue | ||
} | ||
if lineNum, lineCode, ok := strings.Cut(line, "\x00"); ok { | ||
lineNumInt, _ := strconv.Atoi(lineNum) | ||
res.LineNumbers = append(res.LineNumbers, lineNumInt) | ||
res.LineCodes = append(res.LineCodes, lineCode) | ||
} | ||
} | ||
return scanner.Err() | ||
}, | ||
}) | ||
// git grep exits with 1 if no results are found | ||
if IsErrorExitCode(err, 1) && stderr.Len() == 0 { | ||
return nil, nil | ||
} | ||
if err != nil && !errors.Is(err, context.Canceled) { | ||
return nil, fmt.Errorf("unable to run git grep: %w, stderr: %s", err, stderr.String()) | ||
} | ||
return results, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package git | ||
|
||
import ( | ||
"context" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGrepSearch(t *testing.T) { | ||
repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "language_stats_repo")) | ||
assert.NoError(t, err) | ||
defer repo.Close() | ||
|
||
res, err := GrepSearch(context.Background(), repo, "void", GrepOptions{}) | ||
assert.NoError(t, err) | ||
assert.Equal(t, []*GrepResult{ | ||
{ | ||
Filename: "java-hello/main.java", | ||
LineNumbers: []int{3}, | ||
LineCodes: []string{" public static void main(String[] args)"}, | ||
}, | ||
{ | ||
Filename: "main.vendor.java", | ||
LineNumbers: []int{3}, | ||
LineCodes: []string{" public static void main(String[] args)"}, | ||
}, | ||
}, res) | ||
|
||
res, err = GrepSearch(context.Background(), repo, "no-such-content", GrepOptions{}) | ||
assert.NoError(t, err) | ||
assert.Len(t, res, 0) | ||
|
||
res, err = GrepSearch(context.Background(), &Repository{Path: "no-such-git-repo"}, "no-such-content", GrepOptions{}) | ||
assert.Error(t, err) | ||
assert.Len(t, res, 0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.