#!/usr/bin/python
from optparse import OptionParser
import re
import subprocess
import sys

"""
This script generates a release note from the output of git log
between the specified tags.

Options:
--issues          Show output the commits with issues associated with them.
--issue-numbers   Show outputs issue numbers of the commits with issues
                  associated with them

Arguments:
since -- tag name
until -- tag name

Example Input:

   * <commit subject>
   +
   <commit message>

   Bug: issue 123
   Change-Id: <change id>
   Signed-off-by: <name>

Expected Output:

   * issue 123 <commit subject>
   +
   <commit message>
"""

parser = OptionParser(usage='usage: %prog [options] <since> <until>')

parser.add_option('-i', '--issues', action='store_true',
                  dest='issues_only', default=False,
                  help='only output the commits with issues association')

parser.add_option('-n', '--issue-numbers', action='store_true',
                  dest='issue_numbers_only', default=False,
                  help='only outputs issue numbers of the commits with \
                        issues association')

(options, args) = parser.parse_args()

if len(args) != 2:
    parser.error("wrong number of arguments")

issues_only = options.issues_only
issue_numbers_only = options.issue_numbers_only

since_until = args[0] + '..' + args[1]
proc = subprocess.Popen(['git', 'log', '--reverse', '--no-merges',
                         since_until, "--format=* %s%n+%n%b"],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,)

stdout_value = proc.communicate()[0]

subject = ""
message = []
is_issue = False

# regex pattern to match following cases such as Bug: 123, Issue Bug: 123,
# Bug: GERRIT-123, Bug: issue 123, Bug issue: 123, issue: 123, issue: bug 123
p = re.compile('bug: GERRIT-|bug(:? issue)?:? |issue(:? bug)?:? ',
               re.IGNORECASE)

if issue_numbers_only:
    for line in stdout_value.splitlines(True):
        if p.match(line):
            sys.stdout.write(p.sub('', line))
else:
    for line in stdout_value.splitlines(True):
        # Move issue number to subject line
        if p.match(line):
            line = p.sub('issue ', line).replace('\n',' ')
            subject = subject[:2] + line + subject[2:]
            is_issue = True
        elif line.startswith('* '):
            # Write change log for a commit
            if subject != "":
                if (not issues_only or is_issue):
                    # Write subject
                    sys.stdout.write(subject)
                    # Write message lines
                    if message != []:
                        # Clear + from last line in commit message
                        message[-1] = '\n'
                    for m in message:
                        sys.stdout.write(m)
            # Start new commit block
            message = []
            subject = line
            is_issue = False
        # Remove commit footers
        elif re.match(r'((\w+-)+\w+:)', line):
            continue
        # Don't add extra blank line if last one is already blank
        elif line == '\n' and message and message[-1] != '+\n':
                message.append('+\n')
        elif line != '\n':
            message.append(line)
