#!/usr/bin/env python3

# Copyright (C) 2017-2019 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING.  If not, write to
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

# This script parses a .diff file generated with 'diff -up' or 'diff -cp'
# and adds a skeleton ChangeLog file to the file. It does not try to be
# too smart when parsing function names, but it produces a reasonable
# approximation.
#
# This is a straightforward adaptation of original Perl script.
#
# Author: Yury Gribov <tetra2005@gmail.com>

import argparse
import sys
import re
import os.path
import os
import tempfile
import time
import shutil
from subprocess import Popen, PIPE

me = os.path.basename(sys.argv[0])

pr_regex = re.compile('\+(\/(\/|\*)|[Cc*!])\s+(PR [a-z+-]+\/[0-9]+)')

def error(msg):
  sys.stderr.write("%s: error: %s\n" % (me, msg))
  sys.exit(1)

def warn(msg):
  sys.stderr.write("%s: warning: %s\n" % (me, msg))

class RegexCache(object):
  """Simple trick to Perl-like combined match-and-bind."""

  def __init__(self):
    self.last_match = None

  def match(self, p, s):
    self.last_match = re.match(p, s) if isinstance(p, str) else p.match(s)
    return self.last_match

  def search(self, p, s):
    self.last_match = re.search(p, s) if isinstance(p, str) else p.search(s)
    return self.last_match

  def group(self, n):
    return self.last_match.group(n)

cache = RegexCache()

def run(cmd, die_on_error):
  """Simple wrapper for Popen."""
  proc = Popen(cmd.split(' '), stderr = PIPE, stdout = PIPE)
  (out, err) = proc.communicate()
  if die_on_error and proc.returncode != 0:
    error("`%s` failed:\n" % (cmd, proc.stderr))
  return proc.returncode, out.decode(), err

def read_user_info():
  dot_mklog_format_msg = """\
The .mklog format is:
NAME = ...
EMAIL = ...
"""

  # First try to read .mklog config
  mklog_conf = os.path.expanduser('~/.mklog')
  if os.path.exists(mklog_conf):
    attrs = {}
    f = open(mklog_conf)
    for s in f:
      if cache.match(r'^\s*([a-zA-Z0-9_]+)\s*=\s*(.*?)\s*$', s):
        attrs[cache.group(1)] = cache.group(2)
    f.close()
    if 'NAME' not in attrs:
      error("'NAME' not present in .mklog")
    if 'EMAIL' not in attrs:
      error("'EMAIL' not present in .mklog")
    return attrs['NAME'], attrs['EMAIL']

  # Otherwise go with git

  rc1, name, _ = run('git config user.name', False)
  name = name.rstrip()
  rc2, email, _ = run('git config user.email', False)
  email = email.rstrip()

  if rc1 != 0 or rc2 != 0:
    error("""\
Could not read git user.name and user.email settings.
Please add missing git settings, or create a %s.
""" % mklog_conf)

  return name, email

def get_parent_changelog (s):
  """See which ChangeLog this file change should go to."""

  if s.find('\\') == -1 and s.find('/') == -1:
    return "ChangeLog", s

  gcc_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

  d = s
  while d:
    clname = d + "/ChangeLog"
    if os.path.exists(gcc_root + '/' + clname) or os.path.exists(clname):
      relname = s[len(d)+1:]
      return clname, relname
    d, _ = os.path.split(d)

  return "Unknown ChangeLog", s

class FileDiff:
  """Class to represent changes in a single file."""

  def __init__(self, filename):
    self.filename = filename
    self.hunks = []
    self.clname, self.relname = get_parent_changelog(filename);

  def dump(self):
    print("Diff for %s:\n  ChangeLog = %s\n  rel name = %s\n" % (self.filename, self.clname, self.relname))
    for i, h in enumerate(self.hunks):
      print("Next hunk %d:" % i)
      h.dump()

class Hunk:
  """Class to represent a single hunk of changes."""

  def __init__(self, hdr):
    self.hdr = hdr
    self.lines = []
    self.ctx_diff = is_ctx_hunk_start(hdr)

  def dump(self):
    print('%s' % self.hdr)
    print('%s' % '\n'.join(self.lines))

  def is_file_addition(self):
    """Does hunk describe addition of file?"""
    if self.ctx_diff:
      for line in self.lines:
        if re.match(r'^\*\*\* 0 \*\*\*\*', line):
          return True
    else:
      return re.match(r'^@@ -0,0 \+1.* @@', self.hdr)

  def is_file_removal(self):
    """Does hunk describe removal of file?"""
    if self.ctx_diff:
      for line in self.lines:
        if re.match(r'^--- 0 ----', line):
          return True
    else:
      return re.match(r'^@@ -1.* \+0,0 @@', self.hdr)

