Prepare for release 0.21.5.2
[empathy.git] / release.py
1 #!/usr/bin/env python
2
3 import os
4 import re
5 import urllib
6 import csv
7 import datetime
8 from string import Template
9
10 prev_tag = 'EMPATHY_0_21_5_1'
11 username = 'xclaesse'
12 upload_server = 'master.gnome.org'
13 template = '''\
14 $name $version is now available for download from:
15 $download
16
17 $md5sums
18
19 What is it?
20 ===========
21 $about
22
23 You can visit the project web site:
24 $website
25
26 What's New?
27 ===========
28 $news
29
30 $footer'''
31
32 class Commit:
33         ref = ''
34         author = ''
35         date = ''
36         message = ''
37         bug = ''
38         translation = False
39
40         def parse(self):
41                 p1 = self.message.rfind('(')
42                 p2 = self.message.rfind (')')
43                 if len(self.message) - p2 <= 2:
44                         self.author = self.message[p1+1:p2]
45                         self.message = self.message[:p1]
46
47                 p1 = self.message.find('#')
48                 p2 = self.message.find(' ', p1)
49                 if p1 != -1:
50                         self.bug = self.message[p1+1:p2]
51
52                 message = self.message.lower()
53                 if message.find('translation') != -1 and\
54                    message.find('updated') != -1:
55                         self.translation = True
56                         exp = '.*pdated(?P<name>.*).ranslation.*'
57                         lang_re = re.compile(exp, re.S | re.M)
58                         match = lang_re.match(self.message)
59                         if match:
60                                 lang = match.group('name').strip()                              
61                                 self.message = "Updated " + lang + " Translation"
62
63                 self.message += ' (' + self.author + ').'
64
65                 return self.bug
66
67 class Project:
68         def __init__(self):
69                 f = open('config.h', 'r')
70                 s = f.read()
71                 f.close()
72
73                 key = {}
74                 key['package'] = '#define PACKAGE_NAME "'
75                 key['version'] = '#define PACKAGE_VERSION "'
76                 key['bugreport'] = '#define PACKAGE_BUGREPORT "'
77
78                 for line in s.splitlines(1):
79                         if line.startswith(key['package']):
80                                 p1 = len(key['package'])
81                                 p2 = line.rfind('"')
82                                 self.package_name = line[p1:p2]                 
83                         elif line.startswith(key['version']):
84                                 p1 = len(key['version'])
85                                 p2 = line.rfind('"')
86                                 self.package_version = line[p1:p2]              
87                         elif line.startswith(key['bugreport']):
88                                 p2 = line.rfind('"')
89                                 p1 = line.rfind('=') + 1
90                                 self.package_module = line[p1:p2]               
91
92                 first = self.package_version.find('.')
93                 second = self.package_version.find('.', first + 1)
94                 if first == -1 or second == -1 or first == second:
95                         version_dir = self.package_version
96                 else:
97                         version_dir = self.package_version[:second]
98                 self.package_dl_url = 'http://download.gnome.org/sources/%s/%s/' % (self.package_name.lower(), 
99                                                                                     version_dir)
100         def exec_cmd(self,cmd):
101                 return os.popen(cmd).read()
102
103         def get_news(self):
104                 f = open ('NEWS', 'r')
105                 s = f.read()
106                 f.close()
107                 start = s.find ('NEW in '+ self.package_version)
108                 if start != -1:
109                         start = s.find ('\n', start) + 1
110                         start = s.find ('\n', start) + 1
111                         end = s.find ('NEW in', start) - 1
112                         return s[start:end].strip()
113
114         def get_md5sums(self):
115                 md5sums = ''
116
117                 cmd = 'md5sum %s-%s.tar.gz' % (self.package_name.lower(), self.package_version)
118                 md5sums += self.exec_cmd(cmd)
119
120                 cmd = 'md5sum %s-%s.tar.bz2' % (self.package_name.lower(), self.package_version)
121                 md5sums += self.exec_cmd(cmd).strip()
122
123                 return md5sums
124
125         def get_bugzilla_info(self):
126                 query = 'http://bugzilla.gnome.org/browse.cgi?product=%s' % (self.package_module)
127                 f = urllib.urlopen(query)
128                 s = f.read()
129                 f.close()
130
131                 s1 = '<p><i>'
132                 i = s.find(s1)
133                 start = i + len(s1)
134                 s2 = '</i></p>'
135                 end = s.find(s2, i + 1)
136                 description = s[start:end]
137
138                 s1 = "GNOME SVN"
139                 i = s.find(s1)
140                 s1 = "href"
141                 i = s.find(s1, i)        
142                 start = i + 6
143                 s2 = '">'
144                 end = s.find(s2, start)
145                 project_url = s[start:end]
146
147                 return (description, project_url)
148
149         def get_release_notes(self):
150                 name = self.package_name
151                 version = self.package_version
152                 download = self.package_dl_url
153                 md5sums = self.get_md5sums()
154                 (about, website) = self.get_bugzilla_info()
155                 news = self.get_news()
156                 footer = '%s\n%s team' % (datetime.date.today().strftime('%d %B %Y'),\
157                                           self.package_name)
158
159                 t = Template(template)
160                 return t.substitute(locals())
161         
162         def get_commits(self):
163                 bugs = ''
164                 co = None
165                 commits = []
166
167                 changes = self.exec_cmd ("git-log " + prev_tag + "..")
168                 for line in changes.splitlines(1):
169                         if line.startswith('commit'):
170                                 if co != None:
171                                         bug = co.parse()
172                                         if bug:
173                                                 if bugs != '':
174                                                         bugs += ','
175                                                 bugs += bug
176
177                                 co = Commit()
178                                 commits.append(co)
179                                 p1 = line.find(' ')
180                                 co.ref = line[p1:].strip()
181                         elif line.startswith('Author:'):
182                                 p1 = line.find(' ')
183                                 p2 = line.find('<')
184                                 co.author = line[p1:p2].strip()
185                         elif line.startswith('Date:'):
186                                 p1 = line.find(' ')
187                                 co.date = line[p1:].strip()
188                         elif line.startswith('    git-svn-id:'):
189                                 continue
190                         elif line.startswith('Merge:'):
191                                 continue
192                         else:
193                                 msg = line.strip()
194                                 if msg == '':
195                                         continue
196                                 if msg.startswith('*'):
197                                         p1 = msg.find(':')
198                                         msg = msg[p1 + 1:].strip()
199                                 elif msg.startswith('2007-') or msg.startswith('2008-'):
200                                         continue
201                                 if co.message != '':
202                                         co.message += '\n'
203                                 co.message += msg
204
205                 # Bugzilla query to use
206                 query = 'http://bugzilla.gnome.org/buglist.cgi?ctype=csv' \
207                         '&bug_status=RESOLVED,CLOSED,VERIFIED' \
208                         '&resolution=FIXED' \
209                         '&bug_id=' + bugs.replace(',', '%2c')
210
211                 f = urllib.urlopen(query)
212                 s = f.read()
213                 f.close()
214
215                 col_bug_id = -1
216                 col_description = -1
217
218                 reader = csv.reader(s.splitlines(1))
219                 header = reader.next()
220                 i = 0
221
222                 for col in header:
223                         if col == 'bug_id':
224                                 col_bug_id = i
225                         if col == 'short_short_desc':
226                                 col_description = i
227                         i = i + 1
228
229                 for row in reader:
230                         bug_number = row[col_bug_id]
231                         description = row[col_description]
232
233                         for co in commits:
234                                 if co.bug == bug_number:
235                                         co.message = 'Fixed #%s, %s (%s)' % (co.bug, description, co.author)
236                                         break
237                 return commits
238
239         def make_tag(self):
240                 new_tag = self.package_name.upper() + '_' +\
241                           self.package_version.replace('.', '_')
242
243                 url1 = self.exec_cmd('git-config svn-remote.svn.url').strip()
244                 url2 = url1[:url1.rfind('/')] + '/tags/' + new_tag
245                 self.exec_cmd('svn copy %s %s -m "Tagged for release %s."' % (url1, url2, self.package_version))
246
247                 self.exec_cmd('git-tag -m "Tagged for release %s." %s' % ( self.package_version, new_tag))
248
249         def write_news(self):
250                 bugs = ''
251                 translations = ''
252                 others = ''
253                 commits = self.get_commits()
254                 for co in commits:
255
256                         if co.translation == True:
257                                 translations += ' - ' + co.message + '\n'
258                         elif co.bug != '':
259                                 bugs += ' - ' + co.message + '\n'
260                         else:
261                                 others += ' - ' + co.message + '\n'
262                                 
263                 news = 'NEW in '+ self.package_version + '\n==============\n' 
264                 news += others + '\nBugs fixed:\n' + bugs + '\nTranslations:\n' + translations + '\n'
265
266                 f = open ('/tmp/NEWS', 'w')
267                 s = f.write(news)
268                 f.close()
269
270                 self.exec_cmd('cat NEWS >> /tmp/NEWS')
271                 self.exec_cmd('mv /tmp/NEWS .')
272
273         def upload_tarball(self):
274                 tarball = '%s-%s.tar.gz' % (self.package_name.lower(), self.package_version)
275
276                 cmd = 'scp %s %s@%s:' % (tarball, username, upload_server)
277                 self.exec_cmd(cmd)
278
279                 cmd = 'ssh %s@%s install-module -u %s' % (username, upload_server, tarball)
280                 self.exec_cmd(cmd)
281
282         def release(self):
283                 self.make_tag()
284                 self.upload_tarball()
285                 print self.get_release_notes()
286
287 p = Project()
288 #p.write_news()
289 #p.release()