hgext/notify.py
changeset 7726 2486980fe211
parent 7705 c55e68e8f256
child 7762 fece056bf240
equal deleted inserted replaced
7725:6a888d491eaf 7726:2486980fe211
   145                 return addr + '@' + self.domain
   145                 return addr + '@' + self.domain
   146         return addr
   146         return addr
   147 
   147 
   148     def subscribers(self):
   148     def subscribers(self):
   149         '''return list of email addresses of subscribers to this repo.'''
   149         '''return list of email addresses of subscribers to this repo.'''
   150 
       
   151         subs = {}
   150         subs = {}
   152         for user, pats in self.ui.configitems('usersubs'):
   151         for user, pats in self.ui.configitems('usersubs'):
   153             for pat in pats.split(','):
   152             for pat in pats.split(','):
   154                 if fnmatch.fnmatch(self.repo.root, pat.strip()):
   153                 if fnmatch.fnmatch(self.repo.root, pat.strip()):
   155                     subs[self.fixmail(user)] = 1
   154                     subs[self.fixmail(user)] = 1
   162                 for s in subs]
   161                 for s in subs]
   163 
   162 
   164     def url(self, path=None):
   163     def url(self, path=None):
   165         return self.ui.config('web', 'baseurl') + (path or self.root)
   164         return self.ui.config('web', 'baseurl') + (path or self.root)
   166 
   165 
   167     def node(self, node):
   166     def node(self, ctx):
   168         '''format one changeset.'''
   167         '''format one changeset.'''
   169 
   168         self.t.show(ctx, changes=ctx.changeset(),
   170         self.t.show(self.repo[node], changes=self.repo.changelog.read(node),
       
   171                     baseurl=self.ui.config('web', 'baseurl'),
   169                     baseurl=self.ui.config('web', 'baseurl'),
   172                     root=self.repo.root,
   170                     root=self.repo.root, webroot=self.root)
   173                     webroot=self.root)
       
   174 
   171 
   175     def skipsource(self, source):
   172     def skipsource(self, source):
   176         '''true if incoming changes from this source should be skipped.'''
   173         '''true if incoming changes from this source should be skipped.'''
   177         ok_sources = self.ui.config('notify', 'sources', 'serve').split()
   174         ok_sources = self.ui.config('notify', 'sources', 'serve').split()
   178         return source not in ok_sources
   175         return source not in ok_sources
   179 
   176 
   180     def send(self, node, count, data):
   177     def send(self, ctx, count, data):
   181         '''send message.'''
   178         '''send message.'''
   182 
   179 
   183         p = email.Parser.Parser()
   180         p = email.Parser.Parser()
   184         msg = p.parsestr(data)
   181         msg = p.parsestr(data)
   185 
   182 
   201         # try to make subject line exist and be useful
   198         # try to make subject line exist and be useful
   202         if not subject:
   199         if not subject:
   203             if count > 1:
   200             if count > 1:
   204                 subject = _('%s: %d new changesets') % (self.root, count)
   201                 subject = _('%s: %d new changesets') % (self.root, count)
   205             else:
   202             else:
   206                 changes = self.repo.changelog.read(node)
   203                 s = ctx.description().lstrip().split('\n', 1)[0].rstrip()
   207                 s = changes[4].lstrip().split('\n', 1)[0].rstrip()
       
   208                 subject = '%s: %s' % (self.root, s)
   204                 subject = '%s: %s' % (self.root, s)
   209         maxsubject = int(self.ui.config('notify', 'maxsubject', 67))
   205         maxsubject = int(self.ui.config('notify', 'maxsubject', 67))
   210         if maxsubject and len(subject) > maxsubject:
   206         if maxsubject and len(subject) > maxsubject:
   211             subject = subject[:maxsubject-3] + '...'
   207             subject = subject[:maxsubject-3] + '...'
   212         msg['Subject'] = mail.headencode(self.ui, subject,
   208         msg['Subject'] = mail.headencode(self.ui, subject,
   218         if '@' not in sender or '@localhost' in sender:
   214         if '@' not in sender or '@localhost' in sender:
   219             sender = self.fixmail(sender)
   215             sender = self.fixmail(sender)
   220         msg['From'] = mail.addressencode(self.ui, sender,
   216         msg['From'] = mail.addressencode(self.ui, sender,
   221                                          self.charsets, self.test)
   217                                          self.charsets, self.test)
   222 
   218 
   223         msg['X-Hg-Notification'] = 'changeset ' + short(node)
   219         msg['X-Hg-Notification'] = 'changeset %s' % ctx
   224         if not msg['Message-Id']:
   220         if not msg['Message-Id']:
   225             msg['Message-Id'] = ('<hg.%s.%s.%s@%s>' %
   221             msg['Message-Id'] = ('<hg.%s.%s.%s@%s>' %
   226                                  (short(node), int(time.time()),
   222                                  (ctx, int(time.time()),
   227                                   hash(self.repo.root), socket.getfqdn()))
   223                                   hash(self.repo.root), socket.getfqdn()))
   228         msg['To'] = ', '.join(self.subs)
   224         msg['To'] = ', '.join(self.subs)
   229 
   225 
   230         msgtext = msg.as_string(0)
   226         msgtext = msg.as_string(0)
   231         if self.test:
   227         if self.test:
   236             self.ui.status(_('notify: sending %d subscribers %d changes\n') %
   232             self.ui.status(_('notify: sending %d subscribers %d changes\n') %
   237                            (len(self.subs), count))
   233                            (len(self.subs), count))
   238             mail.sendmail(self.ui, util.email(msg['From']),
   234             mail.sendmail(self.ui, util.email(msg['From']),
   239                           self.subs, msgtext)
   235                           self.subs, msgtext)
   240 
   236 
   241     def diff(self, node, ref):
   237     def diff(self, ctx, ref=None):
       
   238 
   242         maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
   239         maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
   243         prev = self.repo.changelog.parents(node)[0]
   240         prev = ctx.parents()[0].node()
   244 
   241         ref = ref and ref.node() or ctx.node()
   245         chunks = patch.diff(self.repo, prev, ref, opts=patch.diffopts(self.ui))
   242         chunks = patch.diff(self.repo, prev, ref, opts=patch.diffopts(self.ui))
   246         difflines = ''.join(chunks).splitlines()
   243         difflines = ''.join(chunks).splitlines()
   247 
   244 
   248         if self.ui.configbool('notify', 'diffstat', True):
   245         if self.ui.configbool('notify', 'diffstat', True):
   249             s = patch.diffstat(difflines)
   246             s = patch.diffstat(difflines)
   250             # s may be nil, don't include the header if it is
   247             # s may be nil, don't include the header if it is
   251             if s:
   248             if s:
   252                 self.ui.write('\ndiffstat:\n\n%s' % s)
   249                 self.ui.write('\ndiffstat:\n\n%s' % s)
       
   250 
   253         if maxdiff == 0:
   251         if maxdiff == 0:
   254             return
   252             return
   255         if maxdiff > 0 and len(difflines) > maxdiff:
   253         elif maxdiff > 0 and len(difflines) > maxdiff:
   256             self.ui.write(_('\ndiffs (truncated from %d to %d lines):\n\n') %
   254             msg = _('\ndiffs (truncated from %d to %d lines):\n\n')
   257                           (len(difflines), maxdiff))
   255             self.ui.write(msg % (len(difflines), maxdiff))
   258             difflines = difflines[:maxdiff]
   256             difflines = difflines[:maxdiff]
   259         elif difflines:
   257         elif difflines:
   260             self.ui.write(_('\ndiffs (%d lines):\n\n') % len(difflines))
   258             self.ui.write(_('\ndiffs (%d lines):\n\n') % len(difflines))
       
   259 
   261         self.ui.write("\n".join(difflines))
   260         self.ui.write("\n".join(difflines))
   262 
   261 
   263 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
   262 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
   264     '''send email notifications to interested subscribers.
   263     '''send email notifications to interested subscribers.
   265 
   264 
   266     if used as changegroup hook, send one email for all changesets in
   265     if used as changegroup hook, send one email for all changesets in
   267     changegroup. else send one email per changeset.'''
   266     changegroup. else send one email per changeset.'''
       
   267 
   268     n = notifier(ui, repo, hooktype)
   268     n = notifier(ui, repo, hooktype)
       
   269     ctx = repo[node]
       
   270 
   269     if not n.subs:
   271     if not n.subs:
   270         ui.debug(_('notify: no subscribers to repo %s\n') % n.root)
   272         ui.debug(_('notify: no subscribers to repo %s\n') % n.root)
   271         return
   273         return
   272     if n.skipsource(source):
   274     if n.skipsource(source):
   273         ui.debug(_('notify: changes have source "%s" - skipping\n') %
   275         ui.debug(_('notify: changes have source "%s" - skipping\n') % source)
   274                  source)
       
   275         return
   276         return
   276     node = bin(node)
   277 
   277     ui.pushbuffer()
   278     ui.pushbuffer()
   278     if hooktype == 'changegroup':
   279     if hooktype == 'changegroup':
   279         start = repo[node].rev()
   280         start, end = ctx.rev(), len(repo)
   280         end = len(repo)
       
   281         count = end - start
   281         count = end - start
   282         for rev in xrange(start, end):
   282         for rev in xrange(start, end):
   283             n.node(repo[rev].node())
   283             n.node(repo[rev])
   284         n.diff(node, repo.changelog.tip())
   284         n.diff(ctx, repo['tip'])
   285     else:
   285     else:
   286         count = 1
   286         count = 1
   287         n.node(node)
   287         n.node(ctx)
   288         n.diff(node, node)
   288         n.diff(ctx)
       
   289 
   289     data = ui.popbuffer()
   290     data = ui.popbuffer()
   290     n.send(node, count, data)
   291     n.send(ctx, count, data)