def is_file_diff_start(s):
  # Don't be fooled by context diff line markers:
  #   *** 385,391 ****
  return ((s.startswith('*** ') and not s.endswith('***'))
          or (s.startswith('--- ') and not s.endswith('---')))

def is_ctx_hunk_start(s):
  return re.match(r'^\*\*\*\*\*\**', s)

def is_uni_hunk_start(s):
  return re.match(r'^@@ .* @@', s)

def is_hunk_start(s):
  return is_ctx_hunk_start(s) or is_uni_hunk_start(s)

def remove_suffixes(s):
  if s.startswith('a/') or s.startswith('b/'):
    s = s[2:]
  if s.endswith('.jj'):
    s = s[:-3]
  return s

def find_changed_funs(hunk):
  """Find all functions touched by hunk.  We don't try too hard
     to find good matches.  This should return a superset
     of the actual set of functions in the .diff file.
  """

  fns = []
  fn = None

  if (cache.match(r'^\*\*\*\*\*\** ([a-zA-Z0-9_].*)', hunk.hdr)
      or cache.match(r'^@@ .* @@ ([a-zA-Z0-9_].*)', hunk.hdr)):
    fn = cache.group(1)

  for i, line in enumerate(hunk.lines):
    # Context diffs have extra whitespace after first char;
    # remove it to make matching easier.
    if hunk.ctx_diff:
      line = re.sub(r'^([-+! ]) ', r'\1', line)

    # Remember most recent identifier in hunk
    # that might be a function name.
    if cache.match(r'^[-+! ]([a-zA-Z0-9_#].*)', line):
      fn = cache.group(1)

    change = line and re.match(r'^[-+!][^-]', line)

    # Top-level comment cannot belong to function
    if re.match(r'^[-+! ]\/\*', line):
      fn = None

    if change and fn:
      if cache.match(r'^((class|struct|union|enum)\s+[a-zA-Z0-9_]+)', fn):
        # Struct declaration
        fn = cache.group(1)
      elif cache.search(r'#\s*define\s+([a-zA-Z0-9_]+)', fn):
        # Macro definition
        fn = cache.group(1)
      elif cache.match('^DEF[A-Z0-9_]+\s*\(([a-zA-Z0-9_]+)', fn):
        # Supermacro
        fn = cache.group(1)
      elif cache.search(r'([a-zA-Z_][^()\s]*)\s*\([^*]', fn):
        # Discard template and function parameters.
        fn = cache.group(1)
        fn = re.sub(r'<[^<>]*>', '', fn)
        fn = fn.rstrip()
      else:
        fn = None

      if fn and fn not in fns:  # Avoid dups
        fns.append(fn)

      fn = None

  return fns

def parse_patch(contents):
  """Parse patch contents to a sequence of FileDiffs."""

  diffs = []

  lines = contents.split('\n')

  i = 0
  while i < len(lines):
    line = lines[i]

    # Diff headers look like
    #   --- a/gcc/tree.c
    #   +++ b/gcc/tree.c
    # or
    #   *** gcc/cfgexpand.c     2013-12-25 20:07:24.800350058 +0400
    #   --- gcc/cfgexpand.c     2013-12-25 20:06:30.612350178 +0400

    if is_file_diff_start(line):
      left = re.split(r'\s+', line)[1]
    else:
      i += 1
      continue

    left = remove_suffixes(left);

    i += 1
    line = lines[i]

    if not cache.match(r'^[+-][+-][+-] +(\S+)', line):
      error("expected filename in line %d" % i)
    right = remove_suffixes(cache.group(1));

    # Extract real file name from left and right names.
    filename = None
    if left == right:
      filename = left
    elif left == '/dev/null':
      filename = right;
    elif right == '/dev/null':
      filename = left;
    else:
      comps = []
      while left and right:
        left, l = os.path.split(left)
        right, r = os.path.split(right)
        if l != r:
          break
        comps.append(l)

      if not comps:
        error("failed to extract common name for %s and %s" % (left, right))

      comps.reverse()
      filename = '/'.join(comps)

    d = FileDiff(filename)
    diffs.append(d)

    # Collect hunks for current file.
    hunk = None
    i += 1
    while i < len(lines):
      line = lines[i]

      # Create new hunk when we see hunk header
      if is_hunk_start(line):
        if hunk is not None:
          d.hunks.append(hunk)
        hunk = Hunk(line)
        i += 1
        continue

      # Stop when we reach next diff
      if (is_file_diff_start(line)
          or line.startswith('diff ')
          or line.startswith('Index: ')):
        i -= 1
        break

      if hunk is not None:
        hunk.lines.append(line)
      i += 1

    d.hunks.append(hunk)

  return diffs


