hgpoll.py

changeset 144
b3d1b356e544
parent 143
d86a81540a71
child 145
588aff83bb87
equal deleted inserted replaced
143:d86a81540a71 144:b3d1b356e544
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 ''' 27 '''
28 28
29 import hgapi
30 import time 29 import time
31 import re 30 import re
32 import bt as Bt 31 import bt as Bt
33 import irc as Irc 32 import irc as Irc
34 import os, sqlite3, subprocess 33 import os, sqlite3, subprocess
153 if repoconfig.has_node (reponame): 152 if repoconfig.has_node (reponame):
154 return repoconfig.get_node (reponame) 153 return repoconfig.get_node (reponame)
155 154
156 return None 155 return None
157 156
158 ' Check if a repository exists '
159 def check_repo_exists (repo_name): 157 def check_repo_exists (repo_name):
160 print 'Checking that %s exists...' % repo_name 158 ' Check if a repository exists '
161 zanrepo = hgapi.Repo (repo_name) 159 print ('Checking that %s exists...' % repo_name)
162 160
163 if not os.path.exists (repo_name): 161 if not os.path.exists (repo_name):
164 os.makedirs (repo_name) 162 os.makedirs (repo_name)
165 163
166 if not os.path.isfile (os.path.join (repo_name, '.hg', 'hgrc')): 164 if not os.path.isfile (os.path.join (repo_name, '.hg', 'hgrc')):
167 # If the repo does not exist, clone it. 165 # If the repo does not exist, clone it.
168 repo_url = get_repo_info (repo_name).get_value ('url') 166 repo_url = get_repo_info (repo_name).get_value ('url')
169 try: 167 try:
170 print ('Cloning %s...' % repo_name) 168 print ('Cloning %s...' % repo_name)
171 zanrepo.hg_clone (repo_url, repo_name) 169 subprocess.call (['hg', 'clone', repo_url, repo_name])
172 170
173 # We need to un-alias a few things, they can be aliased on the host machine (e.g. mine) 171 # We need to un-alias a few things, they may be aliased on the host machine (e.g. mine)
174 comms=['log', 'incoming', 'pull', 'commit', 'push', 'outgoing', 'strip', 'transplant'] 172 comms=['log', 'incoming', 'pull', 'commit', 'push', 'outgoing', 'strip', 'transplant']
175 try: 173 try:
176 with open (os.path.join (repo_name, '.hg', 'hgrc'), 'a') as fp: 174 with open (os.path.join (repo_name, '.hg', 'hgrc'), 'a') as fp:
177 fp.write ('\n[alias]\n' + ''.join(['%s=%s\n' % (x, x) for x in comms])) 175 fp.write ('\n[alias]\n' + ''.join(['%s=%s\n' % (x, x) for x in comms]))
178 except Exception as e: 176 except Exception as e:
180 print ('Cloning done.') 178 print ('Cloning done.')
181 except Exception as e: 179 except Exception as e:
182 print ('Unable to clone %s from %s: %s' % (repo_name, repo_url, e)) 180 print ('Unable to clone %s from %s: %s' % (repo_name, repo_url, e))
183 quit (1) 181 quit (1)
184 182
185
186 class HgProcessError (Exception): 183 class HgProcessError (Exception):
187 def __init__ (self, value): 184 def __init__ (self, value):
188 self.message = value 185 self.message = value
189 def __str__ (self): 186 def __str__ (self):
190 return self.message 187 return self.message
191 188
189 def contains_published_repositories (reponames):
190 for reponame in reponames:
191 if is_published (reponame):
192 return True
193
194 return False
195
196 def is_published (reponame):
197 repoinfo = get_repo_info (reponame)
198 return (repoinfo and not repoinfo.get_value ('extrarepo', default=False))
199
192 def announce_ticket_resolved (ticket_id, cset): 200 def announce_ticket_resolved (ticket_id, cset):
193 ticket_id = int (ticket_id) 201 ticket_id = int (ticket_id)
194 reponames = g_CommitsDb.get_commit_repos (cset) 202 reponames = g_CommitsDb.get_commit_repos (cset)
195 203
196 if not reponames: 204 if not contains_published_repositories (reponames):
197 raise HgProcessError ('Changeset %s does not appear to exist!' % cset) 205 raise HgProcessError ('Changeset %s is only committed to non-published repositories: %s' %
198 206 (cset, ', '.join (reponames)))
199 for reponame in reponames: 207
200 repoinfo = get_repo_info (reponame)
201 if not repoinfo:
202 raise HgProcessError ('Unknown repo %s' % reponame)
203
204 if not repoinfo.get_value ('extrarepo', default=False):
205 break
206 else:
207 raise HgProcessError ('Changeset %s is only committed to non-published repositories %s' %
208 (cset, reponames))
209
210 repo = hgapi.Repo (reponame)
211 repo_url = repoinfo.get_value ('url', default=None) 208 repo_url = repoinfo.get_value ('url', default=None)
212 209
213 if not repo_url: 210 if not repo_url:
214 raise HgProcessError ('Repo %s has no url!' % reponame) 211 raise HgProcessError ('Repo %s has no url!' % reponame)
215 212
216 # Acquire additional data 213 # Acquire additional data
217 moredata = get_commit_data (repo, cset, 214 moredata = get_commit_data (reponame, cset,
218 r"{author|nonempty}\n{date(date, '%A %d %B %Y %H:%M:%S')}").split('\n') 215 r"{author|person}\n{date(date, '%A %d %B %Y %H:%M:%S')}\n{author|email}").split('\n')
219 216
220 if len (moredata) != 2: 217 if len (moredata) != 2:
221 raise HgProcessError ('malformed hg data while processing %s' % cset) 218 raise HgProcessError ('malformed hg data while processing %s' % cset)
222 219
223 commit_author = moredata[0] 220 commit_author = moredata[0]
224 commit_date = moredata[1] 221 commit_date = moredata[1]
225 commit_email = "" 222 commit_email = moredata[2]
226 commit_message = repo.hg_command ('log', '-r', cset, '--template', '{desc}') 223 commit_message = subprocess.check_output (['hg', '--cwd', reponame, 'log', '--rev', cset, '--template', '{desc}'])
224 commit_diffstat = subprocess.check_output (['hg', '--cwd', reponame, 'diff', '--change', cset, '--stat'])
227 225
228 try: 226 try:
229 ticket_data = Bt.get_issue (ticket_id) 227 ticket_data = Bt.get_issue (ticket_id)
230 except Exception as e: 228 except Exception as e:
231 raise HgProcessError ("error while processing %s: %s" % (cset, e)) 229 raise HgProcessError ("error while processing %s: %s" % (cset, e))
232 230
233 # Remove the email address from the author if possible
234 rex = re.compile (r'^(.+) <([^>]+)>$.*')
235 match = rex.match (commit_author)
236 if match:
237 commit_author = match.group (1)
238 commit_email = match.group (2)
239
240 commit_diffstat = repo.hg_command ('diff', '--change', cset, '--stat')
241
242 if len(commit_diffstat) > 0: 231 if len(commit_diffstat) > 0:
243 commit_diffstat = 'Changes in files:\n[code]\n' + commit_diffstat + '\n[/code]' 232 commit_diffstat = 'Changes in files:\n[code]\n' + commit_diffstat + '\n[/code]'
244 # commit_diffstat = 'Changes in files:\n' + bbcodify(commit_diffstat)
245 else: 233 else:
246 commit_diffstat = 'No changes in files.' 234 commit_diffstat = 'No changes in files.'
247 235
248 # Compare the email addresses against known developer usernames 236 # Compare the email addresses against known developer usernames
249 commit_trackeruser = Config.find_developer_by_email (commit_email) 237 commit_trackeruser = Config.find_developer_by_email (commit_email)
280 # Announce on IRC 268 # Announce on IRC
281 for irc_client in Irc.all_clients: 269 for irc_client in Irc.all_clients:
282 for channel in irc_client.channels: 270 for channel in irc_client.channels:
283 if channel.get_value ('btannounce', default=True): 271 if channel.get_value ('btannounce', default=True):
284 irc_client.privmsg (channel.get_value ('name'), 272 irc_client.privmsg (channel.get_value ('name'),
285 "\003%d%s\003: commit\0035 %s\003 addresses issue\002\0032 %d\002" % (color_for_repo (reponame), reponame, cset, ticket_id)) 273 "\003%d%s\003: commit\0035 %s\003 addresses issue\002\0032 %d\002" % \
274 (color_for_repo (reponame), reponame, cset, ticket_id))
286 irc_client.privmsg (channel.get_value ('name'), 275 irc_client.privmsg (channel.get_value ('name'),
287 "Read all about it here: " + Bt.get_ticket_url (ticket_id)) 276 "Read all about it here: " + Bt.get_ticket_url (ticket_id))
288 277
289 if need_update: 278 if need_update:
290 # We need to remove the note data, otherwise the ticket notes 279 # We need to remove the note data, otherwise the ticket notes
296 285
297 def init(): 286 def init():
298 global repocheck_timeout 287 global repocheck_timeout
299 global g_CommitsDb 288 global g_CommitsDb
300 289
301 for repo in all_repo_names(): 290 for reponame in all_repo_names():
302 check_repo_exists (repo) 291 check_repo_exists (reponame)
303 292
304 g_CommitsDb = CommitsDb() 293 g_CommitsDb = CommitsDb()
305 repocheck_timeout = time.time() + 15 294 repocheck_timeout = time.time() + 15
306 295
307 global ZDoomRevNumber 296 def get_commit_data (reponame, rev, template):
308 try: 297 return subprocess.check_output (['hg', '--cwd', reponame, 'log', '--limit', '1', '--rev', rev, '--template', template])
309 ZDoomRevNumber = get_zdrev_number ('zandronum-merge-experiments', 'tip')
310 except Exception as e:
311 print 'error while figuring out zdoom rev number: %s' % e
312
313 def get_commit_data (repo, rev, template):
314 return repo.hg_command ('log', '-l', '1', '-r', rev, '--template', template)
315
316 def decipher_hgapi_error (e):
317 # Blah, hgapi, why must your error messages be so mangled?
318 try:
319 rawmsg = e.message.replace('\n', '').replace('" +','').replace('\t','')
320 errmsg = re.compile (r'.*: tErr: (.*)Out:.*').match (rawmsg).group (1)
321 return [True, errmsg]
322 except:
323 return [False, '']
324
325 def bbcodify (commit_diffstat):
326 result = ''
327
328 for line in commit_diffstat.split('\n'):
329 rex = re.compile (r'^(.*)\|(.*) (\+*)(-*)(.*)$')
330 match = rex.match (line)
331 if match:
332 line = '%s|%s [color=#5F7]%s[/color][color=#F53]%s[/color]%s\n' \
333 % (match.group (1), match.group (2), match.group (3),
334 match.group (4), match.group (5))
335
336 # Tracker doesn't seem to like empty color tags
337 line = line.replace ('[color=#5F7][/color]', '').replace ('[color=#F53][/color]', '')
338
339 result += line
340
341 return result
342 298
343 def poll(): 299 def poll():
344 global repocheck_timeout 300 global repocheck_timeout
345 if time.time() < repocheck_timeout: 301 if time.time() < repocheck_timeout:
346 return 302 return
347 303
304 hgns = Config.get_node ('hg')
305 repocheck_timeout = time.time() + hgns.get_value ('checkinterval', default=15) * 60
306
348 for reponame in all_repo_names(): 307 for reponame in all_repo_names():
349 poll_one_repo (reponame) 308 poll_one_repo (reponame)
350
351 hgns = Config.get_node ('hg')
352 repocheck_timeout = time.time() + hgns.get_value ('checkinterval', default=15) * 60
353 309
354 def poll_one_repo (repo_name): 310 def poll_one_repo (repo_name):
355 global repocheck_timeout 311 global repocheck_timeout
356 hgns = Config.get_node ('hg') 312 hgns = Config.get_node ('hg')
357 313
358 if not hgns.get_value ('track', default=True): 314 if not hgns.get_value ('track', default=True):
359 return 315 return
360 316
361 repo = hgapi.Repo (repo_name)
362 commit_data = [] 317 commit_data = []
363 delimeter = '^^^^^^^^^^' 318 delimeter = '^^^^^^^^^^'
364 delimeter2 = '@@@@@@@@@@' 319 delimeter2 = '@@@@@@@@@@'
320 maxcommits = 15
321 numcommits = 0
365 print 'Checking %s for updates' % repo_name 322 print 'Checking %s for updates' % repo_name
366 323
367 try: 324 try:
368 data = repo.hg_command ('incoming', '--quiet', '--template', 325 data = subprocess.check_output (['hg', '--cwd', repo_name, 'incoming',
369 delimeter.join (['{node|short}', '{desc}']) + delimeter2).split (delimeter2) 326 '--limit', str(maxcommits), '--quiet', '--template',
370 except hgapi.hgapi.HgException as e: 327 delimeter.join (['{node|short}', '{desc}']) + delimeter2]).split (delimeter2)
371 deciphered = decipher_hgapi_error (e) 328 except subprocess.CalledProcessError:
372
373 if deciphered[0] and len(deciphered[1]) > 0:
374 Irc.broadcast ("error while using hg incoming on %s: %s" % (repo_name, deciphered[1]))
375
376 return 329 return
377 except Exception as e: 330 except Exception as e:
378 Irc.broadcast ("%s" % `e`) 331 Irc.broadcast (e.__class__.__name__ + ": " + str (e))
379 return 332 return
380
381 if not data:
382 print ('No updates to %s' % repo_name)
383 333
384 for line in data: 334 for line in data:
385 if line: 335 if line:
336 numcommits += 1
386 commit_data.append (line.split (delimeter)) 337 commit_data.append (line.split (delimeter))
387 338
388 process_new_commits (repo_name, commit_data) 339 process_new_commits (repo_name, commit_data)
340
341 if numcommits == maxcommits:
342 # If we have 25 commits here, there may be more coming so recheck sooner
343 global repocheck_timeout
344 print ('Processed %d commits, checking for new commits in 1 minute...' % len(data))
345 repocheck_timeout = time.time() + 60
389 346
390 def process_new_commits (repo_name, commit_data): 347 def process_new_commits (repo_name, commit_data):
391 if len (commit_data) == 0: 348 if len (commit_data) == 0:
392 return 349 return
393 350
394 repo_name = repo_name.lower() 351 repo_name = repo_name.lower()
395 repo_url = get_repo_info (repo_name).get_value ('url') 352 repo_url = get_repo_info (repo_name).get_value ('url')
396 isExtraRepo = get_repo_info (repo_name).get_value ('extrarepo', False) 353 isExtraRepo = get_repo_info (repo_name).get_value ('extrarepo', False)
397 zanrepo = hgapi.Repo (repo_name) 354 print ('%d new commits on %s' % (len (commit_data), repo_name))
398 print '%d new commits on %s' % (len (commit_data), repo_name)
399 pull_args = [] 355 pull_args = []
400 messages = [[], [], []] 356 messages = [[], [], []]
401 messageSizeClass = 2
402 357
403 for commit in commit_data: 358 for commit in commit_data:
404 pull_args.append ('-r'); 359 pull_args.append ('-r');
405 pull_args.append (commit[0]); 360 pull_args.append (commit[0]);
406 361
407 print 'Pulling new commits...' 362 print ('Pulling new commits...')
408 try: 363 try:
409 zanrepo.hg_command ('pull', *pull_args) 364 subprocess.call (['hg', '--cwd', repo_name, 'pull'] + pull_args)
410 except Exception as e: 365 except Exception as e:
411 Irc.broadcast ('Warning: unable to pull: %s' % `e`) 366 Irc.broadcast ('Warning: unable to pull: %s' % `e`)
412 return 367 return
368
369 LENGTH_MINIMUM, LENGTH_SHORT, LENGTH_FULL = range (0, 3)
413 370
414 for commit in commit_data: 371 for commit in commit_data:
415 commit_node = commit[0] 372 commit_node = commit[0]
416 commit_message = commit[1] 373 commit_message = commit[1]
417 print 'Processing new commit %s...' % commit_node 374 print ('Processing new commit %s...' % commit_node)
418 375
419 try: 376 try:
420 existingrepos = g_CommitsDb.get_commit_repos (commit_node) 377 existingrepos = g_CommitsDb.get_commit_repos (commit_node)
421 alreadyAdded = len (existingrepos) > 0 378 alreadyAdded = len (existingrepos) > 0
422 379
423 delim = '@@@@@@@@@@' 380 delim = '@@@@@@@@@@'
424 data = get_commit_data (zanrepo, commit_node, delim.join (['{node}', '{author}', '{bookmarks}', \ 381 data = get_commit_data (repo_name, commit_node, delim.join (['{node}', '{author|person}',
425 '{date|hgdate}'])).split (delim) 382 '{bookmarks}', '{date|hgdate}', '{author|email}'])).split (delim)
426 commit_full_node = data[0] 383 commit_full_node = data[0]
427 commit_author = data[1] 384 commit_author = data[1]
428 commit_bookmarks = prettify_bookmarks (data[2]) 385 commit_bookmarks = prettify_bookmarks (data[2])
429 commit_time = int (data[3].split (' ')[0]) 386 commit_time = int (data[3].split (' ')[0])
430 commit_url = '%s/commits/%s' % (repo_url, commit_node) 387 commit_url = '%s/commits/%s' % (repo_url, commit_node)
431 commit_email = '' 388 commit_email = data[4]
389 isMergeFromSandbox = False
432 390
433 # If the commit was already in the commits database, it is not a new one and we should 391 # If the commit was already in the commits database, it is not a new one and we should
434 # not react to it. Still add it to the db though so that the new repo name is added. 392 # not react to it. Still add it to the db though so that the new repo name is added.
435 g_CommitsDb.add_commit (repo=repo_name, changeset=commit_full_node, timestamp=commit_time) 393 g_CommitsDb.add_commit (repo=repo_name, changeset=commit_full_node, timestamp=commit_time)
394
436 if alreadyAdded: 395 if alreadyAdded:
437 print ('''I already know of %s - they're in %s - not announcing.''' % 396 if not contains_published_repositories (existingrepos) and is_published (repo_name):
438 (commit_node, existingrepos)) 397 isMergeFromSandbox = True
439 continue 398 print ('''%s appears to be a merge from sandbox (exists in %s)''' %
440 399 (commit_node, existingrepos))
441 # Remove the email address from the author if possible 400 else:
442 rex = re.compile (r'^(.+) <([^>]+)>$.*') 401 print ('''I already know of %s - they're in %s - not announcing.''' %
443 match = rex.match (commit_author) 402 (commit_node, existingrepos))
444 if match: 403 continue
445 commit_author = match.group (1)
446 commit_email = match.group (2)
447 404
448 commit_trackeruser = Config.find_developer_by_email (commit_email) 405 commit_trackeruser = Config.find_developer_by_email (commit_email)
449 committer = commit_trackeruser if commit_trackeruser != '' else commit_author 406 committer = commit_trackeruser if commit_trackeruser else commit_author
450 407 commitDescriptor = """commit""" if int (random.random() * 100) != 0 else """KERMIT"""
451 commitDescriptor = """commit""" if int (math.ceil (random.random() * 100)) != 1 else """KERMIT""" 408
452 409 if not isMergeFromSandbox:
453 commitMessage = """\003%d%s\003: new %s\0035 %s%s\003 by\0032 %s\003: %s""" % \ 410 commitMessage = """\003%d%s\003: new %s\0035 %s%s\003 by\0032 %s\003: %s""" % \
454 (color_for_repo (repo_name), repo_name, commitDescriptor, commit_node, commit_bookmarks, 411 (color_for_repo (repo_name), repo_name, commitDescriptor, commit_node, commit_bookmarks,
455 committer, utility.shorten_link (commit_url)) 412 committer, utility.shorten_link (commit_url))
456 413
457 messages[0].append (commitMessage) 414 for length in [LENGTH_MINIMUM, LENGTH_SHORT, LENGTH_FULL]:
458 messages[1].append (commitMessage) 415 messages[length].append (commitMessage)
459 messages[2].append (commitMessage) 416
460 messages[1].append (' ' + commit_message.splitlines()[0]) 417 messages[LENGTH_SHORT].append (' ' + commit_message.splitlines()[0])
461 418
462 for line in commit_message.splitlines()[0:4]: 419 for line in commit_message.splitlines()[0:4]:
463 messages[2].append (' ' + line) 420 messages[LENGTH_FULL].append (' ' + line)
421 else:
422 commitMessage = """\003%d%s\003: %s\0035 %s%s\003 by\0032 %s\003 was pulled: %s""" % \
423 (color_for_repo (repo_name), repo_name, commitDescriptor, commit_node, commit_bookmarks,
424 committer, utility.shorten_link (commit_url))
425
426 for length in [LENGTH_MINIMUM, LENGTH_SHORT, LENGTH_FULL]:
427 messages[length].append (commitMessage)
464 428
465 if not isExtraRepo: 429 if not isExtraRepo:
466 rex = re.compile (r'^.*(fixes|resolves|addresses|should fix) ([0-9]+).*$') 430 rex = re.compile (r'^.*(fixes|resolves|addresses|should fix) ([0-9]+).*$')
467 431
468 for line in commit_message.splitlines(): 432 for line in commit_message.splitlines():
476 continue 440 continue
477 441
478 fullMessageLength = len (''.join (messages[2])) 442 fullMessageLength = len (''.join (messages[2]))
479 443
480 if fullMessageLength > 3000: 444 if fullMessageLength > 3000:
481 messageSizeClass = 0 445 messageSizeClass = LENGTH_MINIMUM
482 elif fullMessageLength > 768: 446 elif fullMessageLength > 768:
483 messageSizeClass = 1 447 messageSizeClass = LENGTH_SHORT
484 448 else:
485 print ("""Message length in total: %d, using size class %d (%d)""" %\ 449 messageSizeClass = LENGTH_FULL
486 (fullMessageLength, messageSizeClass, len (''.join (messages[messageSizeClass]))))
487 450
488 # Post it all on IRC now 451 # Post it all on IRC now
489 for message in messages[messageSizeClass]: 452 for message in messages[messageSizeClass]:
490 for irc_client in Irc.all_clients: 453 for irc_client in Irc.all_clients:
491 for channel in irc_client.channels: 454 for channel in irc_client.channels:
495 if isExtraRepo and not channel.get_value ('allpublishing', False): 458 if isExtraRepo and not channel.get_value ('allpublishing', False):
496 continue 459 continue
497 460
498 irc_client.privmsg (channel.get_value ('name'), message) 461 irc_client.privmsg (channel.get_value ('name'), message)
499 462
500 # Hack for ZDoom upgrades
501 if repo_name == 'zandronum-merge-experiments':
502 check_zdoom_upgrade (repo_name, commit_node)
503
504 g_CommitsDb.commit() 463 g_CommitsDb.commit()
505 464
506 def make_progress_bar (p, barLength, colored=True): 465 def make_progress_bar (p, barLength, colored=True):
507 BoldChar, ColorChar = (Irc.BoldChar, Irc.ColorChar) 466 BoldChar, ColorChar = (Irc.BoldChar, Irc.ColorChar)
508 return BoldChar + '[' + BoldChar \ 467 return BoldChar + '[' + BoldChar \
509 + ColorChar + '2,2' + ('=' * int (round (p * barLength))) \ 468 + ColorChar + '2,2' + ('=' * int (round (p * barLength))) \
510 + ColorChar + '1,1' + ('-' * int (barLength - round (p * barLength))) \ 469 + ColorChar + '1,1' + ('-' * int (barLength - round (p * barLength))) \
511 + ColorChar + BoldChar + ']' + BoldChar 470 + ColorChar + BoldChar + ']' + BoldChar
512 471
513 ZDoomMin = 2560
514 ZDoomMax = 4341
515
516 def check_zdoom_upgrade (repo_name, commit_node):
517 zanrepo = hgapi.Repo (repo_name)
518 try:
519 global ZDoomRevNumber
520 newnumber = get_zdrev_number (repo_name, commit_node)
521
522 if newnumber > ZDoomRevNumber:
523 ZDoomRevNumber = newnumber
524 update_zadev_topic()
525 except Exception as e:
526 Irc.broadcast ('Error while dealing with ZDoom upgrade number: %s' % e)
527
528 def update_zadev_topic():
529 return
530 fraction = float (ZDoomRevNumber - ZDoomMin) / (ZDoomMax - ZDoomMin)
531 topicText = """ZDoom r%d progress: at r%d, %d revisions left (%d%% complete)""" %\
532 (ZDoomMax, ZDoomRevNumber, ZDoomMax - ZDoomRevNumber, round (fraction * 100))
533
534 try:
535 Irc.ClientsByName['zandronum'].write ("""TOPIC #zadev :%s""" % topicText)
536 Irc.ClientsByName['zandronum'].write ("""TOPIC #commits :%s""" % topicText)
537 except Exception as e:
538 Irc.broadcast ("""Error setting #zadev topic: %s""" % e)
539
540 def get_zdrev_number (repo_name, commit_node):
541 zanrepo = hgapi.Repo (repo_name)
542 subprocess.call (['hg', '--cwd', repo_name, 'revert', '-r', commit_node, 'src/version.h'])
543 rx = re.compile (r'#define\s+ZD_SVN_REVISION_NUMBER\s+([0-9]+)')
544 result = None
545
546 with open (repo_name + '/src/version.h') as version_file:
547 for line in version_file:
548 match = rx.match (line)
549 if match != None:
550 result = int (match.group (1))
551 break
552
553 subprocess.call (['hg', '--cwd', repo_name, 'revert', '-r.', 'src/version.h'])
554
555 if result != None:
556 return result
557
558 raise ValueError ("""Could not find ZD_SVN_REVISION_NUMBER in version.h""")
559
560 def force_poll(): 472 def force_poll():
561 global repocheck_timeout 473 global repocheck_timeout
562 repocheck_timeout = 0 474 repocheck_timeout = 0
563 poll() 475 poll()

mercurial