This repository has no description
0

Configure Feed

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

core / appview / repo / filesearch.go
2.6 kB 100 lines
1package repo 2 3import ( 4 "fmt" 5 "net/http" 6 "slices" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 "tangled.org/core/appview/models" 10 "tangled.org/core/appview/pages" 11 "tangled.org/core/appview/pagination" 12) 13 14func (rp *Repo) Search(w http.ResponseWriter, r *http.Request) { 15 if r.Header.Get("Hx-Request") == "true" { 16 if rp.oauth.GetMultiAccountUser(r) != nil { 17 rp.searchResultsFragment(w, r) 18 } else { 19 w.WriteHeader(http.StatusForbidden) 20 } 21 return 22 } 23 if err := rp.pages.RepoSearchPage(w, pages.RepoSearchParams{ 24 BaseParams: pages.BaseParamsFromContext(r.Context()), 25 RepoInfo: rp.repoResolver.GetRepoInfo(r, rp.oauth.GetMultiAccountUser(r)), 26 FilterQuery: r.URL.Query().Get("q"), 27 }); err != nil { 28 rp.logger.Error("failed to render", "err", err) 29 } 30} 31 32func (rp *Repo) searchResultsFragment(w http.ResponseWriter, r *http.Request) { 33 l := rp.logger.With("handler", "Search") 34 repo, err := rp.repoResolver.Resolve(r) 35 if err != nil { 36 l.Error("failed to get repo", "err", err) 37 return 38 } 39 q := r.URL.Query().Get("q") 40 41 var params pages.RepoSearchResultsFragmentParams 42 params.Query = q 43 defer func() { 44 if err := rp.pages.RepoSearchResultsFragment(w, params); err != nil { 45 l.Error("failed to render", "err", err) 46 } 47 }() 48 49 if q == "" { 50 return 51 } 52 53 q = fmt.Sprintf(`meta.did:%s %q`, repo.RepoDid, q) 54 55 ctx := r.Context() 56 57 res, err := rp.codesearch.Search(ctx, q, pagination.Page{Limit: 50}) 58 if err != nil { 59 l.Error("failed to search files", "err", err) 60 params.ErrorMsg = "Failed to perform search. Please try again later." 61 return 62 } 63 64 if len(res.Results) == 0 { 65 return 66 } 67 68 out := make([]pages.SearchResult, 0, len(res.Results)) 69 for _, res := range res.Results { 70 if res.RepoDID != syntax.DID(repo.RepoDid) { 71 continue 72 } 73 csr := pages.SearchResult{ 74 RepoDID: res.RepoDID, 75 Repo: repo, 76 FilePath: res.FilePath, 77 Branches: res.Branches, 78 Commit: res.Commit, 79 Language: res.Language, 80 } 81 if f := res.File; f != nil { 82 csr.File = &pages.CodeSearchResult_File{ 83 NameSpans: pages.FileNameSpans(res.FilePath, f.Ranges), 84 } 85 } 86 slices.SortStableFunc(res.Chunks, func(a, b models.Result_ChunkMatch) int { 87 return a.ContentStartLine - b.ContentStartLine 88 }) 89 for _, c := range res.Chunks { 90 csr.Chunks = append(csr.Chunks, pages.CodeSearchResult_Chunk{ 91 Lines: pages.ChunkLines(c.Content, c.ContentStartLine, c.Ranges), 92 MatchCount: len(c.Ranges), 93 }) 94 } 95 out = append(out, csr) 96 } 97 98 l.Debug("repo file search result", "len", len(out), "duration", res.Stats.Duration) 99 params.Results = out 100}