Update to point at irker's new gitlab repo
[bzrirker.git] / irkerhook.py
index 99a9d3996205bfb9bf7bcdeed76a79870649e34f..e9aabc8477726d850f9779cb0f6844333f62c995 100644 (file)
 # Copyright 2012 Neil Muller
 # GPL 2+ - see COPYING for details
 
-from bzrlib import (
-    errors,
-    revision as _mod_revision,
-    )
-from bzrlib.config import (
-    ListOption,
-    Option,
-    bool_from_store,
-    int_from_store,
-    )
+from bzrlib.config import Option
+import socket
+import sys
+import json
+
+IRKER_PORT = 6659
 
 
 class IrkerSender(object):
     """An irker message sender."""
 
-    def __init__(self, branch, revision_id, config, local_branch=None,
-        op='commit'):
+    def __init__(self, branch, revision_id, config):
         self.config = config
         self.branch = branch
-        self.repository = branch.repository
-        if (local_branch is not None and
-            local_branch.repository.has_revision(revision_id)):
-            self.repository = local_branch.repository
         self._revision_id = revision_id
         self.revision = None
         self.revno = None
-        self.op = op
 
     def _setup_revision_and_revno(self):
-        self.revision = self.repository.get_revision(self._revision_id)
+        self.revision = self.branch.repository.get_revision(self._revision_id)
         self.revno = self.branch.revision_id_to_revno(self._revision_id)
 
     def _format(self):
+        """Munge the commit info into an irc message"""
+        delta = self.branch.repository.get_revision_delta(self._revision_id)
+        files = []
+        [files.append(f) for (f, _, _) in delta.added]
+        [files.append(f) for (f, _, _) in delta.removed]
+        [files.append(f) for (_, f, _, _, _, _) in delta.renamed]
+        [files.append(f) for (f, _, _, _, _) in delta.modified]
+
         fields = {
             'project': self.project(),
             'committer': self.revision.committer,
-            'repo': '',
+            'repo': self.branch.nick,
             'rev': '%d' % self.revno,
-            'files': '',
+            'files': ' '.join(files),
             'logmsg': self.revision.get_summary(),
-            'url': self.url(),
         }
-        for name, value in self.colours():
-            fields[name] = value
+        if len(fields['files']) > 250:
+            # Dangerously long looking list of files, so truncate it
+            fields['files'] = fields['files'][:250]
+        fields.update(self.colours())
         text = ('%(bold)s%(project)s:%(reset)s '
                 '%(green)s%(committer)s%(reset)s '
                 '%(repo)s * %(bold)s%(rev)s%(reset)s / '
-                ' %(bold)s%(files)s%(reset)s: %(logmsg)s '
-                '%(brown)s%(url)s%(reset)s' % fields)
+                ' %(bold)s%(files)s%(reset)s: %(logmsg)s ' % fields)
         return text
 
-    def body(self):
-        from bzrlib import log
-
-        rev1 = rev2 = self.revno
-        if rev1 == 0:
-            rev1 = None
-            rev2 = None
-
-        # use 'replace' so that we don't abort if trying to write out
-        # in e.g. the default C locale.
-
-        # Following bzr-email, we use StringIO.StringIO to minimise possible
-        # unicode issues.
-        from StringIO import StringIO
-        outf = StringIO()
-
-        lf = log.log_formatter('line',
-                               show_ids=True,
-                               to_file=outf
-                               )
-
-        if len(self.revision.parent_ids) <= 1:
-            # This is not a merge, so we can special case the display of one
-            # revision, and not have to encur the show_log overhead.
-            lr = log.LogRevision(self.revision, self.revno, 0, None)
-            lf.log_revision(lr)
-        else:
-            # let the show_log code figure out what revisions need to be
-            # displayed, as this is a merge
-            log.show_log(self.branch,
-                         lf,
-                         start_revision=rev1,
-                         end_revision=rev2,
-                         verbose=True
-                         )
-
-        return outf.getvalue()
-
-    def url(self):
-        """What URL to display in the subject of the mail"""
-        url = self.config.get('irker_url')
-        if url is None:
-            url = self.config.get('public_branch')
-        if url is None:
-            url = self.branch.base
-        return url
-
     def colours(self):