def get_pr_from_testcase(line):
    r = pr_regex.search(line)
    if r != None:
        return r.group(3)
    else:
        return None

def main():
  name, email = read_user_info()

  help_message =  """\
Generate ChangeLog template for PATCH.
PATCH must be generated using diff(1)'s -up or -cp options
(or their equivalent in Subversion/git).
"""

  inline_message = """\
Prepends ChangeLog to PATCH.
If PATCH is not stdin, modifies PATCH in-place,
otherwise writes to stdout.'
"""

  parser = argparse.ArgumentParser(description = help_message)
  parser.add_argument('-v', '--verbose', action = 'store_true', help = 'Verbose messages')
  parser.add_argument('-i', '--inline', action = 'store_true', help = inline_message)
  parser.add_argument('input', nargs = '?', help = 'Patch file (or missing, read standard input)')
  args = parser.parse_args()
  if args.input == '-':
      args.input = None
  input = open(args.input) if args.input else sys.stdin
  contents = input.read()
  diffs = parse_patch(contents)

  if args.verbose:
    print("Parse results:")
    for d in diffs:
      d.dump()

  # Generate template ChangeLog.

  logs = {}
  prs = []
  for d in diffs:
    log_name = d.clname

    logs.setdefault(log_name, '')
    logs[log_name] += '\t* %s' % d.relname

    change_msg = ''

    # Check if file was removed or added.
    # Two patterns for context and unified diff.
    if len(d.hunks) == 1:
      hunk0 = d.hunks[0]
      if hunk0.is_file_addition():
        if re.search(r'testsuite.*(?<!\.exp)$', d.filename):
          change_msg = ': New test.\n'
          pr = get_pr_from_testcase(hunk0.lines[0])
          if pr and pr not in prs:
              prs.append(pr)
        else:
          change_msg = ": New file.\n"
      elif hunk0.is_file_removal():
        change_msg = ": Remove.\n"

    _, ext = os.path.splitext(d.filename)
    if (not change_msg and ext in ['.c', '.cpp', '.C', '.cc', '.h', '.inc', '.def']
        and not 'testsuite' in d.filename):
      fns = []
      for hunk in d.hunks:
        for fn in find_changed_funs(hunk):
          if fn not in fns:
            fns.append(fn)

      for fn in fns:
        if change_msg:
          change_msg += "\t(%s):\n" % fn
        else:
          change_msg = " (%s):\n" % fn

    logs[log_name] += change_msg if change_msg else ":\n"

  if args.inline and args.input:
    # Get a temp filename, rather than an open filehandle, because we use
    # the open to truncate.
    fd, tmp = tempfile.mkstemp("tmp.XXXXXXXX")
    os.close(fd)

    # Copy permissions to temp file
    # (old Pythons do not support shutil.copymode)
    shutil.copymode(args.input, tmp)

    # Open the temp file, clearing contents.
    out = open(tmp, 'w')
  else:
    tmp = None
    out = sys.stdout

  # Print log
  date = time.strftime('%Y-%m-%d')
  bugmsg = ''
  if len(prs):
    bugmsg = '\n'.join(['\t' + pr for pr in prs]) + '\n'

  for log_name, msg in sorted(logs.items()):
    out.write("""\
%s:

%s  %s  <%s>

%s%s\n""" % (log_name, date, name, email, bugmsg, msg))

  if args.inline:
    # Append patch body
    out.write(contents)

    if args.input:
      # Write new contents atomically
      out.close()
      shutil.move(tmp, args.input)

if __name__ == '__main__':
    main()
