func (s *localImpl) Search(ctx context.Context, req *CodeSearchRequest) (*CodeSearchReply, error) {
	reply := CodeSearchReply{}
	if req.Regexp == nil {
		return nil, errors.New("No search regexp provided.")
	}
	re, err := req.Regexp.Compile()
	if err != nil {
		return nil, fmt.Errorf("Search regexp compilation error: %v", err)
	}
	q := index.RegexpQuery(re.Syntax)
	for _, fileid := range s.ix.PostingQuery(q) {
		// TODO(delroth): Apply pagination.
		// TODO(delroth): Sort the filenames by relevance.
		// TODO(delroth): File RE should be applied here.
		fn := s.ix.Name(fileid)
		data, err := s.ReadFileContents(ctx, fn)
		if err != nil {
			return nil, fmt.Errorf("Search in file contents failed: %v", err)
		}
		m := &Match{
			Filename: fn,
			Snippet:  GetSnippets(data, re, 5),
		}
		if len(m.Snippet) > 0 {
			reply.Match = append(reply.Match, m)
		}
	}
	return &reply, nil
}
Beispiel #2
0
func Main() {
	g := regexp.Grep{
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	g.AddFlags()

	flag.Usage = usage
	flag.Parse()
	args := flag.Args()

	if len(args) != 1 {
		usage()
	}

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	pat := "(?m)" + args[0]
	if *iFlag {
		pat = "(?i)" + pat
	}
	re, err := regexp.Compile(pat)
	if err != nil {
		log.Fatal(err)
	}
	g.Regexp = re
	var fre *regexp.Regexp
	if *fFlag != "" {
		fre, err = regexp.Compile(*fFlag)
		if err != nil {
			log.Fatal(err)
		}
	}
	q := index.RegexpQuery(re.Syntax)
	if *verboseFlag {
		log.Printf("query: %s\n", q)
	}

	ix := index.Open(index.File())
	ix.Verbose = *verboseFlag
	var post []uint32
	if *bruteFlag {
		post = ix.PostingQuery(&index.Query{Op: index.QAll})
	} else {
		post = ix.PostingQuery(q)
	}
	if *verboseFlag {
		log.Printf("post query identified %d possible files\n", len(post))
	}

	if fre != nil {
		fnames := make([]uint32, 0, len(post))

		for _, fileid := range post {
			name := ix.Name(fileid)
			if fre.MatchString(name, true, true) < 0 {
				continue
			}
			fnames = append(fnames, fileid)
		}

		if *verboseFlag {
			log.Printf("filename regexp matched %d files\n", len(fnames))
		}
		post = fnames
	}

	for _, fileid := range post {
		name := ix.Name(fileid)
		g.File(name)
	}

	matches = g.Match
}
Beispiel #3
0
// Search returns matches for the given regexp.
// The results are unordered.
func (s *Searcher) Search(opts Options) ([]Result, error) {
	// Package index needs a regexp from the syntax package.
	syntaxRe, err := syntax.Parse(opts.Regexp, syntax.POSIX)
	if err != nil {
		return nil, err
	}

	// While package grep wants us to use the regex package.
	re, err := regexp.Compile(opts.Regexp)
	if err != nil {
		return nil, err
	}

	// Find candidate files.
	fileids := s.idx.PostingQuery(index.RegexpQuery(syntaxRe))

	// Grep all the files.
	rChan := make(chan Result, 10)
	var wg sync.WaitGroup
	for _, id := range fileids {
		path := s.idx.Name(id)

		wg.Add(1)
		go func() {
			defer wg.Done()
			f, err := os.Open(path)
			if err != nil {
				return
			}

			g, err := grep.New(f)
			if err != nil {
				return
			}

			// Copy the regexp to avoid lock contention.
			m := g.Search(re.Copy(), opts.Context)
			if len(m) > 0 {
				p := strings.TrimPrefix(path, s.prefix)
				rChan <- MakeResult(p, re, m)
			}
		}()
	}

	// Collect the results.
	var results []Result
	var wg2 sync.WaitGroup
	wg2.Add(1)
	go func() {
		defer wg2.Done()
		for {
			r, ok := <-rChan
			if !ok {
				return
			}
			results = append(results, r)
		}
	}()

	wg.Wait()
	close(rChan)
	wg2.Wait()

	return results, nil
}