X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=irkerhook.py;h=d17248a59552e8cb098b439f49ebfc9a1693d3ac;hb=dde3c700cd93680dd9a9898fe30204f6ae36e7de;hp=38b3552cac84349ed856226793b5c6b43549033c;hpb=c07938fb9a088b14749c08899eff215a935804fe;p=irker.git diff --git a/irkerhook.py b/irkerhook.py index 38b3552..d17248a 100755 --- a/irkerhook.py +++ b/irkerhook.py @@ -37,7 +37,7 @@ default_channels = "irc://chat.freenode.net/#commits" # No user-serviceable parts below this line: # -version = "1.19" +version = "2.6" import os, sys, commands, socket, urllib, subprocess, locale, datetime from pipes import quote as shellquote @@ -88,17 +88,20 @@ class Commit: self.url = webview except IOError: self.url = "" - return self.template % self.__dict__ + res = self.template % self.__dict__ + return unicode(res, 'UTF-8') if not isinstance(res, unicode) else res class GenericExtractor: "Generic class for encapsulating data from a VCS." booleans = ["tcp"] numerics = ["maxchannels"] + strings = ["email"] def __init__(self, arguments): self.arguments = arguments self.project = None self.repo = None # These aren't really repo data but they belong here anyway... + self.email = None self.tcp = True self.tinyifier = default_tinyifier self.server = None @@ -183,6 +186,8 @@ class GenericExtractor: setattr(self, key, False) elif key in GenericExtractor.numerics: setattr(self, key, int(val)) + elif key in GenericExtractor.strings: + setattr(self, key, val) if not self.project: sys.stderr.write("irkerhook.py: no project name set!\n") raise SystemExit(1) @@ -195,7 +200,11 @@ class GenericExtractor: def has(dirname, paths): "Test for existence of a list of paths." - return all([os.path.exists(os.path.join(dirname, x)) for x in paths]) + # all() is a python2.5 construct + for exists in [os.path.exists(os.path.join(dirname, x)) for x in paths]: + if not exists: + return False + return True # VCS-dependent code begins here @@ -213,6 +222,7 @@ class GitExtractor(GenericExtractor): self.repo = do("git config --get irker.repo") self.server = do("git config --get irker.server") self.channels = do("git config --get irker.channels") + self.email = do("git config --get irker.email") self.tcp = do("git config --bool --get irker.tcp") self.template = '%(bold)s%(project)s:%(reset)s %(green)s%(author)s%(reset)s %(repo)s:%(yellow)s%(branch)s%(reset)s * %(bold)s%(rev)s%(reset)s / %(bold)s%(files)s%(reset)s: %(logmsg)s %(brown)s%(url)s%(reset)s' self.tinyifier = do("git config --get irker.tinyifier") or default_tinyifier @@ -262,12 +272,11 @@ class GitExtractor(GenericExtractor): # Extract the meta-information for the commit commit.files = do("git diff-tree -r --name-only " + shellquote(commit.commit)) commit.files = " ".join(commit.files.strip().split("\n")[1:]) - # Design choice: for git we ship only the first line, which is + # Design choice: for git we ship only the first message line, which is # conventionally supposed to be a summary of the commit. Under # other VCSes a different choice may be appropriate. - metainfo = do("git log -1 '--pretty=format:%an <%ae>|%s' " + shellquote(commit.commit)) - (commit.author, _, commit.logmsg) = metainfo.partition("|") - commit.mail = commit.author.split()[-1].strip("<>") + commit.author_name, commit.mail, commit.logmsg = \ + do("git log -1 '--pretty=format:%an%n%ae%n%s' " + shellquote(commit.commit)).split("\n") # This discards the part of the author's address after @. # Might be be nice to ship the full email address, if not # for spammers' address harvesters - getting this wrong @@ -346,6 +355,7 @@ class HgExtractor(GenericExtractor): self.repo = ui.config('irker', 'repo') self.server = ui.config('irker', 'server') self.channels = ui.config('irker', 'channels') + self.email = ui.config('irker', 'email') self.tcp = str(ui.configbool('irker', 'tcp')) # converted to bool again in do_overrides self.template = '%(bold)s%(project)s:%(reset)s %(green)s%(author)s%(reset)s %(repo)s:%(yellow)s%(branch)s%(reset)s * %(bold)s%(rev)s%(reset)s / %(bold)s%(files)s%(reset)s: %(logmsg)s %(brown)s%(url)s%(reset)s' self.tinyifier = ui.config('irker', 'tinyifier') or default_tinyifier @@ -383,12 +393,20 @@ class HgExtractor(GenericExtractor): return commit def hg_hook(ui, repo, **kwds): - # To be called from a Mercurial "commit" or "incoming" hook. Example - # configuration: + # To be called from a Mercurial "commit", "incoming" or "changegroup" hook. + # Example configuration: # [hooks] # incoming.irker = python:/path/to/irkerhook.py:hg_hook extractor = HgExtractor([(ui, repo)]) - ship(extractor, kwds['node'], False) + start = repo[kwds['node']].rev() + end = len(repo) + if start != end: + # changegroup with multiple commits, so we generate a notification + # for each one + for rev in range(start, end): + ship(extractor, rev, False) + else: + ship(extractor, kwds['node'], False) # The files we use to identify a Subversion repo might occur as content # in a git or hg repo, but the special subdirectories for those are more @@ -447,7 +465,22 @@ def ship(extractor, commit, debug): print message elif channels: try: - if extractor.tcp: + if extractor.email: + # We can't really figure out what our SF username is without + # exploring our environment. The mail pipeline doesn't care + # about who sent the mail, other than being from sourceforge. + # A better way might be to simply call mail(1) + sender = "irker@users.sourceforge.net" + msg = """From: %(sender)s +Subject: irker json + +%(message)s""" % {"sender":sender, "message":message} + import smtplib + smtp = smtplib.SMTP() + smtp.connect() + smtp.sendmail(sender, extractor.email, msg) + smtp.quit() + elif extractor.tcp: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((extractor.server or default_server, IRKER_PORT))