func assertContextTest(t *testing.T, buf []byte, exp string, ctx int, expectsBefore [][]string, expectsAfter [][]string) { re, err := regexp.Compile(exp) if err != nil { t.Error(err) return } var gotBefore [][][]byte var gotAfter [][][]byte var g grepper if err := g.grep2(bytes.NewBuffer(buf), re, ctx, func(line []byte, lineno int, before [][]byte, after [][]byte) (bool, error) { gotBefore = append(gotBefore, before) gotAfter = append(gotAfter, after) return true, nil }); err != nil { t.Error(err) return } if len(expectsBefore) != len(gotBefore) { t.Errorf("Before had %d lines, should have had %d", len(gotBefore), len(expectsBefore)) return } if len(expectsAfter) != len(gotAfter) { t.Errorf("After had %d lines, should have had %d", len(gotBefore), len(expectsBefore)) return } for i, n := 0, len(gotBefore); i < n; i++ { assertLinesMatch(t, gotBefore[i], expectsBefore[i]) } for i, n := 0, len(gotAfter); i < n; i++ { assertLinesMatch(t, gotAfter[i], expectsAfter[i]) } }
func assertGrepTest(t *testing.T, buf []byte, exp string, expects []*match) { re, err := regexp.Compile(exp) if err != nil { t.Error(err) return } var g grepper var m []*match if err := g.grep2(bytes.NewBuffer(buf), re, 0, func(line []byte, lineno int, before [][]byte, after [][]byte) (bool, error) { m = append(m, aMatch(string(line), lineno)) return true, nil }); err != nil { t.Error(err) return } assertMatchesMatch(t, m, expects) }
func (n *Index) Search(pat string, opt *SearchOptions) (*SearchResponse, error) { startedAt := time.Now() n.lck.RLock() defer n.lck.RUnlock() re, err := regexp.Compile(GetRegexpPattern(pat, opt.IgnoreCase)) if err != nil { return nil, err } var ( g grepper results []*FileMatch filesOpened int filesFound int filesCollected int matchesCollected int ) var fre *regexp.Regexp if opt.FileRegexp != "" { fre, err = regexp.Compile(opt.FileRegexp) if err != nil { return nil, err } } var counter int var lastFileId uint32 files := n.idx.PostingQuery(index.RegexpQuery(re.Syntax)) for _, file := range files { var matches []*Match name := n.idx.Name(file) hasMatch := false // counter++ // reject files that do not match the file pattern if fre != nil && fre.MatchString(name, true, true) < 0 { continue } filesOpened++ if counter > 500 { hasMatch = true matches = append(matches, &Match{ Line: "This hit has been skipped due to performance optimizations", LineNumber: 1337, Before: []string{}, After: []string{}, }) matchesCollected++ } else { if err := g.grep2File(filepath.Join(n.Ref.dir, "raw", name), re, int(opt.LinesOfContext), func(line []byte, lineno int, before [][]byte, after [][]byte) (bool, error) { hasMatch = true if lastFileId != file { lastFileId = file counter++ } if filesFound < opt.Offset || (opt.Limit > 0 && filesCollected >= opt.Limit) { return false, nil } matchesCollected++ // beforeA := []string{"BEFORE1", "BEFORE2"} // afterA := []string{"AFTER1", "AFTER2"} matches = append(matches, &Match{ Line: string(line), LineNumber: lineno, Before: toStrings(before), After: toStrings(after), }) if matchesCollected > matchLimit { return false, fmt.Errorf("search exceeds limit on matches: %d", matchLimit) } return true, nil }); err != nil { return nil, err } } if !hasMatch { continue } filesFound++ if len(matches) > 0 { filesCollected++ results = append(results, &FileMatch{ Filename: name, Matches: matches, }) } } return &SearchResponse{ Matches: results, FilesWithMatch: filesFound, FilesOpened: filesOpened, Duration: time.Now().Sub(startedAt), Revision: n.Ref.Rev, }, nil }