9 from string
import Template
10 from optparse
import OptionParser
12 last_tag_pattern
= 'EMPATHY_3_0*'
13 upload_server
= 'master.gnome.org'
15 $name $version is now available for download from:
24 You can visit the project web site:
39 f
= open('config.h', 'r')
44 key
['package'] = '#define PACKAGE_NAME "'
45 key
['version'] = '#define PACKAGE_VERSION "'
46 key
['bugreport'] = '#define PACKAGE_BUGREPORT "'
48 for line
in s
.splitlines(1):
49 if line
.startswith(key
['package']):
50 p1
= len(key
['package'])
52 self
.package_name
= line
[p1
:p2
]
53 elif line
.startswith(key
['version']):
54 p1
= len(key
['version'])
56 self
.package_version
= line
[p1
:p2
]
57 elif line
.startswith(key
['bugreport']):
59 p1
= line
.rfind('=') + 1
60 self
.package_module
= line
[p1
:p2
]
62 first
= self
.package_version
.find('.')
63 second
= self
.package_version
.find('.', first
+ 1)
64 if first
== -1 or second
== -1 or first
== second
:
65 version_dir
= self
.package_version
67 version_dir
= self
.package_version
[:second
]
68 self
.package_dl_url
= 'http://download.gnome.org/sources/%s/%s/' % (self
.package_name
.lower(),
70 tags_str
= self
.exec_cmd('git tag -l %s' % (last_tag_pattern
))
71 tags
= tags_str
.splitlines()
72 self
.last_tag
= tags
[len(tags
)-1]
74 def exec_cmd(self
,cmd
):
75 return os
.popen(cmd
).read()
78 f
= open ('NEWS', 'r')
81 start
= s
.find ('NEW in '+ self
.package_version
)
83 start
= s
.find ('\n', start
) + 1
84 start
= s
.find ('\n', start
) + 1
85 end
= s
.find ('NEW in', start
) - 1
86 return s
[start
:end
].strip()
88 def get_md5sums(self
):
91 cmd
= 'md5sum %s-%s.tar.gz' % (self
.package_name
.lower(), self
.package_version
)
92 md5sums
+= self
.exec_cmd(cmd
)
94 cmd
= 'md5sum %s-%s.tar.bz2' % (self
.package_name
.lower(), self
.package_version
)
95 md5sums
+= self
.exec_cmd(cmd
).strip()
99 def get_bugzilla_info(self
):
100 query
= 'http://bugzilla.gnome.org/browse.cgi?product=%s' % (self
.package_module
)
101 f
= urllib
.urlopen(query
)
109 end
= s
.find(s2
, i
+ 1)
110 description
= s
[start
:end
]
115 i
= s
.rfind(s1
, 0, i
)
118 end
= s
.find(s2
, start
)
119 project_url
= s
[start
:end
]
121 return (description
, project_url
)
123 def get_release_notes(self
):
124 name
= self
.package_name
125 version
= self
.package_version
126 download
= self
.package_dl_url
127 md5sums
= self
.get_md5sums()
128 (about
, website
) = self
.get_bugzilla_info()
129 news
= self
.get_news()
130 footer
= '%s\n%s team' % (datetime
.date
.today().strftime('%d %B %Y'),\
133 t
= Template(template
)
134 return t
.substitute(locals())
136 def get_translations(self
, cmd
, format
):
138 files_str
= self
.exec_cmd(cmd
)
139 files
= files_str
.splitlines()
141 f
= line
[line
.rfind(' '):]
142 lang
= f
[f
.rfind('/')+1:f
.rfind('.')]
143 commit_str
= self
.exec_cmd("git log %s.. %s" % (self
.last_tag
, f
))
148 for line
in commit_str
.splitlines():
149 if line
.startswith('Author:'):
152 author
= line
[p1
:p2
].strip()
154 if authors
.find(author
) != -1:
160 translations
+= format
% (lang
, authors
)
163 def get_bug_author(self
, bug_number
):
164 cmd
= 'git log %s.. | grep -B 20 -E "(bug %s|#%s)"' \
165 ' | tac | grep ^Author: | head -1' \
166 % (self
.last_tag
, bug_number
, bug_number
)
167 line
= self
.exec_cmd (cmd
)
171 return line
[p1
:p2
].strip()
174 commit_str
= self
.exec_cmd('git show %s' % (self
.last_tag
))
175 for line
in commit_str
.splitlines():
176 if line
.startswith('Date:'):
177 time_str
= line
[5:line
.rfind('+')].strip()
178 t
= time
.strptime(time_str
)
179 last_tag_date
= time
.strftime('%Y-%m-%d', t
)
182 query
= 'http://bugzilla.gnome.org/buglist.cgi?' \
183 'ctype=csv&product=empathy&' \
184 'bug_status=RESOLVED,CLOSED,VERIFIED&resolution=FIXED&' \
185 'chfieldfrom=%s&chfieldto=Now' % (last_tag_date
)
186 f
= urllib
.urlopen(query
)
193 reader
= csv
.reader(s
.splitlines(1))
194 header
= reader
.next()
200 if col
== 'short_short_desc':
206 bug_number
= row
[col_bug_id
]
207 description
= row
[col_description
]
208 author
= self
.get_bug_author(bug_number
)
209 bugs
+= ' - Fixed #%s, %s' % (bug_number
, description
)
211 bugs
+= ' (%s)' % (author
)
215 def generate_news(self
):
216 translations
= self
.get_translations("ls -l po/*.po", \
217 " - Updated %s Translation (%s)\n")
218 help_translations
= self
.get_translations("ls -l help/*/*.po", \
219 " - Updated %s Documentation translation (%s)\n")
220 bugs
= self
.get_bugs()
222 news
= 'NEW in '+ self
.package_version
223 line
= '=' * len(news
)
224 today
= datetime
.date
.today()
225 news
+= ' (%s)\n%s\n' % (today
.strftime('%d/%m/%Y'),line
)
227 news
+= 'Bugs fixed:\n' + bugs
+ '\n'
228 if translations
!= '':
229 news
+= 'Translations:\n' + translations
+ '\n'
230 if help_translations
!= '':
231 news
+= 'Documentation translations:\n' + \
232 help_translations
+ '\n'
236 def write_news(self
):
237 news
= self
.generate_news()
239 f
= open ('/tmp/NEWS', 'w')
243 self
.exec_cmd('cat NEWS >> /tmp/NEWS')
244 self
.exec_cmd('mv /tmp/NEWS .')
247 new_tag
= self
.package_name
.upper() + '_' +\
248 self
.package_version
.replace('.', '_')
249 self
.exec_cmd('git tag -m "Tagged for release %s." %s' % ( self
.package_version
, new_tag
))
251 def _get_username(self
):
252 username
= os
.environ
.get('GNOME_ACCOUNT_NAME')
253 if username
is not None:
259 def upload_tarball(self
):
260 username
= self
._get
_username
()
261 tarball
= '%s-%s.tar.gz' % (self
.package_name
.lower(), self
.package_version
)
263 cmd
= 'scp %s %s@%s:' % (tarball
, username
, upload_server
)
266 cmd
= 'ssh %s@%s install-module -u %s' % (username
, upload_server
, tarball
)
269 def send_email(self
):
270 notes
= self
.get_release_notes()
273 ' --cc telepathy@lists.freedesktop.org' \
274 ' --subject "ANNOUNCE: Empathy %s"' \
276 ' gnome-announce-list@gnome.org' % (self
.package_version
,
277 notes
.replace('"', '\\"'))
282 self
.upload_tarball()
285 if __name__
== '__main__':
287 parser
= OptionParser()
288 parser
.add_option("-n", "--print-news", action
="store_true",\
289 dest
="print_news", help="Generate and print news")
290 parser
.add_option("-p", "--print-notes", action
="store_true",\
291 dest
="print_notes", help="Generate and print the release notes")
292 parser
.add_option("-w", "--write-news", action
="store_true",\
293 dest
="write_news", help="Generate and write news into the NEWS file")
294 parser
.add_option("-r", "--release", action
="store_true",\
295 dest
="release", help="Release the tarball")
296 parser
.add_option("-e", "--email", action
="store_true",\
297 dest
="email", help="Send the release announce email")
299 (options
, args
) = parser
.parse_args ()
300 if (options
.print_news
):
301 print p
.generate_news ()
302 if (options
.print_notes
):
303 print p
.get_release_notes ()
304 if (options
.write_news
):
306 if (options
.release
):