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 p2
< len (message
) and \
156 message
[p2
].isdigit():
158 bug
.number
= message
[p1
+1:p2
]
160 self
.bug_commits
.append(bug
)
161 p1
= message
.find('#', p2
)
163 self
.commits
+= ' - ' + message
+ ' (' + author
+ ').\n'
165 def query_bug_commits(self
):
167 for bug
in self
.bug_commits
:
168 bugs
+= bug
.number
+ ','
170 # Bugzilla query to use
171 query
= 'http://bugzilla.gnome.org/buglist.cgi?ctype=csv' \
172 '&bug_status=RESOLVED,CLOSED,VERIFIED' \
173 '&resolution=FIXED' \
174 '&bug_id=' + bugs
.replace(',', '%2c')
176 f
= urllib
.urlopen(query
)
183 reader
= csv
.reader(s
.splitlines(1))
184 header
= reader
.next()
190 if col
== 'short_short_desc':
195 bug_number
= row
[col_bug_id
]
196 description
= row
[col_description
]
198 for bug
in self
.bug_commits
:
199 if bug
.number
== bug_number
:
200 self
.bugs
+= ' - Fixed #%s, %s (%s)\n' % (bug
.number
, description
, bug
.author
)
203 def get_commits(self
):
205 self
.translations
= ''
207 self
.bug_commits
= []
208 last_tag
= self
.get_last_tag()
211 changes
= self
.exec_cmd ("git-log " + last_tag
+ "..")
212 for line
in changes
.splitlines(1):
213 if line
.startswith('commit'):
215 self
.parse_commit (ref
, author
, date
, message
)
217 ref
= line
[p1
:].strip()
221 elif line
.startswith('Author:'):
224 author
= line
[p1
:p2
].strip()
225 elif line
.startswith('Date:'):
227 date
= line
[p1
:].strip()
228 elif line
.startswith(' git-svn-id:'):
230 elif line
.startswith('Merge:'):
240 self
.query_bug_commits ()
243 new_tag
= self
.package_name
.upper() + '_' +\
244 self
.package_version
.replace('.', '_')
246 url1
= self
.exec_cmd('git-config svn-remote.svn.url').strip()
247 url2
= url1
[:url1
.rfind('/')] + '/tags/' + new_tag
248 self
.exec_cmd('svn copy %s %s -m "Tagged for release %s."' % (url1
, url2
, self
.package_version
))
250 self
.exec_cmd('git-tag -m "Tagged for release %s." %s' % ( self
.package_version
, new_tag
))
252 def generate_news(self
):
254 news
= 'NEW in '+ self
.package_version
+ '\n==============\n'
255 news
+= self
.commits
+ '\nBugs fixed:\n' + self
.bugs
+ '\nTranslations:\n' + self
.translations
+ '\n'
259 def write_news(self
):
260 news
= self
.generate_news()
262 f
= open ('/tmp/NEWS', 'w')
266 self
.exec_cmd('cat NEWS >> /tmp/NEWS')
267 self
.exec_cmd('mv /tmp/NEWS .')
269 def upload_tarball(self
):
270 tarball
= '%s-%s.tar.gz' % (self
.package_name
.lower(), self
.package_version
)
272 cmd
= 'scp %s %s@%s:' % (tarball
, username
, upload_server
)
275 cmd
= 'ssh %s@%s install-module -u %s' % (username
, upload_server
, tarball
)
278 def send_email(self
):
279 notes
= self
.get_release_notes()
281 ' --cc telepathy@lists.freedesktop.org' \
282 ' --subject "ANNOUNCE: Empathy %s"' \
284 ' gnome-announce-list@gnome.org' % (self
.package_version
,
285 notes
.replace('"', '\\"'))
290 self
.upload_tarball()
293 if __name__
== '__main__':
295 parser
= OptionParser()
296 parser
.add_option("-n", "--print-news", action
="store_true",\
297 dest
="print_news", help="Generate and print news")
298 parser
.add_option("-p", "--print-notes", action
="store_true",\
299 dest
="print_notes", help="Generate and print the release notes")
300 parser
.add_option("-w", "--write-news", action
="store_true",\
301 dest
="write_news", help="Generate and write news into the NEWS file")
302 parser
.add_option("-r", "--release", action
="store_true",\
303 dest
="release", help="Release the tarball")
304 parser
.add_option("-e", "--email", action
="store_true",\
305 dest
="email", help="Send the release announce email")
307 (options
, args
) = parser
.parse_args ()
308 if (options
.print_news
):
309 print p
.generate_news ()
310 if (options
.print_notes
):
311 print p
.get_release_notes ()
312 if (options
.write_news
):
314 if (options
.release
):