loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[FEAT] support searching non default branches/tags when using git-grep (#3654)

resolves https://codeberg.org/forgejo/forgejo/pulls/3639#issuecomment-1806676 and https://codeberg.org/forgejo/forgejo/pulls/3513#issuecomment-1794990

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3654
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>

authored by

Shiny Nematoda
Shiny Nematoda
and committed by
Earl Warren
b6ca8abc 9b4452fd

+101 -26
+9 -3
modules/git/grep.go
··· 29 29 MaxResultLimit int 30 30 ContextLineNumber int 31 31 IsFuzzy bool 32 + PathSpec []setting.Glob 32 33 } 33 34 34 35 func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepOptions) ([]*GrepResult, error) { ··· 61 62 } else { 62 63 cmd.AddOptionValues("-e", strings.TrimLeft(search, "-")) 63 64 } 65 + 64 66 // pathspec 65 - files := make([]string, 0, len(setting.Indexer.IncludePatterns)+len(setting.Indexer.ExcludePatterns)) 66 - for _, expr := range setting.Indexer.IncludePatterns { 67 - files = append(files, expr.Pattern()) 67 + files := make([]string, 0, 68 + len(setting.Indexer.IncludePatterns)+ 69 + len(setting.Indexer.ExcludePatterns)+ 70 + len(opts.PathSpec)) 71 + for _, expr := range append(setting.Indexer.IncludePatterns, opts.PathSpec...) { 72 + files = append(files, ":"+expr.Pattern()) 68 73 } 69 74 for _, expr := range setting.Indexer.ExcludePatterns { 70 75 files = append(files, ":^"+expr.Pattern()) 71 76 } 72 77 cmd.AddDynamicArguments(cmp.Or(opts.RefName, "HEAD")).AddDashesAndList(files...) 78 + 73 79 opts.MaxResultLimit = cmp.Or(opts.MaxResultLimit, 50) 74 80 stderr := bytes.Buffer{} 75 81 err = cmd.Run(&RunOpts{
+30
modules/git/grep_test.go
··· 76 76 assert.Len(t, res, 1) 77 77 assert.Len(t, res[0].LineCodes[0], 65*1024) 78 78 } 79 + 80 + func TestGrepRefs(t *testing.T) { 81 + tmpDir := t.TempDir() 82 + 83 + err := InitRepository(DefaultContext, tmpDir, false, Sha1ObjectFormat.Name()) 84 + assert.NoError(t, err) 85 + 86 + gitRepo, err := openRepositoryWithDefaultContext(tmpDir) 87 + assert.NoError(t, err) 88 + defer gitRepo.Close() 89 + 90 + assert.NoError(t, os.WriteFile(path.Join(tmpDir, "README.md"), []byte{'A'}, 0o666)) 91 + assert.NoError(t, AddChanges(tmpDir, true)) 92 + 93 + err = CommitChanges(tmpDir, CommitChangesOptions{Message: "add A"}) 94 + assert.NoError(t, err) 95 + 96 + assert.NoError(t, gitRepo.CreateTag("v1", "HEAD")) 97 + 98 + assert.NoError(t, os.WriteFile(path.Join(tmpDir, "README.md"), []byte{'A', 'B', 'C', 'D'}, 0o666)) 99 + assert.NoError(t, AddChanges(tmpDir, true)) 100 + 101 + err = CommitChanges(tmpDir, CommitChangesOptions{Message: "add BCD"}) 102 + assert.NoError(t, err) 103 + 104 + res, err := GrepSearch(context.Background(), gitRepo, "a", GrepOptions{RefName: "v1"}) 105 + assert.NoError(t, err) 106 + assert.Len(t, res, 1) 107 + assert.Equal(t, res[0].LineCodes[0], "A") 108 + }
+1
release-notes/8.0.0/feat/3654.md
··· 1 + Code Search for non-default branches and tags when repository indexer is disabled
+5 -1
routers/web/repo/search.go
··· 64 64 ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx) 65 65 } 66 66 } else { 67 - res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{ContextLineNumber: 3, IsFuzzy: isFuzzy}) 67 + res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{ 68 + ContextLineNumber: 1, 69 + IsFuzzy: isFuzzy, 70 + RefName: ctx.Repo.RefName, 71 + }) 68 72 if err != nil { 69 73 ctx.ServerError("GrepSearch", err) 70 74 return
+1
routers/web/repo/view.go
··· 1140 1140 ctx.Data["TreeLink"] = treeLink 1141 1141 ctx.Data["TreeNames"] = treeNames 1142 1142 ctx.Data["BranchLink"] = branchLink 1143 + ctx.Data["CodeIndexerDisabled"] = !setting.Indexer.RepoIndexerEnabled 1143 1144 ctx.HTML(http.StatusOK, tplRepoHome) 1144 1145 } 1145 1146
+10 -4
routers/web/web.go
··· 1570 1570 1571 1571 m.Group("/{username}/{reponame}", func() { 1572 1572 if !setting.Repository.DisableStars { 1573 - m.Get("/stars", repo.Stars) 1573 + m.Get("/stars", context.RepoRef(), repo.Stars) 1574 1574 } 1575 - m.Get("/watchers", repo.Watchers) 1576 - m.Get("/search", reqRepoCodeReader, repo.Search) 1577 - }, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes()) 1575 + m.Get("/watchers", context.RepoRef(), repo.Watchers) 1576 + m.Group("/search", func() { 1577 + m.Get("", context.RepoRef(), repo.Search) 1578 + if !setting.Indexer.RepoIndexerEnabled { 1579 + m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Search) 1580 + m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Search) 1581 + } 1582 + }, reqRepoCodeReader) 1583 + }, ignSignIn, context.RepoAssignment, context.UnitTypes()) 1578 1584 1579 1585 m.Group("/{username}", func() { 1580 1586 m.Group("/{reponame}", func() {
+4 -13
templates/repo/home.tmpl
··· 8 8 <div class="repo-description"> 9 9 <div id="repo-desc" class="gt-word-break tw-text-16"> 10 10 {{$description := .Repository.DescriptionHTML $.Context}} 11 - {{if $description}}<span class="description">{{$description | RenderCodeBlock}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{ctx.Locale.Tr "repo.no_desc"}}</span>{{end}} 12 - <a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a> 11 + {{if $description}}<span class="description">{{$description | RenderCodeBlock}}</span>{{else}}<span class="no-description text-italic">{{ctx.Locale.Tr "repo.no_desc"}}</span>{{end}} 12 + {{if .Repository.Website}}<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}} 13 13 </div> 14 - <form class="ignore-dirty" action="{{.RepoLink}}/search" method="get"> 14 + <form class="ignore-dirty" action="{{.RepoLink}}/search/{{if .CodeIndexerDisabled}}{{.BranchNameSubURL}}{{end}}" method="get" data-test-tag="codesearch"> 15 15 <div class="ui small action input"> 16 16 <input name="q" value="{{.Keyword}}" placeholder="{{ctx.Locale.Tr "search.code_kind"}}"> 17 17 {{template "shared/search/button"}} ··· 106 106 {{ctx.Locale.Tr "repo.use_template"}} 107 107 </a> 108 108 {{end}} 109 - {{if $isHomepage}} 110 - {{/* only show the "code search" on the repo home page, it only does global search, 111 - so do not show it when viewing file or directory to avoid misleading users (it doesn't search in a directory) */}} 112 - <form class="ignore-dirty" action="{{.RepoLink}}/search" method="get"> 113 - <div class="ui small action input"> 114 - <input name="q" placeholder="{{ctx.Locale.Tr "search.code_kind"}}"> 115 - {{template "shared/search/button"}} 116 - </div> 117 - </form> 118 - {{else}} 109 + {{if (not $isHomepage)}} 119 110 <span class="breadcrumb repo-path tw-ml-1"> 120 111 <a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a> 121 112 {{- range $i, $v := .TreeNames -}}
+9
tests/integration/repo_search_test.go
··· 12 12 code_indexer "code.gitea.io/gitea/modules/indexer/code" 13 13 "code.gitea.io/gitea/modules/setting" 14 14 "code.gitea.io/gitea/modules/test" 15 + "code.gitea.io/gitea/routers" 15 16 "code.gitea.io/gitea/tests" 16 17 17 18 "github.com/PuerkitoBio/goquery" ··· 38 39 func testSearchRepo(t *testing.T, indexer bool) { 39 40 defer tests.PrepareTestEnv(t)() 40 41 defer test.MockVariableValue(&setting.Indexer.RepoIndexerEnabled, indexer)() 42 + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() 41 43 42 44 repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1") 43 45 assert.NoError(t, err) ··· 47 49 } 48 50 49 51 testSearch(t, "/user2/repo1/search?q=Description&page=1", []string{"README.md"}, indexer) 52 + 53 + req := NewRequest(t, "HEAD", "/user2/repo1/search/branch/"+repo.DefaultBranch) 54 + if indexer { 55 + MakeRequest(t, req, http.StatusNotFound) 56 + } else { 57 + MakeRequest(t, req, http.StatusOK) 58 + } 50 59 51 60 defer test.MockVariableValue(&setting.Indexer.IncludePatterns, setting.IndexerGlobFromString("**.txt"))() 52 61 defer test.MockVariableValue(&setting.Indexer.ExcludePatterns, setting.IndexerGlobFromString("**/y/**"))()
+32 -5
tests/integration/repo_test.go
··· 190 190 191 191 // TestViewAsRepoAdmin tests PR #2167 192 192 func TestViewAsRepoAdmin(t *testing.T) { 193 - for user, expectedNoDescription := range map[string]bool{ 194 - "user2": true, 195 - "user4": false, 196 - } { 193 + for _, user := range []string{"user2", "user4"} { 197 194 defer tests.PrepareTestEnv(t)() 198 195 199 196 session := loginUser(t, user) ··· 206 203 repoTopics := htmlDoc.doc.Find("#repo-topics").Children() 207 204 repoSummary := htmlDoc.doc.Find(".repository-summary").Children() 208 205 209 - assert.Equal(t, expectedNoDescription, noDescription.HasClass("no-description")) 206 + assert.True(t, noDescription.HasClass("no-description")) 210 207 assert.True(t, repoTopics.HasClass("repo-topic")) 211 208 assert.True(t, repoSummary.HasClass("repository-menu")) 212 209 } ··· 995 992 testOpenWith([]string{"test://"}) 996 993 }) 997 994 } 995 + 996 + func TestRepoCodeSearchForm(t *testing.T) { 997 + defer tests.PrepareTestEnv(t)() 998 + 999 + testSearchForm := func(t *testing.T, indexer bool) { 1000 + defer test.MockVariableValue(&setting.Indexer.RepoIndexerEnabled, indexer)() 1001 + req := NewRequest(t, "GET", "/user2/repo1/src/branch/master") 1002 + resp := MakeRequest(t, req, http.StatusOK) 1003 + 1004 + htmlDoc := NewHTMLParser(t, resp.Body) 1005 + action, exists := htmlDoc.doc.Find("form[data-test-tag=codesearch]").Attr("action") 1006 + assert.True(t, exists) 1007 + 1008 + branchSubURL := "/branch/master" 1009 + 1010 + if indexer { 1011 + assert.NotContains(t, action, branchSubURL) 1012 + } else { 1013 + assert.Contains(t, action, branchSubURL) 1014 + } 1015 + } 1016 + 1017 + t.Run("indexer disabled", func(t *testing.T) { 1018 + testSearchForm(t, false) 1019 + }) 1020 + 1021 + t.Run("indexer enabled", func(t *testing.T) { 1022 + testSearchForm(t, true) 1023 + }) 1024 + }