diff -r 2266d6d73de3 -r d67cc4fbc3f1 hgpoll.py --- a/hgpoll.py Sun Nov 09 19:59:10 2014 +0200 +++ b/hgpoll.py Mon Nov 10 02:06:06 2014 +0200 @@ -1,40 +1,43 @@ -impot hgapi +import hgapi +import time +import re +import bt as Bt +import irc as Irc +from datetime import datetime from configfile import Config g_needCommitsTxtRebuild = True def make_commits_txt(): global g_needCommitsTxtRebuild - + if g_needCommitsTxtRebuild == False: return - + print 'Building commits.txt...' # Update zandronum-everything repo = hgapi.Repo ('zandronum-everything') repo.hg_command ('pull', '../zandronum-sandbox') repo.hg_command ('pull', '../zandronum-sandbox-stable') - data = repo.hg_command ('log', '--template', '{node} {date|hgdate}\n') - f = open ('commits.txt', 'w') - + for line in data.split ('\n'): if line == '': continue - + words = line.split (' ') timestamp = int (words[1]) f.write ('%s %s\n' % (words[0], datetime.utcfromtimestamp (timestamp).strftime ('%y%m%d-%H%M'))) + f.close() g_needCommitsTxtRebuild = False -#enddef ' Check if a repository exists ' def check_repo_exists (repo_name, repo_owner): print 'Checking that %s exists...' % repo_name repo_url = 'https://bitbucket.org/%s/%s' % (repo_owner, repo_name) zanrepo = hgapi.Repo (repo_name) - + try: zanrepo.hg_command ('id', '.') except hgapi.hgapi.HgException: @@ -42,7 +45,7 @@ if repo_name == 'zandronum-everything': if not os.path.exists (repo_name): os.makedirs (repo_name) - + global g_needCommitsTxtRebuild g_needCommitsTxtRebuild = True print 'Init %s' % repo_name @@ -54,29 +57,26 @@ print 'Done' make_commits_txt() return - #fi - + try: print 'Cloning %s...' % repo_name zanrepo.hg_clone (repo_url, repo_name) print 'Cloning done.' except Exception as e: print 'Unable to clone %s from %s: %s' % (repo_name, repo_url, str (`e`)) - quit(1) - #tried -#enddef + quit (1) -check_repo_exists ('zandronum', 'Torr_Samaho') -check_repo_exists ('zandronum-stable', 'Torr_Samaho') -check_repo_exists ('zandronum-sandbox', 'crimsondusk') -check_repo_exists ('zandronum-sandbox-stable', 'crimsondusk') -check_repo_exists ('zandronum-everything', '') - -repocheck_timeout = (time.time()) + 15 +def init(): + check_repo_exists ('zandronum', 'Torr_Samaho') + check_repo_exists ('zandronum-stable', 'Torr_Samaho') + check_repo_exists ('zandronum-sandbox', 'crimsondusk') + check_repo_exists ('zandronum-sandbox-stable', 'crimsondusk') + check_repo_exists ('zandronum-everything', '') + global repocheck_timeout + repocheck_timeout = (time.time()) + 15 def get_commit_data (zanrepo, rev, template): return zanrepo.hg_command ('log', '-l', '1', '-r', rev, '--template', template) -#enddef def decipher_hgapi_error (e): # Blah, hgapi, why must your error messages be so mangled? @@ -86,119 +86,99 @@ return [True, errmsg] except: return [False, ''] - #endtry -#enddef -def bbcodify(commit_diffstat): - result='' +def bbcodify (commit_diffstat): + result = '' + for line in commit_diffstat.split('\n'): - # Add green color-tags for the ++++++++++ stream rex = re.compile (r'^(.*)\|(.*) (\+*)(-*)(.*)$') match = rex.match (line) if match: line = '%s|%s [color=#5F7]%s[/color][color=#F53]%s[/color]%s\n' \ % (match.group (1), match.group (2), match.group (3), match.group (4), match.group (5)) - + # Tracker doesn't seem to like empty color tags line = line.replace ('[color=#5F7][/color]', '').replace ('[color=#F53][/color]', '') - #else: - #rex = re.compile (r'^(.*) ([0-9]+) insertions\(\+\), ([0-9]+) deletions\(\-\)$') - #match = rex.match (line) - #if match: - #line = '%s [b][color=green]%s[/color][/b] insertions, [b][color=red]%s[/color][/b] deletions\n' \ - #% (match.group (1), match.group (2), match.group (3)) - + result += line - #done - + return result -#enddef def find_developer_by_email (commit_email): for developer, emails in Config.get_value ('developer_emails', default={}).iteritems(): - for email in emails: - if commit_email == email: - return developer - #fi - #done - #done - + if commit_email in emails: + return developer + return '' -#enddef -' Retrieves and processes commits for zandronum repositories ' -' Ensure both repositories are OK before using this! ' def poll(): + global repocheck_timeout + if time.time() < repocheck_timeout: + return + for n in ['zandronum-stable', 'zandronum', 'zandronum-sandbox', 'zandronum-sandbox-stable']: - process_one_repo (n) + poll_one_repo (n) + + hgns = Config.get_node ('hg') + repocheck_timeout = time.time() + hgns.get_value ('checkinterval', default=15) * 60 -def process_one_repo (repo_name): +def poll_one_repo (repo_name): global repocheck_timeout - global g_clients - hgns = Config.get_node ('hg') if not hgns.get_value ('track', default=True): return - + usestable = repo_name == 'zandronum-stable' usesandbox = repo_name == 'zandronum-sandbox' or repo_name == 'zandronum-sandbox-stable' repo_owner = 'Torr_Samaho' if not usesandbox else 'crimsondusk' repo_url = 'https://bitbucket.org/%s/%s' % (repo_owner, repo_name) num_commits = 0 - btuser, btpassword = bt_credentials() - - if time.time() < repocheck_timeout: - return - - repocheck_timeout = time.time() + hgns.get_value ('checkinterval', default=15) * 60 zanrepo = hgapi.Repo (repo_name) commit_data = [] delimeter = '@@@@@@@@@@' - + print 'Checking %s for updates' % repo_name + try: data = zanrepo.hg_command ('incoming', '--quiet', '--template', '{node|short} {desc}' + delimeter) except hgapi.hgapi.HgException as e: deciphered = decipher_hgapi_error (e) - + if deciphered[0] and len(deciphered[1]) > 0: - chanlog ("error while using hg import on %s: %s" % (repo_name, deciphered[1])) - #fi - + Irc.broadcast ("error while using hg import on %s: %s" % (repo_name, deciphered[1])) + return except Exception as e: - chanlog ("%s" % `e`) + Irc.broadcast ("%s" % `e`) return - #tried - + for line in data.split (delimeter): if line == '': continue - #fi - + rex = re.compile (r'([^ ]+) (.+)') match = rex.match (line) failed = False if not match: - chanlog ('malformed hg data: %s' % line) + Irc.broadcast ('malformed hg data: %s' % line) continue - #fi - + commit_node = match.group (1) commit_message = match.group (2) commit_data.append ([commit_node, commit_message]) - #done - + + print '%d new commits on %s' % (len (commit_data), repo_name) + if len (commit_data) > 0: pull_args = []; - + for commit in commit_data: pull_args.append ('-r'); pull_args.append (commit[0]); - #done - + + print 'Pulling new commits...' try: zanrepo.hg_command ('pull', *pull_args) @@ -206,8 +186,7 @@ if usestable: devrepo = hgapi.Repo ('zandronum') devrepo.hg_command ('pull', '../zandronum-stable', *pull_args) - #fi - + # Pull everything into sandboxes too if not usesandbox: devrepo = hgapi.Repo ('zandronum-sandbox') @@ -215,130 +194,116 @@ devrepo = hgapi.Repo ('zandronum-sandbox-stable') devrepo.hg_command ('pull', '../%s' % repo_name, *pull_args) - #fi - + devrepo = hgapi.Repo ('zandronum-everything') devrepo.hg_command ('pull', '../%s' % repo_name, *pull_args) global g_needCommitsTxtRebuild g_needCommitsTxtRebuild = True except Exception as e: - chanlog ('Warning: unable to pull: %s' % `e`) + Irc.broadcast ('Warning: unable to pull: %s' % `e`) return - #tried - #fi - + for commit in commit_data: commit_node = commit[0] commit_message = commit[1] - + print 'Processing new commit %s...' % commit_node + try: if usesandbox: commit_author = get_commit_data (zanrepo, commit_node, '{author}') commit_url = '%s/commits/%s' % (repo_url, commit_node) commit_email = '' - + # Remove the email address from the author if possible rex = re.compile (r'^(.+) <([^>]+)>$.*') match = rex.match (commit_author) if match: commit_author = match.group (1) commit_email = match.group (2) - #fi - + commit_trackeruser = find_developer_by_email (commit_email) committer = commit_trackeruser if commit_trackeruser != '' else commit_author - - for irc_client in g_clients: - for channel in irc_client.cfg['channels']: - if 'btprivate' in channel and channel['btprivate'] == True: - irc_client.privmsg (channel['name'], + + for irc_client in Irc.all_clients: + for channel in irc_client.channels: + if channel.get_value ('btprivate', False): + irc_client.privmsg (channel.get_value ('name'), "%s: new commit %s by %s: %s" % (repo_name, commit_node, committer, commit_url)) - + for line in commit_message.split ('\n'): - irc_client.privmsg (channel['name'], line) - #fi - #done - #done - + irc_client.privmsg (channel.get_value ('name'), line) + num_commits += 1 continue - #fi - + rex = re.compile (r'^.*(fixes|resolves|addresses|should fix) ([0-9]+).*$') match = rex.match (commit_message) - + if not match: continue # no "fixes" message in the commit - #fi - + ticket_id = int (match.group (2)) - + # Acquire additional data moredata = get_commit_data (zanrepo, commit_node, '{author|nonempty}\n{date(date, \'%A %d %B %Y %T\')}').split('\n') - + if len (moredata) != 2: - chanlog ('error while processing %s: malformed hg data' % commit_node) + Irc.broadcast ('error while processing %s: malformed hg data' % commit_node) continue - #fi - + commit_author = moredata[0] commit_date = moredata[1] commit_email = "" - + try: - ticket_data = suds_client.service.mc_issue_get (btuser, btpassword, ticket_id) + ticket_data = Bt.get_issue (ticket_id) except Exception as e: - chanlog ('error while processing %s: %s' % (commit_node, `e`)) + Irc.broadcast ('error while processing %s: %s' % (commit_node, `e`)) continue - #tried - + # Remove the email address from the author if possible rex = re.compile (r'^(.+) <([^>]+)>$.*') match = rex.match (commit_author) if match: commit_author = match.group (1) commit_email = match.group (2) - #fi - + commit_diffstat = zanrepo.hg_command ('diff', '--change', commit_node, '--stat') - + if len(commit_diffstat) > 0: # commit_diffstat = 'Changes in files:\n[code]\n' + commit_diffstat + '\n[/code]' commit_diffstat = 'Changes in files:\n' + bbcodify(commit_diffstat) else: commit_diffstat = 'No changes in files.' - + # Compare the email addresses against known developer usernames commit_trackeruser = find_developer_by_email (commit_email) - + if commit_trackeruser != '': commit_author += ' [%s]' % commit_trackeruser - #fi - + message = 'Issue addressed by commit %s: [b][url=%s/commits/%s]%s[/url][/b]' \ % (commit_node, repo_url, commit_node, commit_message) message += "\nCommitted by %s on %s\n\n%s" \ % (commit_author, commit_date, commit_diffstat) - + need_update = False - + # If not already set, set handler if not 'handler' in ticket_data: ticket_data['handler'] = {'name': commit_trackeruser} need_update = True - #fi - + # Find out the status level of the ticket needs_testing_level = 70 if ticket_data['status']['id'] < needs_testing_level: ticket_data.status['id'] = needs_testing_level need_update = True - #fi - + # Set target version if not set if not 'target_version' in ticket_data: ticket_data['target_version'] = '1.4' if repo_name == 'zandronum-stable' else '2.0' @@ -352,37 +317,30 @@ # Fix target version from 2.0-beta to 2.0 ticket_data['target_version'] = '2.0' need_update = True - #fi - + # Announce on IRC - for irc_client in g_clients: + for irc_client in Irc.all_clients: for channel in irc_client.channels: if channel.get_value ('btannounce', default=True): irc_client.privmsg (channel.get_value ('name'), "%s: commit %s fixes issue %d: %s" % (repo_name, commit_node, ticket_id, commit_message)) irc_client.privmsg (channel.get_value ('name'), - "Read all about it here: " + irc_client.get_ticket_url (ticket_id)) - #fi - #done - #done - + "Read all about it here: " + Bt.get_ticket_url (ticket_id)) + if need_update: # We need to remove the note data, otherwise the ticket notes # will get unnecessary updates. WTF, MantisBT? ticket_data.notes = [] - suds_client.service.mc_issue_update (btuser, btpassword, ticket_id, ticket_data) - #fi - - suds_client.service.mc_issue_note_add (btuser, btpassword, ticket_id, { 'text': message }) + Bt.update_issue (ticket_id, ticket_data) + + Bt.post_note (ticket_id, message) num_commits += 1 except Exception as e: - chanlog ('Error while processing %s: %s' % (commit_node, `e`)) + Irc.broadcast ('Error while processing %s: %s' % (commit_node, e)) continue - #tried - #done -#enddef def force_poll(): + global repocheck_timeout repocheck_timeout = 0 poll() \ No newline at end of file