]> git.donarmstrong.com Git - lilypond.git/blob - buildscripts/git-update-changelog.py
script to update ChangeLog with Git messages.
[lilypond.git] / buildscripts / git-update-changelog.py
1 import time
2 import os
3 import re
4 import optparse
5
6 class Commit:
7     def __init__ (self, dict):
8         for v in ('message',
9                   'date',
10                   'author',
11                   'committish'):
12             self.__dict__[v] = dict[v]
13
14         # Sat Oct 28 18:52:30 2006 +0200
15         
16         self.date = ' '.join  (self.date.split (' ')[:-1])
17         self.date = time.strptime (self.date, '%a %b %d %H:%M:%S %Y')
18
19         m = re.search ('(.*)<(.*)>', self.author)
20         self.email = m.group (2)
21         self.name = m.group (1)
22
23     def touched_files (self):
24
25         files = []
26         def note_file (x):
27             files.append (x.group (1))
28             return ''
29             
30         diff = os.popen ('git show %s' % self.committish).read ()
31         re.sub ('\n--- a/([^\n]+)\n',
32                 note_file, diff)
33         re.sub('\n--- /dev/null\n\\+\\+\\+ b/([^\n]+)',
34                note_file, diff)
35
36         return files
37
38 def parse_commit_log (log):
39     committish = re.search ('^([^\n]+)', log).group (1)
40     author = re.search ('\nAuthor:\s+([^\n]+)', log).group (1)
41     date_match = re.search ('\nDate:\s+([^\n]+)', log)
42     date = date_match.group (1)
43     log = log[date_match.end (1):]
44
45     message = re.sub ("\n *", '', log)
46     message = message.strip ()
47
48     c = Commit (locals ())
49     return c
50
51 def parse_add_changes (from_commit):
52     log = os.popen ('git log %(from_commit)s..' % locals ()).read ()
53
54     log = log[len ('commit '):]
55     commits = map (parse_commit_log, re.split ('\ncommit ', log))
56     commits.reverse ()
57
58     return commits
59
60
61 def header (commit):
62     return '%d-%02d-%02d  %s  <%s>\n' % (commit.date[:3] + (commit.name, commit.email))
63
64 def changelog_body (commit):
65
66     s = ''
67     s += "\ngit commit %s\n" % commit.committish    
68     s += ''.join ('\n* %s: ' % f for f in commit.touched_files())
69     s += '\n' + commit.message
70     
71     s = s.replace ('\n', '\n\t')
72     s += '\n'
73     return s
74     
75 def to_change_log (commit, last_commit):
76
77     s = ''
78     
79     date = commit.date[:3]
80     if (last_commit == None
81         or commit.author != last_commit.author
82         or commit.date[:3] != last_commit.date[:3]):
83
84         s += header (last_commit)
85
86     s += changelog_body (commit)  
87
88     return s
89         
90 def find_last_checked_in_commit (log):
91     m = re.search (r'^(\d+-\d+\d+)[^\n]+\n*\t\*git commit ([a-f0-9]+):', log)
92
93     if m:
94         return (m.group (0), m.group (1))
95
96     return None
97
98
99
100
101 def main ():
102     p = optparse.OptionParser ("usage git-update-changelog.py --options")
103     p.add_option ("--start",
104                   action='store',
105                   default='',
106                   dest="start",
107                   help="start of log messages to merge.")
108
109     (options, args) = p.parse_args ()
110     
111     log = open ('ChangeLog').read ()
112
113     if not options.start:
114         options.start = find_last_checked_in_commit (log)
115
116     commits = parse_add_changes (options.start)
117     if not commits:
118         return
119     
120
121     new_log = ''
122     last_commit = None
123
124     first = header (commits[0])
125     if first == log[:len (first)]:
126         log = log[len (first):]
127     
128     for c in commits:
129         if (last_commit
130             and c.author != last_commit.author
131             and c.date[:3] != last_commit.date[:3]):
132
133             new_log += header (last_commit)
134
135         new_log += changelog_body (c)  
136         last_commit = c
137         
138     new_log = header (last_commit) + new_log + '\n'
139
140     log = new_log + log
141     try:
142         os.unlink ('ChangeLog~')
143     except IOError:
144         passa
145     
146     os.rename ('ChangeLog', 'ChangeLog~')
147     open ('ChangeLog', 'w').write (log)
148     
149 main ()
150     
151     
152