7 from string
import Template
8 from optparse
import OptionParser
11 last_tag_pattern
= 'EMPATHY_3_12*'
12 upload_server
= 'master.gnome.org'
14 $name $version is now available for download from:
23 You can visit the project web site:
38 f
= open('config.h', 'r')
43 key
['package'] = '#define PACKAGE_NAME "'
44 key
['version'] = '#define PACKAGE_VERSION "'
45 key
['bugreport'] = '#define PACKAGE_BUGREPORT "'
47 for line
in s
.splitlines(1):
48 if line
.startswith(key
['package']):
49 p1
= len(key
['package'])
51 self
.package_name
= line
[p1
:p2
]
52 elif line
.startswith(key
['version']):
53 p1
= len(key
['version'])
55 self
.package_version
= line
[p1
:p2
]
56 elif line
.startswith(key
['bugreport']):
58 p1
= line
.rfind('=') + 1
59 self
.package_module
= line
[p1
:p2
]
61 first
= self
.package_version
.find('.')
62 second
= self
.package_version
.find('.', first
+ 1)
63 if first
== -1 or second
== -1 or first
== second
:
64 version_dir
= self
.package_version
66 version_dir
= self
.package_version
[:second
]
67 self
.package_dl_url
= 'http://download.gnome.org/sources/%s/%s/' % (self
.package_name
.lower(),
69 tags_str
= self
.exec_cmd('git tag -l %s' % (last_tag_pattern
))
70 tags
= tags_str
.splitlines()
71 self
.last_tag
= tags
[len(tags
)-1]
73 def exec_cmd(self
,cmd
):
74 return os
.popen(cmd
).read()
77 f
= open ('NEWS', 'r')
80 start
= s
.find ('NEW in '+ self
.package_version
)
82 start
= s
.find ('\n', start
) + 1
83 start
= s
.find ('\n', start
) + 1
84 end
= s
.find ('NEW in', start
) - 1
85 return s
[start
:end
].strip()
87 def get_md5sums(self
):
90 cmd
= 'md5sum %s-%s.tar.xz' % (self
.package_name
.lower(), self
.package_version
)
91 md5sums
+= self
.exec_cmd(cmd
)
95 def get_bugzilla_info(self
):
96 query
= 'http://bugzilla.gnome.org/browse.cgi?product=%s' % (self
.package_module
)
97 f
= urllib
.urlopen(query
)
105 end
= s
.find(s2
, i
+ 1)
106 description
= s
[start
:end
]
111 i
= s
.rfind(s1
, 0, i
)
114 end
= s
.find(s2
, start
)
115 project_url
= s
[start
:end
]
117 return (description
, project_url
)
119 def get_release_notes(self
):
120 name
= self
.package_name
121 version
= self
.package_version
122 download
= self
.package_dl_url
123 md5sums
= self
.get_md5sums()
124 (about
, website
) = self
.get_bugzilla_info()
125 news
= self
.get_news()
126 footer
= '%s\n%s team' % (datetime
.date
.today().strftime('%d %B %Y'),\
129 t
= Template(template
)
130 return t
.substitute(locals())
132 def get_translations(self
, cmd
, format
):
134 files_str
= self
.exec_cmd(cmd
)
135 files
= files_str
.splitlines()
137 f
= line
[line
.rfind(' '):]
138 lang
= f
[f
.rfind('/')+1:f
.rfind('.')]
139 commit_str
= self
.exec_cmd("git log %s.. %s" % (self
.last_tag
, f
))
144 for line
in commit_str
.splitlines():
145 if line
.startswith('Author:'):
148 author
= line
[p1
:p2
].strip()
150 if authors
.find(author
) != -1:
156 translations
+= format
% (lang
, authors
)
159 def get_bug_author(self
, bug_number
):
160 cmd
= 'git log %s.. | grep -B 20 -E \
161 "(bug %s|#%s)|bugzilla.gnome.org/show_bug.cgi\?id=%s"' \
162 ' | tac | grep ^Author: | head -1' \
163 % (self
.last_tag
, bug_number
, bug_number
, bug_number
)
164 line
= self
.exec_cmd (cmd
)
168 return line
[p1
:p2
].strip()
171 commit_str
= self
.exec_cmd('git show %s' % (self
.last_tag
))
172 for line
in commit_str
.splitlines():
173 if line
.startswith('Date:'):
175 t
= dateutil
.parser
.parse(time_str
)
176 last_tag_date
= t
.strftime('%Y-%m-%d')
179 query
= 'http://bugzilla.gnome.org/buglist.cgi?' \
180 'ctype=csv&product=empathy&' \
181 'bug_status=RESOLVED,CLOSED,VERIFIED&resolution=FIXED&' \
182 'chfieldfrom=%s&chfieldto=Now' % (last_tag_date
)
183 f
= urllib
.urlopen(query
)
190 reader
= csv
.reader(s
.splitlines(1))
191 header
= reader
.next()
197 if col
== 'short_short_desc':
203 bug_number
= row
[col_bug_id
]
204 description
= row
[col_description
]
205 author
= self
.get_bug_author(bug_number
)
206 bugs
+= ' - Fixed #%s, %s' % (bug_number
, description
)
208 bugs
+= ' (%s)' % (author
)
212 def generate_news(self
):
213 translations
= self
.get_translations("ls -l po/*.po", \
214 " - Updated %s Translation (%s)\n")
215 help_translations
= self
.get_translations("ls -l help/*/*.po", \
216 " - Updated %s Documentation translation (%s)\n")
217 bugs
= self
.get_bugs()
219 news
= 'NEW in '+ self
.package_version
220 line
= '=' * len(news
)
221 today
= datetime
.date
.today()
222 news
+= ' (%s)\n%s\n' % (today
.strftime('%d/%m/%Y'),line
)
224 news
+= 'Bugs fixed:\n' + bugs
+ '\n'
225 if translations
!= '':
226 news
+= 'Translations:\n' + translations
+ '\n'
227 if help_translations
!= '':
228 news
+= 'Documentation translations:\n' + \
229 help_translations
+ '\n'
233 def write_news(self
):
234 news
= self
.generate_news()
236 f
= open ('/tmp/NEWS', 'w')
240 self
.exec_cmd('cat NEWS >> /tmp/NEWS')
241 self
.exec_cmd('mv /tmp/NEWS .')
244 new_tag
= self
.package_name
.upper() + '_' +\
245 self
.package_version
.replace('.', '_')
246 self
.exec_cmd('git tag -m "Tagged for release %s." %s' % ( self
.package_version
, new_tag
))
248 def _get_username(self
):
249 username
= os
.environ
.get('GNOME_ACCOUNT_NAME')
250 if username
is not None:
255 def upload_tarball(self
):
256 username
= self
._get
_username
()
257 tarball
= '%s-%s.tar.xz' % (self
.package_name
.lower(), self
.package_version
)
259 cmd
= 'scp %s %s@%s:' % (tarball
, username
, upload_server
)
262 cmd
= 'ssh %s@%s install-module -u %s' % (username
, upload_server
, tarball
)
265 def send_email(self
):
266 notes
= self
.get_release_notes()
269 ' --cc telepathy@lists.freedesktop.org' \
270 ' --subject "ANNOUNCE: Empathy %s"' \
272 ' gnome-announce-list@gnome.org' % (self
.package_version
,
273 notes
.replace('"', '\\"'))
278 self
.upload_tarball()
281 if __name__
== '__main__':
283 parser
= OptionParser()
284 parser
.add_option("-n", "--print-news", action
="store_true",\
285 dest
="print_news", help="Generate and print news")
286 parser
.add_option("-p", "--print-notes", action
="store_true",\
287 dest
="print_notes", help="Generate and print the release notes")
288 parser
.add_option("-w", "--write-news", action
="store_true",\
289 dest
="write_news", help="Generate and write news into the NEWS file")
290 parser
.add_option("-r", "--release", action
="store_true",\
291 dest
="release", help="Release the tarball")
292 parser
.add_option("-e", "--email", action
="store_true",\
293 dest
="email", help="Send the release announce email")
295 (options
, args
) = parser
.parse_args ()
296 if (options
.print_news
):
297 print p
.generate_news ()
298 if (options
.print_notes
):
299 print p
.get_release_notes ()
300 if (options
.write_news
):
302 if (options
.release
):