Simplfy entrypoint and add files code (both taken from bzr-cia)
[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 import (
7     errors,
8     revision as _mod_revision,
9     )
10 from bzrlib.config import (
11     ListOption,
12     Option,
13     bool_from_store,
14     int_from_store,
15     )
16 import socket
17 import sys
18 import json
19
20
21 class IrkerSender(object):
22     """An irker message sender."""
23
24     def __init__(self, branch, revision_id, config):
25         self.config = config
26         self.branch = branch
27         self.repository = branch.repository
28         self._revision_id = revision_id
29         self.revision = None
30         self.revno = None
31
32     def _setup_revision_and_revno(self):
33         self.revision = self.repository.get_revision(self._revision_id)
34         self.revno = self.branch.revision_id_to_revno(self._revision_id)
35
36     def _format(self):
37         delta = self.branch.repository.get_revision_delta(self._revision_id)
38         files = []
39         [files.append(f) for (f,_,_) in delta.added]
40         [files.append(f) for (f,_,_) in delta.removed]
41         [files.append(f) for (_,f,_,_,_,_) in delta.renamed]
42         [files.append(f) for (f,_,_,_,_) in delta.modified]
43
44         fields = {
45             'project': self.project(),
46             'committer': self.revision.committer,
47             'repo': self.branch.nick,
48             'rev': '%d' % self.revno,
49             'files': ' '.join(files),
50             'logmsg': self.revision.get_summary(),
51             'url': self.url(),
52         }
53         for name, value in self.colours():
54             fields[name] = value
55         text = ('%(bold)s%(project)s:%(reset)s '
56                 '%(green)s%(committer)s%(reset)s '
57                 '%(repo)s * %(bold)s%(rev)s%(reset)s / '
58                 ' %(bold)s%(files)s%(reset)s: %(logmsg)s '
59                 '%(brown)s%(url)s%(reset)s' % fields)
60         return text
61
62     def url(self):
63         """What URL to display in the subject of the mail"""
64         url = self.config.get('irker_url')
65         if url is None:
66             url = self.config.get('public_branch')
67         if url is None:
68             url = self.branch.base
69         return url
70
71     def colours(self):
72         colour_style = self.config.get('irker_colors')
73         colours = {
74                 'bold': '',
75                 'green': '',
76                 'blue': '',
77                 'red': '',
78                 'yellow': '',
79                 'brown': '',
80                 'magenta': '',
81                 'cyan': '',
82                 'reset': '',
83                 }
84         # Vaues taken from irker's irkerhook.py
85         if colour_style == 'ANSI':
86             colours = {
87                     'bold': '\x1b[1m',
88                     'green': '\x1b[1;32m',
89                     'blue': '\x1b[1;34m',
90                     'red':  '\x1b[1;31m',
91                     'yellow': '\x1b[1;33m',
92                     'brown': '\x1b[33m',
93                     'magenta': '\x1b[35m',
94                     'cyan': '\x1b[36m',
95                     'reset': '\x1b[0m',
96                     }
97         elif colour_style == 'mIRC':
98             colours = {
99                     'bold': '\x02',
100                     'green': '\x0303',
101                     'blue': '\x0302',
102                     'red': '\x0305',
103                     'yellow': '\x0307',
104                     'brown': '\x0305',
105                     'magenta': '\x0306',
106                     'cyan': '\x0310',
107                     'reset': '\x0F',
108                     }
109         return colours
110
111     def project(self):
112         project = self.config.get('irker_project')
113         if project is None:
114             project = 'No Project name set'
115         return project
116
117     def send(self):
118         """Send the info to irkerd.
119         """
120         self.branch.lock_read()
121         self.repository.lock_read()
122         # These should become configurable at some point
123         default_server = 'localhost'
124         IRKER_PORT = 6659
125         try:
126             # Do this after we have locked, to make things faster.
127             self._setup_revision_and_revno()
128             channels = self.config.get('irker_channels')
129             msg = unicode(self._format())
130             # We rely on the server truncating, rather than trying to be
131             # too fancy here
132             message = json.dumps({"to": channels, "privmsg": msg})
133             if channels:
134                 # We assume tcp, since I'm lazy, so we just grab that bit
135                 # of irker's code
136                 try:
137                     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
138                     sock.connect((default_server, IRKER_PORT))
139                     sock.sendall(message + "\n")
140                 except socket.error, e:
141                     sys.stderr.write("%s\n" % e)
142                 finally:
143                     sock.close()
144         finally:
145             self.repository.unlock()
146             self.branch.unlock()
147
148 opt_irker_url = Option('irker_url',
149     help='URL to mention for branch in messages.')
150 opt_irker_channels = Option('irker_channels',
151     help='Channel(s) to post commit messages to.')
152 opt_irker_colours = Option('irker_colours',
153     help='Colour option for irker.')
154 opt_irker_project = Option('irker_project',
155     help='Project name to use.')