1#!/usr/bin/python
2# Copyright 2008 Marcus D. Hanwell <marcus@cryos.org>
3# Distributed under the terms of the GNU General Public License v2 or later
4
5import string, re, os
6
7# Execute git log with the desired command line options.
8fin = os.popen('git log --summary --stat --no-merges --date=short', 'r')
9# Create a ChangeLog file in the current directory.
10fout = open('ChangeLog', 'w')
11
12# Set up the loop variables in order to locate the blocks we want
13authorFound = False
14dateFound = False
15messageFound = False
16filesFound = False
17message = ""
18messageNL = False
19files = ""
20prevAuthorLine = ""
21
22# The main part of the loop
23for line in fin:
24    # The commit line marks the start of a new commit object.
25    if string.find(line, 'commit') >= 0:
26        # Start all over again...
27        authorFound = False
28        dateFound = False
29        messageFound = False
30        messageNL = False
31        message = ""
32        filesFound = False
33        files = ""
34        continue
35    # Match the author line and extract the part we want
36    elif re.match('Author:', line) >=0:
37        authorList = re.split(': ', line, 1)
38        author = authorList[1]
39        author = author[0:len(author)-1]
40        authorFound = True
41    # Match the date line
42    elif re.match('Date:', line) >= 0:
43        dateList = re.split(': ', line, 1)
44        date = dateList[1]
45        date = date[0:len(date)-1]
46        dateFound = True
47    # The svn-id lines are ignored
48    elif re.match(' git-svn-id:', line) >= 0:
49        continue
50    # The sign off line is ignored too
51    elif re.search('Signed-off-by', line) >= 0:
52        continue
53    # Extract the actual commit message for this commit
54    elif authorFound & dateFound & messageFound == False:
55        # Find the commit message if we can
56        if len(line) == 1:
57            if messageNL:
58                messageFound = True
59            else:
60                messageNL = True
61        elif len(line) == 4:
62            messageFound = True
63        else:
64            if len(message) == 0:
65                message = message + line.strip()
66            else:
67                message = message + " " + line.strip()
68    # If this line is hit all of the files have been stored for this commit
69    elif re.search('files changed', line) >= 0:
70        filesFound = True
71        continue
72    # Collect the files for this commit. FIXME: Still need to add +/- to files
73    elif authorFound & dateFound & messageFound:
74        fileList = re.split(' \| ', line, 2)
75        if len(fileList) > 1:
76            if len(files) > 0:
77                files = files + ", " + fileList[0].strip()
78            else:
79                files = fileList[0].strip()
80    # All of the parts of the commit have been found - write out the entry
81    if authorFound & dateFound & messageFound & filesFound:
82        # First the author line, only outputted if it is the first for that
83        # author on this day
84        authorLine = date + " " + author
85        if len(prevAuthorLine) == 0:
86            fout.write(authorLine + "\n")
87        elif authorLine == prevAuthorLine:
88            pass
89        else:
90            fout.write("\n" + authorLine + "\n")
91
92        # Assemble the actual commit message line(s) and limit the line length
93        # to 80 characters.
94        commitLine = "* " + files + ": " + message
95        i = 0
96        commit = ""
97        while i < len(commitLine):
98            if len(commitLine) < i + 78:
99                commit = commit + "\n " + commitLine[i:len(commitLine)]
100                break
101            index = commitLine.rfind(' ', i, i+78)
102            if index > i:
103                commit = commit + "\n " + commitLine[i:index]
104                i = index+1
105            else:
106                commit = commit + "\n " + commitLine[i:78]
107                i = i+79
108
109        # Write out the commit line
110        fout.write(commit + "\n")
111
112        #Now reset all the variables ready for a new commit block.
113        authorFound = False
114        dateFound = False
115        messageFound = False
116        messageNL = False
117        message = ""
118        filesFound = False
119        files = ""
120        prevAuthorLine = authorLine
121
122# Close the input and output lines now that we are finished.
123fin.close()
124fout.close()
125