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