#
# 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.

Boolean 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)
