hgext/notify.py
author Bryan O'Sullivan <bos@serpentine.com>
Thu, 04 May 2006 12:25:10 -0700
changeset 2201 f15056b29472
child 2203 9569eea1707c
permissions -rw-r--r--
patch queue: notify.patch
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2201
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     1
from mercurial.demandload import *
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     2
from mercurial.i18n import gettext as _
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     3
from mercurial.node import *
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     4
demandload(globals(), 'email.MIMEText mercurial:templater,util fnmatch socket')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     5
demandload(globals(), 'time')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     6
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     7
class notifier(object):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     8
    def __init__(self, ui, repo):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     9
        self.ui = ui
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    10
        self.ui.readconfig(self.ui.config('notify', 'config'))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    11
        self.repo = repo
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    12
        self.stripcount = self.ui.config('notify', 'strip')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    13
        self.root = self.strip(self.repo.root)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    14
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    15
    def strip(self, path):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    16
        path = util.pconvert(path)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    17
        count = self.stripcount
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    18
        while path and count >= 0:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    19
            c = path.find('/')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    20
            if c == -1:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    21
                break
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    22
            path = path[c+1:]
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    23
            count -= 1
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    24
        return path
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    26
    def subscribers(self):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    27
        subs = []
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    28
        for user, pat in self.ui.configitems('usersubs'):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    29
            if fnmatch.fnmatch(self.root, pat):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    30
                subs.append(user)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
        for pat, users in self.ui.configitems('reposubs'):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    32
            if fnmatch.fnmatch(self.root, pat):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    33
                subs.extend([u.strip() for u in users.split(',')])
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
        subs.sort()
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    35
        return subs
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    36
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
    def seen(self, node):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    38
        pass
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    40
    def url(self, path=None):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    41
        return self.ui.config('web', 'baseurl') + (path or self.root)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    42
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
    def message(self, node, changes):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    44
        sio = templater.stringio()
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
        seen = self.seen(node)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
        if seen:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    47
            seen = self.strip(seen)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
            sio.write('Changeset %s merged to %s\n' %
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
                      (short(node), self.url()))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
            sio.write('First seen in %s\n' % self.url(seen))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
        else:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
            sio.write('Changeset %s new to %s\n' % (short(node), self.url()))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
        sio.write('Committed by %s at %s\n' %
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
                  (changes[1], templater.isodate(changes[2])))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
        sio.write('See %s?cmd=changeset;node=%s for full details\n' %
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
                  (self.url(), short(node)))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
        sio.write('\nDescription:\n')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    58
        sio.write(templater.indent(changes[4], '  '))
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    59
        msg = email.MIMEText.MIMEText(sio.getvalue(), 'plain')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    60
        firstline = changes[4].lstrip().split('\n', 1)[0].rstrip()
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    61
        subject = '%s %s: %s' % (self.root, self.repo.rev(node), firstline)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
        if seen:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
            subject = '[merge] ' + subject
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    64
        if subject.endswith('.'):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
            subject = subject[:-1]
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
        if len(subject) > 67:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    67
            subject = subject[:64] + '...'
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    68
        msg['Subject'] = subject
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    69
        msg['X-Hg-Repo'] = self.root
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    70
        if '@' in changes[1]:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    71
            msg['From'] = changes[1]
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    72
        else:
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    73
            msg['From'] = self.ui.config('email', 'from')
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    74
        msg['Message-Id'] = '<hg.%s.%s.%s@%s>' % (hex(node),
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
                                                  int(time.time()),
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    76
                                                  hash(self.repo.root),
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    77
                                                  socket.getfqdn())
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    78
        return msg
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    79
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    80
    def node(self, node):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    81
        mail = self.ui.sendmail()
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    82
        changes = self.repo.changelog.read(node)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    83
        fromaddr = self.ui.config('email', 'from', changes[1])
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    84
        msg = self.message(node, changes)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    85
        subs = self.subscribers()
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    86
        msg['To'] = ', '.join(subs)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    87
        msgtext = msg.as_string(0)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    88
        mail.sendmail(templater.email(fromaddr),
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    89
                      [templater.email(s) for s in subs],
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    90
                      msgtext)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    91
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    92
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    93
def hook(ui, repo, hooktype, node=None, **kwargs):
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    94
    n = notifier(ui, repo)
f15056b29472 patch queue: notify.patch
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    95
    n.node(bin(node))