fork of https://github.com/sourcegraph/zoekt
1package shards
2
3import (
4 "context"
5
6 "github.com/sourcegraph/zoekt"
7 "github.com/sourcegraph/zoekt/query"
8 "github.com/sourcegraph/zoekt/trace"
9)
10
11// typeRepoSearcher evaluates all type:repo sub-queries before sending the query
12// to the underlying searcher. We need to evaluate type:repo queries first
13// since they need to do cross shard operations.
14type typeRepoSearcher struct {
15 zoekt.Streamer
16}
17
18func (s *typeRepoSearcher) Search(ctx context.Context, q query.Q, opts *zoekt.SearchOptions) (sr *zoekt.SearchResult, err error) {
19 tr, ctx := trace.New(ctx, "typeRepoSearcher.Search", "")
20 tr.LazyLog(q, true)
21 tr.LazyPrintf("opts: %+v", opts)
22 defer func() {
23 if sr != nil {
24 tr.LazyPrintf("num files: %d", len(sr.Files))
25 tr.LazyPrintf("stats: %+v", sr.Stats)
26 }
27 if err != nil {
28 tr.LazyPrintf("error: %v", err)
29 tr.SetError(err)
30 }
31 tr.Finish()
32 }()
33
34 q, err = s.eval(ctx, q)
35 if err != nil {
36 return nil, err
37 }
38
39 return s.Streamer.Search(ctx, q, opts)
40}
41
42func (s *typeRepoSearcher) StreamSearch(ctx context.Context, q query.Q, opts *zoekt.SearchOptions, sender zoekt.Sender) (err error) {
43 tr, ctx := trace.New(ctx, "typeRepoSearcher.StreamSearch", "")
44 tr.LazyLog(q, true)
45 tr.LazyPrintf("opts: %+v", opts)
46 defer func() {
47 if err != nil {
48 tr.LazyPrintf("error: %v", err)
49 tr.SetError(err)
50 }
51 tr.Finish()
52 }()
53
54 q, err = s.eval(ctx, q)
55 if err != nil {
56 return err
57 }
58
59 return s.Streamer.StreamSearch(ctx, q, opts, sender)
60}
61
62func (s *typeRepoSearcher) List(ctx context.Context, r query.Q, opts *zoekt.ListOptions) (rl *zoekt.RepoList, err error) {
63 tr, ctx := trace.New(ctx, "typeRepoSearcher.List", "")
64 tr.LazyLog(r, true)
65 tr.LazyPrintf("opts: %s", opts)
66 defer func() {
67 if rl != nil {
68 tr.LazyPrintf("repos size: %d", len(rl.Repos))
69 tr.LazyPrintf("crashes: %d", rl.Crashes)
70 tr.LazyPrintf("minimal size : %d", len(rl.Minimal))
71 }
72 if err != nil {
73 tr.LazyPrintf("error: %v", err)
74 tr.SetError(err)
75 }
76 tr.Finish()
77 }()
78
79 r, err = s.eval(ctx, r)
80 if err != nil {
81 return nil, err
82 }
83
84 return s.Streamer.List(ctx, r, opts)
85}
86
87func (s *typeRepoSearcher) eval(ctx context.Context, q query.Q) (query.Q, error) {
88 var err error
89 q = query.Map(q, func(q query.Q) query.Q {
90 if err != nil {
91 return nil
92 }
93
94 rq, ok := q.(*query.Type)
95 if !ok || rq.Type != query.TypeRepo {
96 return q
97 }
98
99 var rl *zoekt.RepoList
100 rl, err = s.Streamer.List(ctx, rq.Child, nil)
101 if err != nil {
102 return nil
103 }
104
105 rs := &query.RepoSet{Set: make(map[string]bool, len(rl.Repos))}
106 for _, r := range rl.Repos {
107 rs.Set[r.Repository.Name] = true
108 }
109 return rs
110 })
111 return q, err
112}