advanced_grep

in lib/grit/repo.rb [727:802]


    def advanced_grep(searchtext, contextlines = 3, branch = 'master')

      
      searchtext = searchtext.gsub('"', '') if searchtext.count('"') % 2 == 1

      
      searchtext = Shellwords.shellescape(searchtext).gsub('\ ',' ').gsub('\\"','"')

      
      terms = Shellwords.split(searchtext)

      term_args = []
      negative_args = []

      
      
      terms.each do |term|
        arg_array = term_args
        if term[0] == '-'
          arg_array = negative_args
          term = term[1..-1]
        end
        arg_array.push '-e'
        arg_array.push final_escape(term)
      end

      context_arg = '-C ' + contextlines.to_s
      result = git.native(:grep, {pipeline: false}, '-n', '-F', '-i', '-z', '--heading', '--break', '--all-match', context_arg, *term_args, branch).encode('UTF-8', invalid: :replace, undef: :replace, replace: '')

      
      excluded_files = Array.new
      unless negative_args.empty?
        negative = git.native(:grep, {pipeline: false}, '-F', '-i', '--files-with-matches', *negative_args, branch).encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
        excluded_files = negative.split("\n").map {|text| text.partition(':')[2]}
      end

      greps = []
      filematches = result.split("\n\n")
      filematches.each do |filematch|
        binary = false
        file = ''
        matches = filematch.split("--\n")
        matches.each_with_index do |match, i|
          content = []
          startline = 0
          lines = match.split("\n")
          if i == 0
            text = lines.first
            lines.slice!(0)
            file = text[/^Binary file (.+) matches$/]
            if file
              puts "BINARY #{file}"
              binary = true
            else
              text.slice! /^
              file = text
            end
          end

          
          next if excluded_files.include? file || ( excluded_files.include? text[/^Binary file (.+) matches$/, 1].partition(':')[2] )

          lines.each_with_index do |line, j|
            line.chomp!
            number, text = line.split("\0", 2)
            if j == 0
              startline = number.to_i
            end
            content << text
          end
          greps << Grit::Grep.new(self, file, startline, content, binary)
        end
      end
      greps
    end