#!/usr/bin/python import sys import os import re LIBDIR = '<%= @gitolite_commonhooksdir %>' sys.path.insert(0, LIBDIR) import git_multimail import xmlrpclib from cookielib import CookieJar, LWPCookieJar from bugz.bugzilla import BugzillaProxy # When editing this list, remember to edit the same list in # modules/cgit/templates/filter.commit-links.sh BUG_REFS = { 'Mageia': { 're': re.compile('mga#([0-9]+)'), 'replace': 'https://bugs.mageia.org/show_bug.cgi?id=%s' }, 'Red Hat': { 're': re.compile('rhbz#([0-9]+)'), 'replace': 'https://bugzilla.redhat.com/show_bug.cgi?id=%s' }, 'Free Desktop': { 're': re.compile('fdo#([0-9]+)'), 'replace': 'https://bugs.freedesktop.org/show_bug.cgi?id=%s' }, 'KDE': { 're': re.compile('(?:bko|kde)#([0-9]+)'), 'replace': 'https://bugs.kde.org/show_bug.cgi?id=%s' }, 'GNOME': { 're': re.compile('(?:bgo|gnome)#([0-9]+)'), 'replace': 'https://bugzilla.gnome.org/show_bug.cgi?id=%s' }, 'Launchpad': { 're': re.compile('lp#([0-9]+)'), 'replace': 'https://launchpad.net/bugs/%s' }, } COMMIT_RE = re.compile('^commit ([a-f0-9]{40})') COMMIT_REPLACE = 'http://gitweb.mageia.org/%s/commit/?id=%s' MAGEIA_BUGZILLA_URL = 'https://bugs.mageia.org/xmlrpc.cgi' MAGEIA_BUGZILLA_PASSWORD_FILE = '.gitzilla-password' MAGEIA_BUGZILLA_COOKIE_FILE = '.gitzilla-cookie' git_multimail.FOOTER_TEMPLATE = """\ -- \n\ Mageia Git Monkeys. """ git_multimail.REVISION_FOOTER_TEMPLATE = git_multimail.FOOTER_TEMPLATE # Override the Environment class to generate an apporpriate short name which is # used in git links and as an email prefix class LinksEnvironment(git_multimail.Environment): REPO_NAME_RE = re.compile(r'^/git/(?P.+?)(?:\.git)?$') def get_repo_shortname(self): """Use the last part of the repo path, with ".git" stripped off if present.""" basename = os.path.abspath(self.get_repo_path()) m = self.REPO_NAME_RE.match(basename) if m: return m.group('name') else: return basename git_multimail.Environment = LinksEnvironment # Override the Reviesion class to inject gitweb/cgit links and any referenced # bug URLs class LinksRevision(git_multimail.Revision): bz = None def bugzilla_init(self): if self.bz is None: cookie_file = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_COOKIE_FILE) self.cookiejar = LWPCookieJar(cookie_file) try: self.cookiejar.load() except IOError: pass self.bz = BugzillaProxy(MAGEIA_BUGZILLA_URL, cookiejar=self.cookiejar) return self.bz def bugzilla_login(self): params = { 'login': 'bot', 'password': open(os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_PASSWORD_FILE), 'r').readline().rstrip(), 'remember': True } self.bz.User.login(params) self.cookiejar.save() os.chmod(self.cookiejar.filename, 0600) def bugzilla_call(self, method, *args): """Attempt to call method with args. Log in if authentication is required. """ try: return method(*args) except xmlrpclib.Fault, fault: # Fault code 410 means login required if fault.faultCode == 410: self.bugzilla_login() return method(*args) raise def generate_email_body(self, push): """Show this revision.""" output = git_multimail.read_git_lines( ['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1], keepends=True, ) bugs = {} commit = None idx = 0 for line in output: idx+=1 if line == "---\n": if commit and COMMIT_REPLACE: output.insert(idx, "\n") output.insert(idx, " %s\n" % (COMMIT_REPLACE % (self.environment.get_repo_shortname(), commit))) output.insert(idx, " Commit Link:\n") idx+=3 if bugs: output.insert(idx, " Bug links:\n") idx+=1 for tracker,bugnos in bugs.items(): output.insert(idx, " %s\n" % tracker) idx+=1 for bugno in bugnos: output.insert(idx, " %s\n" % (BUG_REFS[tracker]['replace'] % bugno)) idx+=1 output.insert(idx, "\n") idx+=1 # Attempt to modify bugzilla if "Mageia" in bugs: try: bz = self.bugzilla_init() # Mask email address comment = None # Suppress the "Bug links:" section if only one bug # is referenced if len(bugs) == 1 and len(bugs['Mageia']) == 1: comment = output[0:idx-4] else: comment = output[0:idx] comment[1] = re.sub(r'^(Author: [^@]*)@.*(>)?', r'\1@...>', comment[1]) comment = "".join(comment) params = {} params['ids'] = bugs['Mageia'] params['comment'] = { 'body': comment } self.bugzilla_call(bz.Bug.update, params) print "Updated bugzilla bugs: %s" % ", ".join(bugs['Mageia']) except: print "Unable to post to bugzilla bugs: %s :(" % ", ".join(bugs['Mageia']) pass break m = COMMIT_RE.search(line) if m: commit = m.group(1); for tracker in BUG_REFS.keys(): foundbugs = BUG_REFS[tracker]['re'].findall(line) if len(foundbugs): if not tracker in bugs: bugs[tracker] = foundbugs else: bugs[tracker] = list(set(bugs[tracker] + foundbugs)) return output git_multimail.Revision = LinksRevision if __name__ == '__main__': git_multimail.main(sys.argv[1:])