summaryrefslogtreecommitdiffstats
path: root/tools/gitlog2asciidoc.py
blob: dfbad82ed259cce1cd81adebc20eb7b8c4f86307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/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)