97a064eee65793d0d233f249410e0021d24994ae
[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_4'
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         summary = ''
39         translation = False
40
41         def parse(self):
42                 if self.message[len(self.message) - 1] == ')':
43                         p1 = self.message.rfind('(')
44                         self.author = self.message[p1+1:len(self.message) - 1]
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.summary = "Updated " + lang + " Translation"
62                         else:
63                                 self.summary = self.message
64                         self.summary += ' (' + self.author + ').'
65
66                 return self.bug
67
68 class Project:
69         def __init__(self):
70                 f = open('config.h', 'r')
71                 s = f.read()
72                 f.close()
73
74                 key = {}
75                 key['package'] = '#define PACKAGE_NAME "'
76                 key['version'] = '#define PACKAGE_VERSION "'
77                 key['bugreport'] = '#define PACKAGE_BUGREPORT "'
78
79                 for line in s.splitlines(1):
80                         if line.startswith(key['package']):
81                                 p1 = len(key['package'])
82                                 p2 = line.rfind('"')
83                                 self.package_name = line[p1:p2]                 
84                         elif line.startswith(key['version']):
85                                 p1 = len(key['version'])
86                                 p2 = line.rfind('"')
87                                 self.package_version = line[p1:p2]              
88                         elif line.startswith(key['bugreport']):
89                                 p2 = line.rfind('"')
90                                 p1 = line.rfind('=') + 1
91                                 self.package_module = line[p1:p2]               
92
93                 first = self.package_version.find('.')
94                 second = self.package_version.find('.', first + 1)
95                 if first == -1 or second == -1 or first == second:
96                         version_dir = self.package_version
97                 else:
98                         version_dir = self.package_version[:second]
99                 self.package_dl_url = 'http://download.gnome.org/sources/%s/%s/' % (self.package_name.lower(), 
100                                                                                     version_dir)
101         def exec_cmd(self,cmd):
102                 return os.popen(cmd).read()
103
104         def get_news(self):
105                 f = open ('NEWS', 'r')
106                 s = f.read()
107                 f.close()
108                 start = s.find ('NEW in '+ self.package_version)
109                 if start != -1:
110                         start = s.find ('\n', start) + 1
111                         start = s.find ('\n', start) + 1
112                         end = s.find ('NEW in', start) - 1
113                         return s[start:end].strip()
114
115         def get_md5sums(self):
116                 md5sums = ''
117
118                 cmd = 'md5sum %s-%s.tar.gz' % (self.package_name.lower(), self.package_version)
119                 md5sums += self.exec_cmd(cmd)
120
121                 cmd = 'md5sum %s-%s.tar.bz2' % (self.package_name.lower(), self.package_version)
122                 md5sums += self.exec_cmd(cmd).strip()
123
124                 return md5sums
125
126         def get_bugzilla_info(self):
127                 query = 'http://bugzilla.gnome.org/browse.cgi?product=%s' % (self.package_module)
128                 f = urllib.urlopen(query)
129                 s = f.read()
130                 f.close()
131
132                 s1 = '<p><i>'
133                 i = s.find(s1)
134                 start = i + len(s1)
135                 s2 = '</i></p>'
136                 end = s.find(s2, i + 1)
137                 description = s[start:end]
138
139                 s1 = "GNOME SVN"
140                 i = s.find(s1)
141                 s1 = "href"
142                 i = s.find(s1, i)        
143                 start = i + 6
144                 s2 = '">'
145                 end = s.find(s2, start)
146                 project_url = s[start:end]
147
148                 return (description, project_url)
149
150         def get_release_notes(self):
151                 name = self.package_name
152                 version = self.package_version
153                 download = self.package_dl_url
154                 md5sums = self.get_md5sums()
155                 (about, website) = self.get_bugzilla_info()
156                 news = self.get_news()
157                 footer = '%s\n%s team' % (datetime.date.today().strftime('%d %B %Y'),\
158                                           self.package_name)
159
160                 t = Template(template)
161                 return t.substitute(locals())
162         
163         def get_commits(self):
164                 bugs = ''
165                 co = None
166                 commits = []
167
168                 changes = self.exec_cmd ("git-log " + prev_tag + "..")
169                 for line in changes.splitlines(1):
170                         if line.startswith('commit'):
171                                 if co != None:
172                                         bug = co.parse()
173                                         if bug:
174                                                 if bugs != '':
175                                                         bugs += ','
176                                                 bugs += bug
177
178                                 co = Commit()
179                                 commits.append(co)
180                                 p1 = line.find(' ')
181                                 co.ref = line[p1:].strip()
182                         elif line.startswith('Author:'):
183                                 p1 = line.find(' ')
184                                 p2 = line.find('<')
185                                 co.author = line[p1:p2].strip()
186                         elif line.startswith('Date:'):
187                                 p1 = line.find(' ')
188                                 co.date = line[p1:].strip()
189                         elif line.startswith('    git-svn-id:'):
190                                 continue
191                         elif line.startswith('Merge:'):
192                                 continue
193                         else:
194                                 msg = line.strip()
195                                 if msg == '':
196                                         continue
197                                 if msg.startswith('*'):
198                                         p1 = msg.find(':')
199                                         msg = msg[p1 + 1:].strip()
200                                 elif msg.startswith('2007-') or msg.startswith('2008-'):
201                                         continue
202                                 if co.message != '':
203                                         co.message += '\n'
204                                 co.message += msg
205
206                 # Bugzilla query to use
207                 query = 'http://bugzilla.gnome.org/buglist.cgi?ctype=csv' \
208                         '&bug_status=RESOLVED,CLOSED,VERIFIED' \
209                         '&resolution=FIXED' \
210                         '&bug_id=' + bugs.replace(',', '%2c')
211
212                 f = urllib.urlopen(query)
213                 s = f.read()
214                 f.close()
215
216                 col_bug_id = -1
217                 col_description = -1
218
219                 reader = csv.reader(s.splitlines(1))
220                 header = reader.next()
221                 i = 0
222
223                 for col in header:
224                         if col == 'bug_id':
225                                 col_bug_id = i
226                         if col == 'short_short_desc':
227                                 col_description = i
228                         i = i + 1
229
230                 for row in reader:
231                         bug_number = row[col_bug_id]
232                         description = row[col_description]
233
234                         for co in commits:
235                                 if co.bug == bug_number:
236                                         co.summary = 'Fixed #%s, %s (%s)' % (co.bug, description, co.author)
237                                         break
238                 return commits
239
240         def make_tag(self):
241                 new_tag = self.package_name.upper() + '_' +\
242                           self.package_version.replace('.', '_')
243
244                 url1 = self.exec_cmd('git-config svn-remote.svn.url').strip()
245                 url2 = url1[:url1.rfind('/')] + '/tags/' + new_tag
246                 self.exec_cmd('svn copy %s %s -m "Tagged for release %s."' % (url1, url2, self.package_version))
247
248                 self.exec_cmd('git-tag -m "Tagged for release %s." %s' % ( self.package_version, new_tag))
249
250         def write_news(self):
251                 bugs = ''
252                 translations = ''
253                 others = ''
254                 commits = self.get_commits()
255                 for co in commits:
256                         if co.summary == '':
257                                 others += '- ' + co.message + '\n'
258                         elif co.translation == False:
259                                 bugs += '- ' + co.summary + '\n'
260                         else :
261                                 translations += '- ' + co.summary + '\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 %s' % (username, upload_server, tarball)
280                 self.exec_cmd(cmd)
281
282 project = Project()
283 project.write_news()