8 from string
import Template
9 from optparse
import OptionParser
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 def exec_cmd(self
,cmd
):
70 return os
.popen(cmd
).read()
73 f
= open ('NEWS', 'r')
76 start
= s
.find ('NEW in '+ self
.package_version
)
78 start
= s
.find ('\n', start
) + 1
79 start
= s
.find ('\n', start
) + 1
80 end
= s
.find ('NEW in', start
) - 1
81 return s
[start
:end
].strip()
83 def get_md5sums(self
):
86 cmd
= 'md5sum %s-%s.tar.gz' % (self
.package_name
.lower(), self
.package_version
)
87 md5sums
+= self
.exec_cmd(cmd
)
89 cmd
= 'md5sum %s-%s.tar.bz2' % (self
.package_name
.lower(), self
.package_version
)
90 md5sums
+= self
.exec_cmd(cmd
).strip()
94 def get_bugzilla_info(self
):
95 query
= 'http://bugzilla.gnome.org/browse.cgi?product=%s' % (self
.package_module
)
96 f
= urllib
.urlopen(query
)
104 end
= s
.find(s2
, i
+ 1)
105 description
= s
[start
:end
]
113 end
= s
.find(s2
, start
)
114 project_url
= s
[start
:end
]
116 return (description
, project_url
)
118 def get_release_notes(self
):
119 name
= self
.package_name
120 version
= self
.package_version
121 download
= self
.package_dl_url
122 md5sums
= self
.get_md5sums()
123 (about
, website
) = self
.get_bugzilla_info()
124 news
= self
.get_news()
125 footer
= '%s\n%s team' % (datetime
.date
.today().strftime('%d %B %Y'),\
128 t
= Template(template
)
129 return t
.substitute(locals())
131 def get_last_tag(self
):
132 tags_str
= self
.exec_cmd('git-tag')
133 tags
= tags_str
.splitlines()
135 return tags
[len(tags
)-1]
137 def parse_commit(self
, ref
, author
, date
, message
):
138 p1
= message
.rfind('(')
139 p2
= message
.rfind (')')
140 if len(message
) - p2
<= 2 and \
141 message
[p1
+1:].find('#') == -1:
142 author
= message
[p1
+1:p2
]
143 message
= message
[:p1
]
145 msg
= message
.lower()
146 if msg
.find('translation') != -1 and \
147 (msg
.find('added') != -1 or \
148 msg
.find('updated') != -1):
149 self
.translations
+= ' - ' + message
+ ' (' + author
+ ').\n'
150 elif message
.find('#') != -1:
151 p1
= message
.find('#')
155 while message
[p2
].isdigit():
157 bug
.number
= message
[p1
+1:p2
]
159 self
.bug_commits
.append(bug
)
160 p1
= message
.find('#', p2
)
162 self
.commits
+= ' - ' + message
+ ' (' + author
+ ').\n'
164 def query_bug_commits(self
):
166 for bug
in self
.bug_commits
:
167 bugs
+= bug
.number
+ ','
169 # Bugzilla query to use
170 query
= 'http://bugzilla.gnome.org/buglist.cgi?ctype=csv' \
171 '&bug_status=RESOLVED,CLOSED,VERIFIED' \
172 '&resolution=FIXED' \
173 '&bug_id=' + bugs
.replace(',', '%2c')
175 f
= urllib
.urlopen(query
)
182 reader
= csv
.reader(s
.splitlines(1))
183 header
= reader
.next()
189 if col
== 'short_short_desc':
194 bug_number
= row
[col_bug_id
]
195 description
= row
[col_description
]
197 for bug
in self
.bug_commits
:
198 if bug
.number
== bug_number
:
199 self
.bugs
+= ' - Fixed #%s, %s (%s)\n' % (bug
.number
, description
, bug
.author
)
202 def get_commits(self
):
204 self
.translations
= ''
206 self
.bug_commits
= []
207 last_tag
= self
.get_last_tag()
210 changes
= self
.exec_cmd ("git-log " + last_tag
+ "..")
211 for line
in changes
.splitlines(1):
212 if line
.startswith('commit'):
214 self
.parse_commit (ref
, author
, date
, message
)
216 ref
= line
[p1
:].strip()
220 elif line
.startswith('Author:'):
223 author
= line
[p1
:p2
].strip()
224 elif line
.startswith('Date:'):
226 date
= line
[p1
:].strip()
227 elif line
.startswith(' git-svn-id:'):
229 elif line
.startswith('Merge:'):
239 self
.query_bug_commits ()
242 new_tag
= self
.package_name
.upper() + '_' +\
243 self
.package_version
.replace('.', '_')
245 url1
= self
.exec_cmd('git-config svn-remote.svn.url').strip()
246 url2
= url1
[:url1
.rfind('/')] + '/tags/' + new_tag
247 self
.exec_cmd('svn copy %s %s -m "Tagged for release %s."' % (url1
, url2
, self
.package_version
))
249 self
.exec_cmd('git-tag -m "Tagged for release %s." %s' % ( self
.package_version
, new_tag
))
251 def generate_news(self
):
253 news
= 'NEW in '+ self
.package_version
+ '\n==============\n'
254 news
+= self
.commits
+ '\nBugs fixed:\n' + self
.bugs
+ '\nTranslations:\n' + self
.translations
+ '\n'
258 def write_news(self
):
259 news
= self
.generate_news()
261 f
= open ('/tmp/NEWS', 'w')
265 self
.exec_cmd('cat NEWS >> /tmp/NEWS')
266 self
.exec_cmd('mv /tmp/NEWS .')
268 def upload_tarball(self
):
269 tarball
= '%s-%s.tar.gz' % (self
.package_name
.lower(), self
.package_version
)
271 cmd
= 'scp %s %s@%s:' % (tarball
, username
, upload_server
)
274 cmd
= 'ssh %s@%s install-module -u %s' % (username
, upload_server
, tarball
)
277 def send_email(self
):
278 notes
= self
.get_release_notes()
280 ' --cc telepathy@lists.freedesktop.org' \
281 ' --subject "ANNOUNCE: Empathy %s"' \
283 ' gnome-announce-list@gnome.org' % (self
.package_version
,
284 notes
.replace('"', '\\"'))
289 self
.upload_tarball()
292 if __name__
== '__main__':
294 parser
= OptionParser()
295 parser
.add_option("-n", "--print-news", action
="store_true",\
296 dest
="print_news", help="Generate and print news")
297 parser
.add_option("-p", "--print-notes", action
="store_true",\
298 dest
="print_notes", help="Generate and print the release notes")
299 parser
.add_option("-w", "--write-news", action
="store_true",\
300 dest
="write_news", help="Generate and write news into the NEWS file")
301 parser
.add_option("-r", "--release", action
="store_true",\
302 dest
="release", help="Release the tarball")
303 parser
.add_option("-e", "--email", action
="store_true",\
304 dest
="email", help="Send the release announce email")
306 (options
, args
) = parser
.parse_args ()
307 if (options
.print_news
):
308 print p
.generate_news ()
309 if (options
.print_notes
):
310 print p
.get_release_notes ()
311 if (options
.write_news
):
313 if (options
.release
):