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

Configure Feed

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

at main 12 kB View raw
1package query 2 3import ( 4 "fmt" 5 "regexp/syntax" 6 7 "github.com/RoaringBitmap/roaring" 8 "github.com/grafana/regexp" 9 10 webserverv1 "github.com/sourcegraph/zoekt/grpc/protos/zoekt/webserver/v1" 11) 12 13func QToProto(q Q) *webserverv1.Q { 14 switch v := q.(type) { 15 case RawConfig: 16 return &webserverv1.Q{Query: &webserverv1.Q_RawConfig{RawConfig: v.ToProto()}} 17 case *Regexp: 18 return &webserverv1.Q{Query: &webserverv1.Q_Regexp{Regexp: v.ToProto()}} 19 case *Symbol: 20 return &webserverv1.Q{Query: &webserverv1.Q_Symbol{Symbol: v.ToProto()}} 21 case *Language: 22 return &webserverv1.Q{Query: &webserverv1.Q_Language{Language: v.ToProto()}} 23 case *Const: 24 return &webserverv1.Q{Query: &webserverv1.Q_Const{Const: v.Value}} 25 case *Repo: 26 return &webserverv1.Q{Query: &webserverv1.Q_Repo{Repo: v.ToProto()}} 27 case *RepoRegexp: 28 return &webserverv1.Q{Query: &webserverv1.Q_RepoRegexp{RepoRegexp: v.ToProto()}} 29 case *BranchesRepos: 30 return &webserverv1.Q{Query: &webserverv1.Q_BranchesRepos{BranchesRepos: v.ToProto()}} 31 case *RepoIDs: 32 return &webserverv1.Q{Query: &webserverv1.Q_RepoIds{RepoIds: v.ToProto()}} 33 case *RepoSet: 34 return &webserverv1.Q{Query: &webserverv1.Q_RepoSet{RepoSet: v.ToProto()}} 35 case *FileNameSet: 36 return &webserverv1.Q{Query: &webserverv1.Q_FileNameSet{FileNameSet: v.ToProto()}} 37 case *Type: 38 return &webserverv1.Q{Query: &webserverv1.Q_Type{Type: v.ToProto()}} 39 case *Substring: 40 return &webserverv1.Q{Query: &webserverv1.Q_Substring{Substring: v.ToProto()}} 41 case *And: 42 return &webserverv1.Q{Query: &webserverv1.Q_And{And: v.ToProto()}} 43 case *Or: 44 return &webserverv1.Q{Query: &webserverv1.Q_Or{Or: v.ToProto()}} 45 case *Not: 46 return &webserverv1.Q{Query: &webserverv1.Q_Not{Not: v.ToProto()}} 47 case *Branch: 48 return &webserverv1.Q{Query: &webserverv1.Q_Branch{Branch: v.ToProto()}} 49 case *Boost: 50 return &webserverv1.Q{Query: &webserverv1.Q_Boost{Boost: v.ToProto()}} 51 default: 52 // The following nodes do not have a proto representation: 53 // - caseQ: only used internally, not by the RPC layer 54 panic(fmt.Sprintf("unknown query node %T", v)) 55 } 56} 57 58func QFromProto(p *webserverv1.Q) (Q, error) { 59 switch v := p.Query.(type) { 60 case *webserverv1.Q_RawConfig: 61 return RawConfigFromProto(v.RawConfig), nil 62 case *webserverv1.Q_Regexp: 63 return RegexpFromProto(v.Regexp) 64 case *webserverv1.Q_Symbol: 65 return SymbolFromProto(v.Symbol) 66 case *webserverv1.Q_Language: 67 return LanguageFromProto(v.Language), nil 68 case *webserverv1.Q_Const: 69 return &Const{Value: v.Const}, nil 70 case *webserverv1.Q_Repo: 71 return RepoFromProto(v.Repo) 72 case *webserverv1.Q_RepoRegexp: 73 return RepoRegexpFromProto(v.RepoRegexp) 74 case *webserverv1.Q_BranchesRepos: 75 return BranchesReposFromProto(v.BranchesRepos) 76 case *webserverv1.Q_RepoIds: 77 return RepoIDsFromProto(v.RepoIds) 78 case *webserverv1.Q_RepoSet: 79 return RepoSetFromProto(v.RepoSet), nil 80 case *webserverv1.Q_FileNameSet: 81 return FileNameSetFromProto(v.FileNameSet), nil 82 case *webserverv1.Q_Type: 83 return TypeFromProto(v.Type) 84 case *webserverv1.Q_Substring: 85 return SubstringFromProto(v.Substring), nil 86 case *webserverv1.Q_And: 87 return AndFromProto(v.And) 88 case *webserverv1.Q_Or: 89 return OrFromProto(v.Or) 90 case *webserverv1.Q_Not: 91 return NotFromProto(v.Not) 92 case *webserverv1.Q_Branch: 93 return BranchFromProto(v.Branch), nil 94 case *webserverv1.Q_Boost: 95 return BoostFromProto(v.Boost) 96 case *webserverv1.Q_Meta: 97 return MetaFromProto(v.Meta) 98 default: 99 panic(fmt.Sprintf("unknown query node %T", p.Query)) 100 } 101} 102 103func RegexpFromProto(p *webserverv1.Regexp) (*Regexp, error) { 104 parsed, err := syntax.Parse(p.GetRegexp(), regexpFlags) 105 if err != nil { 106 return nil, err 107 } 108 return &Regexp{ 109 Regexp: parsed, 110 FileName: p.GetFileName(), 111 Content: p.GetContent(), 112 CaseSensitive: p.GetCaseSensitive(), 113 }, nil 114} 115 116func (r *Regexp) ToProto() *webserverv1.Regexp { 117 return &webserverv1.Regexp{ 118 Regexp: r.RegexpString(), 119 FileName: r.FileName, 120 Content: r.Content, 121 CaseSensitive: r.CaseSensitive, 122 } 123} 124 125func SymbolFromProto(p *webserverv1.Symbol) (*Symbol, error) { 126 expr, err := QFromProto(p.GetExpr()) 127 if err != nil { 128 return nil, err 129 } 130 131 return &Symbol{ 132 Expr: expr, 133 }, nil 134} 135 136func (s *Symbol) ToProto() *webserverv1.Symbol { 137 return &webserverv1.Symbol{ 138 Expr: QToProto(s.Expr), 139 } 140} 141 142func LanguageFromProto(p *webserverv1.Language) *Language { 143 return &Language{ 144 Language: p.GetLanguage(), 145 } 146} 147 148func (l *Language) ToProto() *webserverv1.Language { 149 return &webserverv1.Language{Language: l.Language} 150} 151 152func RepoFromProto(p *webserverv1.Repo) (*Repo, error) { 153 r, err := regexp.Compile(p.GetRegexp()) 154 if err != nil { 155 return nil, err 156 } 157 return &Repo{ 158 Regexp: r, 159 }, nil 160} 161 162func (q *Repo) ToProto() *webserverv1.Repo { 163 return &webserverv1.Repo{ 164 Regexp: q.Regexp.String(), 165 } 166} 167 168func RepoRegexpFromProto(p *webserverv1.RepoRegexp) (*RepoRegexp, error) { 169 r, err := regexp.Compile(p.GetRegexp()) 170 if err != nil { 171 return nil, err 172 } 173 return &RepoRegexp{ 174 Regexp: r, 175 }, nil 176} 177 178func (q *RepoRegexp) ToProto() *webserverv1.RepoRegexp { 179 return &webserverv1.RepoRegexp{ 180 Regexp: q.Regexp.String(), 181 } 182} 183 184func BranchesReposFromProto(p *webserverv1.BranchesRepos) (*BranchesRepos, error) { 185 brs := make([]BranchRepos, len(p.GetList())) 186 for i, br := range p.GetList() { 187 branchRepos, err := BranchReposFromProto(br) 188 if err != nil { 189 return nil, err 190 } 191 brs[i] = branchRepos 192 } 193 return &BranchesRepos{ 194 List: brs, 195 }, nil 196} 197 198func (br *BranchesRepos) ToProto() *webserverv1.BranchesRepos { 199 list := make([]*webserverv1.BranchRepos, len(br.List)) 200 for i, branchRepo := range br.List { 201 list[i] = branchRepo.ToProto() 202 } 203 204 return &webserverv1.BranchesRepos{ 205 List: list, 206 } 207} 208 209func RepoIDsFromProto(p *webserverv1.RepoIds) (*RepoIDs, error) { 210 bm := roaring.NewBitmap() 211 err := bm.UnmarshalBinary(p.GetRepos()) 212 if err != nil { 213 return nil, err 214 } 215 216 return &RepoIDs{ 217 Repos: bm, 218 }, nil 219} 220 221func (q *RepoIDs) ToProto() *webserverv1.RepoIds { 222 b, err := q.Repos.ToBytes() 223 if err != nil { 224 panic("unexpected error marshalling bitmap: " + err.Error()) 225 } 226 return &webserverv1.RepoIds{ 227 Repos: b, 228 } 229} 230 231func BranchReposFromProto(p *webserverv1.BranchRepos) (BranchRepos, error) { 232 bm := roaring.NewBitmap() 233 err := bm.UnmarshalBinary(p.GetRepos()) 234 if err != nil { 235 return BranchRepos{}, err 236 } 237 return BranchRepos{ 238 Branch: p.GetBranch(), 239 Repos: bm, 240 }, nil 241} 242 243func (br *BranchRepos) ToProto() *webserverv1.BranchRepos { 244 b, err := br.Repos.ToBytes() 245 if err != nil { 246 panic("unexpected error marshalling bitmap: " + err.Error()) 247 } 248 249 return &webserverv1.BranchRepos{ 250 Branch: br.Branch, 251 Repos: b, 252 } 253} 254 255func RepoSetFromProto(p *webserverv1.RepoSet) *RepoSet { 256 return &RepoSet{ 257 Set: p.GetSet(), 258 } 259} 260 261func (q *RepoSet) ToProto() *webserverv1.RepoSet { 262 return &webserverv1.RepoSet{ 263 Set: q.Set, 264 } 265} 266 267func FileNameSetFromProto(p *webserverv1.FileNameSet) *FileNameSet { 268 m := make(map[string]struct{}, len(p.GetSet())) 269 for _, name := range p.GetSet() { 270 m[name] = struct{}{} 271 } 272 return &FileNameSet{ 273 Set: m, 274 } 275} 276 277func (q *FileNameSet) ToProto() *webserverv1.FileNameSet { 278 s := make([]string, 0, len(q.Set)) 279 for name := range q.Set { 280 s = append(s, name) 281 } 282 return &webserverv1.FileNameSet{ 283 Set: s, 284 } 285} 286 287func TypeFromProto(p *webserverv1.Type) (*Type, error) { 288 child, err := QFromProto(p.GetChild()) 289 if err != nil { 290 return nil, err 291 } 292 293 var kind uint8 294 switch p.GetType() { 295 case webserverv1.Type_KIND_FILE_MATCH: 296 kind = TypeFileMatch 297 case webserverv1.Type_KIND_FILE_NAME: 298 kind = TypeFileName 299 case webserverv1.Type_KIND_REPO: 300 kind = TypeRepo 301 } 302 303 return &Type{ 304 Child: child, 305 // TODO: make proper enum types 306 Type: kind, 307 }, nil 308} 309 310func (q *Type) ToProto() *webserverv1.Type { 311 var kind webserverv1.Type_Kind 312 switch q.Type { 313 case TypeFileMatch: 314 kind = webserverv1.Type_KIND_FILE_MATCH 315 case TypeFileName: 316 kind = webserverv1.Type_KIND_FILE_NAME 317 case TypeRepo: 318 kind = webserverv1.Type_KIND_REPO 319 } 320 321 return &webserverv1.Type{ 322 Child: QToProto(q.Child), 323 Type: kind, 324 } 325} 326 327func SubstringFromProto(p *webserverv1.Substring) *Substring { 328 return &Substring{ 329 Pattern: p.GetPattern(), 330 CaseSensitive: p.GetCaseSensitive(), 331 FileName: p.GetFileName(), 332 Content: p.GetContent(), 333 } 334} 335 336func (q *Substring) ToProto() *webserverv1.Substring { 337 return &webserverv1.Substring{ 338 Pattern: q.Pattern, 339 CaseSensitive: q.CaseSensitive, 340 FileName: q.FileName, 341 Content: q.Content, 342 } 343} 344 345func OrFromProto(p *webserverv1.Or) (*Or, error) { 346 children := make([]Q, len(p.GetChildren())) 347 for i, child := range p.GetChildren() { 348 c, err := QFromProto(child) 349 if err != nil { 350 return nil, err 351 } 352 children[i] = c 353 } 354 return &Or{ 355 Children: children, 356 }, nil 357} 358 359func (q *Or) ToProto() *webserverv1.Or { 360 children := make([]*webserverv1.Q, len(q.Children)) 361 for i, child := range q.Children { 362 children[i] = QToProto(child) 363 } 364 return &webserverv1.Or{ 365 Children: children, 366 } 367} 368 369func BoostFromProto(p *webserverv1.Boost) (*Boost, error) { 370 child, err := QFromProto(p.GetChild()) 371 if err != nil { 372 return nil, err 373 } 374 return &Boost{ 375 Child: child, 376 Boost: p.GetBoost(), 377 }, nil 378} 379 380func MetaFromProto(p *webserverv1.Meta) (*Meta, error) { 381 re, err := regexp.Compile(p.GetValue()) 382 if err != nil { 383 return nil, fmt.Errorf("invalid regexp in Meta.Value: %w", err) 384 } 385 return &Meta{ 386 Field: p.GetKey(), 387 Value: re, 388 }, nil 389} 390 391func (q *Boost) ToProto() *webserverv1.Boost { 392 return &webserverv1.Boost{ 393 Child: QToProto(q.Child), 394 Boost: q.Boost, 395 } 396} 397 398func NotFromProto(p *webserverv1.Not) (*Not, error) { 399 child, err := QFromProto(p.GetChild()) 400 if err != nil { 401 return nil, err 402 } 403 return &Not{ 404 Child: child, 405 }, nil 406} 407 408func (q *Not) ToProto() *webserverv1.Not { 409 return &webserverv1.Not{ 410 Child: QToProto(q.Child), 411 } 412} 413 414func AndFromProto(p *webserverv1.And) (*And, error) { 415 children := make([]Q, len(p.GetChildren())) 416 for i, child := range p.GetChildren() { 417 c, err := QFromProto(child) 418 if err != nil { 419 return nil, err 420 } 421 children[i] = c 422 } 423 return &And{ 424 Children: children, 425 }, nil 426} 427 428func (q *And) ToProto() *webserverv1.And { 429 children := make([]*webserverv1.Q, len(q.Children)) 430 for i, child := range q.Children { 431 children[i] = QToProto(child) 432 } 433 return &webserverv1.And{ 434 Children: children, 435 } 436} 437 438func BranchFromProto(p *webserverv1.Branch) *Branch { 439 return &Branch{ 440 Pattern: p.GetPattern(), 441 Exact: p.GetExact(), 442 } 443} 444 445func (q *Branch) ToProto() *webserverv1.Branch { 446 return &webserverv1.Branch{ 447 Pattern: q.Pattern, 448 Exact: q.Exact, 449 } 450} 451 452func RawConfigFromProto(p *webserverv1.RawConfig) (res RawConfig) { 453 for _, protoFlag := range p.Flags { 454 switch protoFlag { 455 case webserverv1.RawConfig_FLAG_ONLY_PUBLIC: 456 res |= RcOnlyPublic 457 case webserverv1.RawConfig_FLAG_ONLY_PRIVATE: 458 res |= RcOnlyPrivate 459 case webserverv1.RawConfig_FLAG_ONLY_FORKS: 460 res |= RcOnlyForks 461 case webserverv1.RawConfig_FLAG_NO_FORKS: 462 res |= RcNoForks 463 case webserverv1.RawConfig_FLAG_ONLY_ARCHIVED: 464 res |= RcOnlyArchived 465 case webserverv1.RawConfig_FLAG_NO_ARCHIVED: 466 res |= RcNoArchived 467 } 468 } 469 return res 470} 471 472func (r RawConfig) ToProto() *webserverv1.RawConfig { 473 var flags []webserverv1.RawConfig_Flag 474 for _, flag := range flagNames { 475 if r&flag.Mask != 0 { 476 switch flag.Mask { 477 case RcOnlyPublic: 478 flags = append(flags, webserverv1.RawConfig_FLAG_ONLY_PUBLIC) 479 case RcOnlyPrivate: 480 flags = append(flags, webserverv1.RawConfig_FLAG_ONLY_PRIVATE) 481 case RcOnlyForks: 482 flags = append(flags, webserverv1.RawConfig_FLAG_ONLY_FORKS) 483 case RcNoForks: 484 flags = append(flags, webserverv1.RawConfig_FLAG_NO_FORKS) 485 case RcOnlyArchived: 486 flags = append(flags, webserverv1.RawConfig_FLAG_ONLY_ARCHIVED) 487 case RcNoArchived: 488 flags = append(flags, webserverv1.RawConfig_FLAG_NO_ARCHIVED) 489 } 490 } 491 } 492 return &webserverv1.RawConfig{Flags: flags} 493}