Update to point at irker's new gitlab repo
[bzrirker.git] / irkerhook.py
1 # -*- coding: utf-8 -*-
2 # vim:fileencoding=utf-8 ai ts=4 sts=4 et sw=4
3 # Copyright 2012 Neil Muller
4 # GPL 2+ - see COPYING for details
5
6 from bzrlib.config import Option
7 import socket
8 import sys
9 import json
10
11 IRKER_PORT = 6659
12
13
14 class IrkerSender(object):
15     """An irker message sender."""
16
17     def __init__(self, branch, revision_id, config):
18         self.config = config
19         self.branch = branch
20         self._revision_id = revision_id
21         self.revision = None
22         self.revno = None
23
24     def _setup_revision_and_revno(self):
25         self.revision = self.branch.repository.get_revision(self._revision_id)
26         self.revno = self.branch.revision_id_to_revno(self._revision_id)
27
28     def _format(self):
29         """Munge the commit info into an irc message"""
30         delta = self.branch.repository.get_revision_delta(self._revision_id)
31         files = []
32         [files.append(f) for (f, _, _) in delta.added]
33         [files.append(f) for (f, _, _) in delta.removed]
34         [files.append(f) for (_, f, _, _, _, _) in delta.renamed]
35         [files.append(f) for (f, _, _, _, _) in delta.modified]
36
37         fields = {
38             'project': self.project(),
39             'committer': self.revision.committer,
40             'repo': self.branch.nick,
41             'rev': '%d' % self.revno,
42             'files': ' '.join(files),
43             'logmsg': self.revision.get_summary(),
44         }
45         if len(fields['files']) > 250:
46             # Dangerously long looking list of files, so truncate it
47             fields['files'] = fields['files'][:250]
48         fields.update(self.colours())
49         text = ('%(bold)s%(project)s:%(reset)s '
50                 '%(green)s%(committer)s%(reset)s '
51                 '%(repo)s * %(bold)s%(rev)s%(reset)s / '
52                 ' %(bold)s%(files)s%(reset)s: %(logmsg)s ' % fields)
53         return text
54
55     def colours(self):
56         """Utility function to handle the colours"""
57         colour_style = self.config.get('irker_colours')
58         colours = {
59                 'bold': '',
60                 'green': '',
61                 'blue': '',
62                 'red': '',
63                 'yellow': '',
64                 'brown': '',
65                 'magenta': '',
66                 'cyan': '',
67                 'reset': '',
68                 }
69         # Vaues taken from irker's irkerhook.py
70         if colour_style == 'ANSI':
71             colours = {
72                     'bold': '\x1b[1m',
73                     'green': '\x1b[1;32m',
74                     'blue': '\x1b[1;34m',
75                     'red':  '\x1b[1;31m',
76                     'yellow': '\x1b[1;33m',
77                     'brown': '\x1b[33m',
78                     'magenta': '\x1b[35m',
79                     'cyan': '\x1b[36m',
80                     'reset': '\x1b[0m',
81                     }
82         elif colour_style == 'mIRC':
83             colours = {
84                     'bold': '\x02',
85                     'green': '\x0303',
86                     'blue': '\x0302',
87                     'red': '\x0305',
88                     'yellow': '\x0307',
89                     'brown': '\x0305',
90                     'magenta': '\x0306',
91                     'cyan': '\x0310',
92                     'reset': '\x0F',
93                     }
94         return colours
95
96     def project(self):
97         project = self.config.get('irker_project')
98         if project is None:
99             project = 'No Project name set'
100         return project
101
102     def send(self):
103         """Send the info to irkerd.
104         """
105         self.branch.lock_read()
106         self.branch.repository.lock_read()
107         server = self.config.get('irker_server')
108         if not server:
109             server = 'localhost'
110         port = int(self.config.get('irker_port'))
111         if not port:
112             port = IRKER_PORT
113         try:
114             # Do this after we have locked, to make things faster.
115             self._setup_revision_and_revno()
116             channels = self.config.get('irker_channels')
117             if channels:
118                 channels = channels.split(',')
119             # If we're too long, we might not get any notification, so
120             # we truncate the msg to max 450 chars, and hope that's
121             # going to be within the 510 irc limit
122             msg = unicode(self._format())[:450]
123             message = json.dumps({"to": channels, "privmsg": msg})
124             if channels:
125                 # We assume tcp, since I'm lazy, so we just grab that bit
126                 # of irker's code
127                 try:
128                     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
129                     sock.connect((server, port))
130                     sock.sendall(message + "\n")
131                 except socket.error, e:
132                     sys.stderr.write("%s\n" % e)
133                 finally:
134                     sock.close()
135         finally:
136             self.branch.repository.unlock()
137             self.branch.unlock()
138
139 opt_irker_channels = Option('irker_channels',
140     help='Channel(s) to post commit messages to.')
141 opt_irker_colours = Option('irker_colours',
142     help='Colour option for irker.')
143 opt_irker_project = Option('irker_project',
144     help='Project name to use.')
145 opt_irker_server = Option('irker_server',
146     help='host for the irkerd server (default localhost).')
147 opt_irker_port = Option('irker_port',
148     help='port for the irkerd server (default %d)' % IRKER_PORT)