hgext/notify.py
changeset 3739 16f8e7d1dd54
parent 3679 2956948b81f3
child 3885 1e0b94cfba0e
child 4077 1305ba7dee88
equal deleted inserted replaced
3738:cb48cd27d3f4 3739:16f8e7d1dd54
    66 # push changes to, they can manage their own subscriptions.
    66 # push changes to, they can manage their own subscriptions.
    67 
    67 
    68 from mercurial.demandload import *
    68 from mercurial.demandload import *
    69 from mercurial.i18n import gettext as _
    69 from mercurial.i18n import gettext as _
    70 from mercurial.node import *
    70 from mercurial.node import *
    71 demandload(globals(), 'mercurial:commands,patch,cmdutil,templater,util,mail')
    71 demandload(globals(), 'mercurial:patch,cmdutil,templater,util,mail')
    72 demandload(globals(), 'email.Parser fnmatch socket time')
    72 demandload(globals(), 'email.Parser fnmatch socket time')
    73 
    73 
    74 # template for single changeset can include email headers.
    74 # template for single changeset can include email headers.
    75 single_template = '''
    75 single_template = '''
    76 Subject: changeset in {webroot}: {desc|firstline|strip}
    76 Subject: changeset in {webroot}: {desc|firstline|strip}
   105             self.ui.readsections(cfg, 'usersubs', 'reposubs')
   105             self.ui.readsections(cfg, 'usersubs', 'reposubs')
   106         self.repo = repo
   106         self.repo = repo
   107         self.stripcount = int(self.ui.config('notify', 'strip', 0))
   107         self.stripcount = int(self.ui.config('notify', 'strip', 0))
   108         self.root = self.strip(self.repo.root)
   108         self.root = self.strip(self.repo.root)
   109         self.domain = self.ui.config('notify', 'domain')
   109         self.domain = self.ui.config('notify', 'domain')
   110         self.sio = cmdutil.stringio()
       
   111         self.subs = self.subscribers()
   110         self.subs = self.subscribers()
   112 
   111 
   113         mapfile = self.ui.config('notify', 'style')
   112         mapfile = self.ui.config('notify', 'style')
   114         template = (self.ui.config('notify', hooktype) or
   113         template = (self.ui.config('notify', hooktype) or
   115                     self.ui.config('notify', 'template'))
   114                     self.ui.config('notify', 'template'))
   116         self.t = cmdutil.changeset_templater(self.ui, self.repo, mapfile,
   115         self.t = cmdutil.changeset_templater(self.ui, self.repo,
   117                                                self.sio)
   116                                              False, None, mapfile, False)
   118         if not mapfile and not template:
   117         if not mapfile and not template:
   119             template = deftemplates.get(hooktype) or single_template
   118             template = deftemplates.get(hooktype) or single_template
   120         if template:
   119         if template:
   121             template = templater.parsestring(template, quoted=False)
   120             template = templater.parsestring(template, quoted=False)
   122             self.t.use_template(template)
   121             self.t.use_template(template)
   175     def skipsource(self, source):
   174     def skipsource(self, source):
   176         '''true if incoming changes from this source should be skipped.'''
   175         '''true if incoming changes from this source should be skipped.'''
   177         ok_sources = self.ui.config('notify', 'sources', 'serve').split()
   176         ok_sources = self.ui.config('notify', 'sources', 'serve').split()
   178         return source not in ok_sources
   177         return source not in ok_sources
   179 
   178 
   180     def send(self, node, count):
   179     def send(self, node, count, data):
   181         '''send message.'''
   180         '''send message.'''
   182 
   181 
   183         p = email.Parser.Parser()
   182         p = email.Parser.Parser()
   184         self.sio.seek(0)
   183         msg = p.parsestr(data)
   185         msg = p.parse(self.sio)
       
   186 
   184 
   187         def fix_subject():
   185         def fix_subject():
   188             '''try to make subject line exist and be useful.'''
   186             '''try to make subject line exist and be useful.'''
   189 
   187 
   190             subject = msg['Subject']
   188             subject = msg['Subject']
   235 
   233 
   236     def diff(self, node, ref):
   234     def diff(self, node, ref):
   237         maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
   235         maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
   238         if maxdiff == 0:
   236         if maxdiff == 0:
   239             return
   237             return
   240         fp = cmdutil.stringio()
       
   241         prev = self.repo.changelog.parents(node)[0]
   238         prev = self.repo.changelog.parents(node)[0]
   242         patch.diff(self.repo, prev, ref, fp=fp)
   239         self.ui.pushbuffer()
   243         difflines = fp.getvalue().splitlines(1)
   240         patch.diff(self.repo, prev, ref)
       
   241         difflines = self.ui.popbuffer().splitlines(1)
   244         if self.ui.configbool('notify', 'diffstat', True):
   242         if self.ui.configbool('notify', 'diffstat', True):
   245             s = patch.diffstat(difflines)
   243             s = patch.diffstat(difflines)
   246             self.sio.write('\ndiffstat:\n\n' + s)
   244             self.ui.write('\ndiffstat:\n\n' + s)
   247         if maxdiff > 0 and len(difflines) > maxdiff:
   245         if maxdiff > 0 and len(difflines) > maxdiff:
   248             self.sio.write(_('\ndiffs (truncated from %d to %d lines):\n\n') %
   246             self.ui.write(_('\ndiffs (truncated from %d to %d lines):\n\n') %
   249                            (len(difflines), maxdiff))
   247                           (len(difflines), maxdiff))
   250             difflines = difflines[:maxdiff]
   248             difflines = difflines[:maxdiff]
   251         elif difflines:
   249         elif difflines:
   252             self.sio.write(_('\ndiffs (%d lines):\n\n') % len(difflines))
   250             self.ui.write(_('\ndiffs (%d lines):\n\n') % len(difflines))
   253         self.sio.write(*difflines)
   251         self.ui.write(*difflines)
   254 
   252 
   255 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
   253 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
   256     '''send email notifications to interested subscribers.
   254     '''send email notifications to interested subscribers.
   257 
   255 
   258     if used as changegroup hook, send one email for all changesets in
   256     if used as changegroup hook, send one email for all changesets in
   264     if n.skipsource(source):
   262     if n.skipsource(source):
   265         ui.debug(_('notify: changes have source "%s" - skipping\n') %
   263         ui.debug(_('notify: changes have source "%s" - skipping\n') %
   266                   source)
   264                   source)
   267         return
   265         return
   268     node = bin(node)
   266     node = bin(node)
       
   267     ui.pushbuffer()
   269     if hooktype == 'changegroup':
   268     if hooktype == 'changegroup':
   270         start = repo.changelog.rev(node)
   269         start = repo.changelog.rev(node)
   271         end = repo.changelog.count()
   270         end = repo.changelog.count()
   272         count = end - start
   271         count = end - start
   273         for rev in xrange(start, end):
   272         for rev in xrange(start, end):
   275         n.diff(node, repo.changelog.tip())
   274         n.diff(node, repo.changelog.tip())
   276     else:
   275     else:
   277         count = 1
   276         count = 1
   278         n.node(node)
   277         n.node(node)
   279         n.diff(node, node)
   278         n.diff(node, node)
   280     n.send(node, count)
   279     data = ui.popbuffer()
       
   280     n.send(node, count, data)