#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
from optparse import SUPPRESS_HELP
from color import Coloring
from command import PagedCommand
from git_command import GitCommand

class GrepColoring(Coloring):
  def __init__(self, config):
    Coloring.__init__(self, config, 'grep')
    self.project = self.printer('project', attr='bold')

class Grep(PagedCommand):
  common = True
  helpSummary = "Print lines matching a pattern"
  helpUsage = """
%prog {pattern | -e pattern} [<project>...]
"""
  helpDescription = """
Search for the specified patterns in all project files.

Options
-------

The following options can appear as often as necessary to express
the pattern to locate:

 -e PATTERN
 --and, --or, --not, -(, -)

Further, the -r/--revision option may be specified multiple times
in order to scan multiple trees.  If the same file matches in more
than one tree, only the first result is reported, prefixed by the
revision name it was found under.

Examples
-------

Look for a line that has '#define' and either 'MAX_PATH or 'PATH_MAX':

  repo grep -e '#define' --and -\( -e MAX_PATH -e PATH_MAX \)

Look for a line that has 'NODE' or 'Unexpected' in files that
contain a line that matches both expressions:

  repo grep --all-match -e NODE -e Unexpected

"""

  def _Options(self, p):
    def carry(option,
              opt_str,
              value,
              parser):
      pt = getattr(parser.values, 'cmd_argv', None)
      if pt is None:
        pt = []
        setattr(parser.values, 'cmd_argv', pt)

      if opt_str == '-(':
        pt.append('(')
      elif opt_str == '-)':
        pt.append(')')
      else:
        pt.append(opt_str)

      if value is not None:
        pt.append(value)

    g = p.add_option_group('Sources')
    g.add_option('--cached',
                 action='callback', callback=carry,
                 help='Search the index, instead of the work tree')
    g.add_option('-r','--revision',
                 dest='revision', action='append', metavar='TREEish',
                 help='Search TREEish, instead of the work tree')

    g = p.add_option_group('Pattern')
    g.add_option('-e',
                 action='callback', callback=carry,
                 metavar='PATTERN', type='str',
                 help='Pattern to search for')
    g.add_option('-i', '--ignore-case',
                 action='callback', callback=carry,
                 help='Ignore case differences')
    g.add_option('-a','--text',
                 action='callback', callback=carry,
                 help="Process binary files as if they were text")
    g.add_option('-I',
                 action='callback', callback=carry,
                 help="Don't match the pattern in binary files")
    g.add_option('-w', '--word-regexp',
                 action='callback', callback=carry,
                 help='Match the pattern only at word boundaries')
    g.add_option('-v', '--invert-match',
                 action='callback', callback=carry,
                 help='Select non-matching lines')
    g.add_option('-G', '--basic-regexp',
                 action='callback', callback=carry,
                 help='Use POSIX basic regexp for patterns (default)')
    g.add_option('-E', '--extended-regexp',
                 action='callback', callback=carry,
                 help='Use POSIX extended regexp for patterns')
    g.add_option('-F', '--fixed-strings',
                 action='callback', callback=carry,
                 help='Use fixed strings (not regexp) for pattern')

    g = p.add_option_group('Pattern Grouping')
    g.add_option('--all-match',
                 action='callback', callback=carry,
                 help='Limit match to lines that have all patterns')
    g.add_option('--and', '--or', '--not',
                 action='callback', callback=carry,
                 help='Boolean operators to combine patterns')
    g.add_option('-(','-)',
                 action='callback', callback=carry,
                 help='Boolean operator grouping')

    g = p.add_option_group('Output')
    g.add_option('-n',
                 action='callback', callback=carry,
                 help='Prefix the line number to matching lines')
    g.add_option('-C',
                 action='callback', callback=carry,
                 metavar='CONTEXT', type='str',
                 help='Show CONTEXT lines around match')
    g.add_option('-B',
                 action='callback', callback=carry,
                 metavar='CONTEXT', type='str',
                 help='Show CONTEXT lines before match')
    g.add_option('-A',
                 action='callback', callback=carry,
                 metavar='CONTEXT', type='str',
                 help='Show CONTEXT lines after match')
    g.add_option('-l','--name-only','--files-with-matches',
                 action='callback', callback=carry,
                 help='Show only file names containing matching lines')
    g.add_option('-L','--files-without-match',
                 action='callback', callback=carry,
                 help='Show only file names not containing matching lines')


  def Execute(self, opt, args):
    out = GrepColoring(self.manifest.manifestProject.config)

    cmd_argv = ['grep']
    if out.is_on:
      cmd_argv.append('--color')
    cmd_argv.extend(getattr(opt,'cmd_argv',[]))

    if '-e' not in cmd_argv:
      if not args:
        self.Usage()
      cmd_argv.append('-e')
      cmd_argv.append(args[0])
      args = args[1:]

    projects = self.GetProjects(args)

    full_name = False
    if len(projects) > 1:
      cmd_argv.append('--full-name')
      full_name = True

    have_rev = False
    if opt.revision:
      if '--cached' in cmd_argv:
        print >>sys.stderr,\
          'fatal: cannot combine --cached and --revision'
        sys.exit(1)
      have_rev = True
      cmd_argv.extend(opt.revision)
    cmd_argv.append('--')

    bad_rev = False
    have_match = False

    for project in projects:
      p = GitCommand(project,
                     cmd_argv,
                     bare = False,
                     capture_stdout = True,
                     capture_stderr = True)
      if p.Wait() != 0:
        # no results
        #
        if p.stderr:
          if have_rev and 'fatal: ambiguous argument' in p.stderr:
            bad_rev = True
          else:
            out.project('--- project %s ---' % project.relpath)
            out.nl()
            out.write(p.stderr)
            out.nl()
        continue
      have_match = True

      # We cut the last element, to avoid a blank line.
      #
      r = p.stdout.split('\n')
      r = r[0:-1]

      if have_rev and full_name:
        for line in r:
          rev, line = line.split(':', 1)
          out.write(rev)
          out.write(':')
          out.project(project.relpath)
          out.write('/')
          out.write(line)
          out.nl()
      elif full_name:
        for line in r:
          out.project(project.relpath)
          out.write('/')
          out.write(line)
          out.nl()
      else:
        for line in r:
          print line

    if have_match:
      sys.exit(0)
    elif have_rev and bad_rev:
      for r in opt.revision:
        print >>sys.stderr, "error: can't search revision %s" % r
      sys.exit(1)
    else:
      sys.exit(1)