-        colour_style = self.config.get('irker_colors')
+        """Utility function to handle the colours"""
+        colour_style = self.config.get('irker_colours')
         colours = {
                 'bold': '',
                 'green': '',
@@ -117,32 +69,32 @@ class IrkerSender(object):
         # Vaues taken from irker's irkerhook.py
         if colour_style == 'ANSI':
             colours = {
-                    'bold': '\x1b[1m'
-                    'green': '\x1b[1;32m'
-                    'blue': '\x1b[1;34m'
-                    'red':  '\x1b[1;31m'
-                    'yellow': '\x1b[1;33m'
-                    'brown': '\x1b[33m'
-                    'magenta': '\x1b[35m'
-                    'cyan': '\x1b[36m'
-                    'reset': '\x1b[0m'
+                    'bold': '\x1b[1m',
+                    'green': '\x1b[1;32m',
+                    'blue': '\x1b[1;34m',
+                    'red':  '\x1b[1;31m',
+                    'yellow': '\x1b[1;33m',
+                    'brown': '\x1b[33m',
+                    'magenta': '\x1b[35m',
+                    'cyan': '\x1b[36m',
+                    'reset': '\x1b[0m',
                     }
         elif colour_style == 'mIRC':
             colours = {
-                    'bold': '\x02'
-                    'green': '\x0303'
-                    'blue': '\x0302'
-                    'red': '\x0305'
-                    'yellow': '\x0307'
-                    'brown': '\x0305'
-                    'magenta': '\x0306'
-                    'cyan': '\x0310'
-                    'reset': '\x0F'
+                    'bold': '\x02',
+                    'green': '\x0303',
+                    'blue': '\x0302',
+                    'red': '\x0305',
+                    'yellow': '\x0307',
+                    'brown': '\x0305',
+                    'magenta': '\x0306',
+                    'cyan': '\x0310',
+                    'reset': '\x0F',
                     }
         return colours
 
     def project(self):
-        projet = self.config.get('irker_project')
+        project = self.config.get('irker_project')
         if project is None:
             project = 'No Project name set'
         return project
@@ -151,19 +103,46 @@ class IrkerSender(object):
         """Send the info to irkerd.
         """
         self.branch.lock_read()
-        self.repository.lock_read()
+        self.branch.repository.lock_read()
+        server = self.config.get('irker_server')
+        if not server:
+            server = 'localhost'
+        port = int(self.config.get('irker_port'))
+        if not port:
+            port = IRKER_PORT
         try:
             # Do this after we have locked, to make things faster.
             self._setup_revision_and_revno()
+            channels = self.config.get('irker_channels')
+            if channels:
+                channels = channels.split(',')
+            # If we're too long, we might not get any notification, so
+            # we truncate the msg to max 450 chars, and hope that's
+            # going to be within the 510 irc limit
+            msg = unicode(self._format())[:450]
+            message = json.dumps({"to": channels, "privmsg": msg})
+            if channels:
+                # We assume tcp, since I'm lazy, so we just grab that bit
+                # of irker's code
+                try:
+                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+                    sock.connect((server, port))
+                    sock.sendall(message + "\n")
+                except socket.error, e:
+                    sys.stderr.write("%s\n" % e)
+                finally:
+                    sock.close()
         finally:
-            self.repository.unlock()
+            self.branch.repository.unlock()
             self.branch.unlock()
 
-opt_irker_url = Option('irker_url',
-    help='URL to mention for branch in messages.')
 opt_irker_channels = Option('irker_channels',
     help='Channel(s) to post commit messages to.')
 opt_irker_colours = Option('irker_colours',
     help='Colour option for irker.')
 opt_irker_project = Option('irker_project',
     help='Project name to use.')
+opt_irker_server = Option('irker_server',
+    help='host for the irkerd server (default localhost).')
+opt_irker_port = Option('irker_port',
+    help='port for the irkerd server (default %d)' % IRKER_PORT)