fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

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

Support repo:REPONAME search operator.

+126 -13
+1
api.go
··· 24 24 // Ranking; the higher, the better. 25 25 Score float64 26 26 Name string 27 + Repo string 27 28 Branches []string 28 29 Matches []Match 29 30 }
+1
build/builder.go
··· 144 144 return err 145 145 } 146 146 shardBuilder := zoekt.NewIndexBuilder() 147 + shardBuilder.SetName(b.opts.RepoName) 147 148 for _, t := range todo { 148 149 shardBuilder.AddFileBranches(t.name, t.content, t.branches) 149 150 }
+5 -1
cmd/server/main.go
··· 99 99 <dt>path file:java</dt><dd>search for the word "path" in files whose name contains "java" 100 100 </dd> 101 101 <dt>path -file:java</dt><dd>search for the word "path" excluding files whose name contains "java" 102 + <dt>regex:foo.*bar</dt><dd>search for the regular expression "foo.*bar"</dd> 103 + <dt>repo:android</dt><dd>restrict to the "android" repository</dd> 102 104 </dl> 103 105 </div> 104 106 </body> ··· 113 115 114 116 type FileMatchData struct { 115 117 FileName string 118 + Repo string 116 119 Matches []MatchData 117 120 } 118 121 ··· 143 146 in {{.Stats.Duration}} 144 147 <p> 145 148 {{range .FileMatches}} 146 - <b><tt>{{.FileName}}:</tt></b> 149 + <b><tt>{{.Repo}}:{{.FileName}}:</tt></b> 147 150 <div style="background: #eef;"> 148 151 {{range .Matches}} 149 152 <pre>{{.LineNum}}: {{.Pre}}<b>{{.MatchText}}</b>{{.Post}}</pre> ··· 189 192 for _, f := range result.Files { 190 193 fMatch := FileMatchData{ 191 194 FileName: f.Name, 195 + Repo: f.Repo, 192 196 } 193 197 for _, m := range f.Matches { 194 198 l := m.LineOff
+16
eval.go
··· 371 371 return nil, nil 372 372 } 373 373 374 + func (d *indexData) simplify(in Query) Query { 375 + eval := mapQuery(in, func(q Query) Query { 376 + if r, ok := q.(*RepoQuery); ok { 377 + return constQuery(r.Name == d.repoName) 378 + } 379 + return q 380 + }) 381 + return simplify(eval) 382 + } 383 + 374 384 func (d *indexData) Search(q Query) (*SearchResult, error) { 375 385 var res SearchResult 386 + 387 + q = d.simplify(q) 388 + if c, ok := isConst(q); ok && !c { 389 + return &res, nil 390 + } 376 391 377 392 atoms := map[*SubstringQuery]*substrMatchTree{} 378 393 mt, err := d.newMatchTree(q, atoms) ··· 475 490 } 476 491 477 492 fileMatch := FileMatch{ 493 + Repo: d.repoName, 478 494 Name: d.fileName(nextDoc), 479 495 // Maintain ordering of input files. This 480 496 // strictly dominates the in-file ordering of
+2
index.go
··· 47 47 fileBranchMasks []uint32 48 48 branchNames map[int]string 49 49 branchIDs map[string]int 50 + 51 + repoName string 50 52 } 51 53 52 54 func (data *indexData) getDocIterator(query *SubstringQuery) (*docIterator, error) {
+39
index_test.go
··· 639 639 t.Fatalf("got %v, want 0 matches", sres.Files) 640 640 } 641 641 } 642 + 643 + func TestRepoName(t *testing.T) { 644 + b := NewIndexBuilder() 645 + 646 + content := []byte("bla the needle") 647 + // ----------------01234567890123 648 + b.AddFile("f1", content) 649 + b.SetName("bla") 650 + 651 + searcher := searcherForTest(t, b) 652 + sres, err := searcher.Search( 653 + &AndQuery{[]Query{ 654 + &SubstringQuery{Pattern: "needle"}, 655 + &RepoQuery{Name: "foo"}, 656 + }}) 657 + if err != nil { 658 + t.Fatalf("Search: %v", err) 659 + } 660 + if len(sres.Files) != 0 { 661 + t.Fatalf("got %v, want 0 matches", sres.Files) 662 + } 663 + 664 + if sres.Stats.FilesConsidered > 0 { 665 + t.Fatalf("got FilesConsidered %d, should have short circuited", sres.Stats.FilesConsidered) 666 + } 667 + 668 + sres, err = searcher.Search( 669 + &AndQuery{[]Query{ 670 + &SubstringQuery{Pattern: "needle"}, 671 + &RepoQuery{Name: "bla"}, 672 + }}) 673 + if err != nil { 674 + t.Fatalf("Search: %v", err) 675 + } 676 + if len(sres.Files) != 1 { 677 + t.Fatalf("got %v, want 1 match", sres.Files) 678 + } 679 + 680 + }
+7
indexbuilder.go
··· 69 69 70 70 // Branch name => ID 71 71 branches map[string]int 72 + 73 + // The repository name 74 + repoName string 72 75 } 73 76 74 77 // ContentSize returns the number of content bytes so far ingested. ··· 85 88 namePostings: make(map[ngram][]uint32), 86 89 branches: make(map[string]int), 87 90 } 91 + } 92 + 93 + func (b *IndexBuilder) SetName(nm string) { 94 + b.repoName = nm 88 95 } 89 96 90 97 // AddFile adds a file. This is the basic ordering for search results,
+13
parse.go
··· 138 138 return string(arg), n, ok, err 139 139 } 140 140 141 + func tryConsumeRepo(in []byte) (string, int, bool, error) { 142 + arg, n, ok, err := consumeKeyword(in, []byte("repo:")) 143 + return string(arg), n, ok, err 144 + } 145 + 141 146 func Parse(qStr string) (Query, error) { 142 147 b := []byte(qStr) 143 148 ··· 178 183 Pattern: fn, 179 184 FileName: true, 180 185 }) 186 + b = b[n:] 187 + continue 188 + } 189 + 190 + if fn, n, ok, err := tryConsumeRepo(b); err != nil { 191 + return nil, err 192 + } else if ok { 193 + add(&RepoQuery{Name: fn}) 181 194 b = b[n:] 182 195 continue 183 196 }
+1
parse_test.go
··· 57 57 }}, false}, 58 58 59 59 {"regex:abc[p-q]", &RegexpQuery{mustParseRE("abc[p-q]")}, false}, 60 + {"repo:go", &RepoQuery{"go"}, false}, 60 61 61 62 // case 62 63 {"abc case:yes", &SubstringQuery{Pattern: "abc", CaseSensitive: true}, false},
+34 -11
query.go
··· 50 50 return "FALSE" 51 51 } 52 52 53 + type RepoQuery struct { 54 + Name string 55 + } 56 + 57 + func (q *RepoQuery) String() string { 58 + return fmt.Sprintf("repo:%s", q.Name) 59 + } 60 + 53 61 // SubstringQuery is the most basic query: a query for a substring. 54 62 type SubstringQuery struct { 55 63 Pattern string ··· 166 174 } 167 175 } 168 176 169 - func mapQuery(qs []Query, f func(Query) Query) []Query { 177 + func mapQueryList(qs []Query, f func(Query) Query) []Query { 170 178 var neg []Query 171 179 for _, sub := range qs { 172 180 neg = append(neg, f(sub)) ··· 174 182 return neg 175 183 } 176 184 185 + func constQuery(c bool) Query { 186 + if c { 187 + return &TrueQuery{} 188 + } 189 + return &FalseQuery{} 190 + } 191 + 177 192 func isConst(q Query) (bool, bool) { 178 193 if _, ok := q.(*TrueQuery); ok { 179 194 return true, true ··· 185 200 } 186 201 187 202 func invertConst(q Query) Query { 188 - switch q.(type) { 189 - case *TrueQuery: 190 - return &FalseQuery{} 191 - case *FalseQuery: 192 - return &TrueQuery{} 203 + c, ok := isConst(q) 204 + if ok { 205 + return constQuery(!c) 193 206 } 194 207 return q 195 208 } ··· 197 210 func evalAndOrConstants(q Query, children []Query) Query { 198 211 _, isAnd := q.(*AndQuery) 199 212 200 - children = mapQuery(children, evalConstants) 213 + children = mapQueryList(children, evalConstants) 201 214 202 215 newCH := children[:0] 203 216 for _, ch := range children { ··· 212 225 newCH = append(newCH, ch) 213 226 } 214 227 if len(newCH) == 0 { 215 - if isAnd { 216 - return &TrueQuery{} 217 - } 218 - return &FalseQuery{} 228 + return constQuery(isAnd) 219 229 } 220 230 if isAnd { 221 231 return &AndQuery{newCH} ··· 251 261 252 262 return q 253 263 } 264 + 265 + // mapQueryList runs f over the q. 266 + func mapQuery(q Query, f func(q Query) Query) Query { 267 + switch s := q.(type) { 268 + case *AndQuery: 269 + return &AndQuery{Children: mapQueryList(s.Children, f)} 270 + case *OrQuery: 271 + return &OrQuery{Children: mapQueryList(s.Children, f)} 272 + case *NotQuery: 273 + return &NotQuery{Child: f(s.Child)} 274 + } 275 + return f(q) 276 + }
+1 -1
read.go
··· 101 101 d.fileNameCaseBits = r.readSectionBlob(toc.fileNames.caseBits.data) 102 102 d.fileNameCaseBitsIndex = toc.fileNames.caseBits.relativeIndex() 103 103 d.fileNameIndex = toc.fileNames.content.relativeIndex() 104 - 104 + d.repoName = string(r.readSectionBlob(toc.repoName)) 105 105 nameNgramText := r.readSectionBlob(toc.nameNgramText) 106 106 fileNamePostingsData := r.readSectionBlob(toc.namePostings.data) 107 107 fileNamePostingsIndex := toc.namePostings.relativeIndex()
+6
write.go
··· 36 36 37 37 nameNgramText simpleSection 38 38 namePostings compoundSection 39 + repoName simpleSection 39 40 } 40 41 41 42 func (t *indexTOC) sections() []section { ··· 49 50 &t.namePostings, 50 51 &t.branchMasks, 51 52 &t.branchNames, 53 + &t.repoName, 52 54 } 53 55 } 54 56 ··· 131 133 toc.branchNames.addItem(w, []byte(inv[k])) 132 134 } 133 135 toc.branchNames.end(w) 136 + 137 + toc.repoName.start(w) 138 + w.Write([]byte(b.repoName)) 139 + toc.repoName.end(w) 134 140 135 141 var tocSection simpleSection 136 142