Bugzilla 2.18 and on use contrib/sendbugmail.pl, not processmail.
authorJim Hague <jim.hague@acm.org>
Fri, 09 Jan 2009 22:15:08 +0000
changeset 7618 6c89dd0a7797
parent 7617 7b554c6ad390
child 7619 e9da3de01e0a
Bugzilla 2.18 and on use contrib/sendbugmail.pl, not processmail. During 2.17, Bugzilla ditched the old 'processmail' script. With 2.18 contrib/sendbugmail.pl arrived in its place. For notification emails to work properly, sendbugmail.pl requires as its second parameter the Bugzilla user who made the commit. Otherwise the user will not be recognised as the committer, and will receive notification emails about the commit regardless of their preference about being notified on their own commits. This parameter should be given to processmail also, but wasn't for historical reasons. Add new config with the local Bugzilla install directory, and provide defaults for the notify string which should work for most setups. Still permit notify string to be specified, and for backwards compatibility with any extant notify strings try first interpolating notify string with old-style single bug ID argument. Add new 2.18 support version to introduce sendbugmail.pl. In other words, this update should be backwards-compatible with existing installations, but offers simplified setup in most cases. And as a bonus Bugzilla notification emails will be dispatched correctly; notifiers will not receive an email unless configured to do so.
hgext/bugzilla.py
--- a/hgext/bugzilla.py	Fri Jan 09 18:12:53 2009 +0100
+++ b/hgext/bugzilla.py	Fri Jan 09 22:15:08 2009 +0000
@@ -29,14 +29,18 @@
     user       Username to use to access MySQL server. Default 'bugs'.
     password   Password to use to access MySQL server.
     timeout    Database connection timeout (seconds). Default 5.
-    version    Bugzilla version. Specify '3.0' for Bugzilla versions from
-               3.0 onwards, and '2.16' for versions prior to 3.0.
+    version    Bugzilla version. Specify '3.0' for Bugzilla versions 3.0 and
+               later, '2.18' for Bugzilla versions from 2.18 and '2.16' for
+               versions prior to 2.18.
     bzuser     Fallback Bugzilla user name to record comments with, if
                changeset committer cannot be found as a Bugzilla user.
+    bzdir      Bugzilla install directory. Used by default notify.
+               Default '/var/www/html/bugzilla'.
     notify     The command to run to get Bugzilla to send bug change
-               notification emails. Substitutes one string parameter,
-               the bug ID. Default 'cd /var/www/html/bugzilla && '
-                                   './processmail %s nobody@nowhere.com'.
+               notification emails. Substitutes from a map with 3 keys,
+               'bzdir', 'id' (bug id) and 'user' (committer bugzilla email).
+               Default depends on version; from 2.18 it is
+               "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s".
     regexp     Regular expression to match bug IDs in changeset commit message.
                Must contain one "()" group. The default expression matches
                'Bug 1234', 'Bug no. 1234', 'Bug number 1234',
@@ -88,7 +92,7 @@
     password=XYZZY
     version=3.0
     bzuser=unknown@domain.com
-    notify=cd /opt/bugzilla-3.2 && perl -T contrib/sendbugmail.pl %%s bugmail@domain.com
+    bzdir=/opt/bugzilla-3.2
     template=Changeset {node|short} in {root|basename}.\\n{hgweb}/{webroot}/rev/{node|short}\\n\\n{desc}\\n
     strip=5
 
@@ -136,6 +140,7 @@
         self.cursor = self.conn.cursor()
         self.longdesc_id = self.get_longdesc_id()
         self.user_ids = {}
+        self.default_notify = "cd %(bzdir)s && ./processmail %(id)s %(user)s"
 
     def run(self, *args, **kwargs):
         '''run a query.'''
@@ -172,15 +177,23 @@
             unknown.pop(id, None)
         return util.sort(unknown.keys())
 
-    def notify(self, ids):
+    def notify(self, ids, committer):
         '''tell bugzilla to send mail.'''
 
         self.ui.status(_('telling bugzilla to send mail:\n'))
+        (user, userid) = self.get_bugzilla_user(committer)
         for id in ids:
             self.ui.status(_('  bug %s\n') % id)
-            cmd = self.ui.config('bugzilla', 'notify',
-                               'cd /var/www/html/bugzilla && '
-                               './processmail %s nobody@nowhere.com') % id
+            cmdfmt = self.ui.config('bugzilla', 'notify', self.default_notify)
+            bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
+            try:
+                # Backwards-compatible with old notify string, which
+                # took one string. This will throw with a new format
+                # string.
+                cmd = cmdfmt % id
+            except TypeError:
+                cmd = cmdfmt % {'bzdir': bzdir, 'id': id, 'user': user}
+            self.ui.note(_('running notify command %s\n') % cmd)
             fp = util.popen('(%s) 2>&1' % cmd)
             out = fp.read()
             ret = fp.close()
@@ -215,9 +228,10 @@
                 return bzuser
         return user
 
-    def add_comment(self, bugid, text, committer):
-        '''add comment to bug. try adding comment as committer of
-        changeset, otherwise as default bugzilla user.'''
+    def get_bugzilla_user(self, committer):
+        '''see if committer is a registered bugzilla user. Return
+        bugzilla username and userid if so. If not, return default
+        bugzilla username and userid.'''
         user = self.map_committer(committer)
         try:
             userid = self.get_user_id(user)
@@ -228,9 +242,16 @@
                     raise util.Abort(_('cannot find bugzilla user id for %s') %
                                      user)
                 userid = self.get_user_id(defaultuser)
+                user = defaultuser
             except KeyError:
                 raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
                                  (user, defaultuser))
+        return (user, userid)
+
+    def add_comment(self, bugid, text, committer):
+        '''add comment to bug. try adding comment as committer of
+        changeset, otherwise as default bugzilla user.'''
+        (user, userid) = self.get_bugzilla_user(committer)
         now = time.strftime('%Y-%m-%d %H:%M:%S')
         self.run('''insert into longdescs
                     (bug_id, who, bug_when, thetext)
@@ -241,11 +262,18 @@
                  (bugid, userid, now, self.longdesc_id))
         self.conn.commit()
 
-class bugzilla_3_0(bugzilla_2_16):
+class bugzilla_2_18(bugzilla_2_16):
+    '''support for bugzilla 2.18 series.'''
+
+    def __init__(self, ui):
+        bugzilla_2_16.__init__(self, ui)
+        self.default_notify = "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s"
+
+class bugzilla_3_0(bugzilla_2_18):
     '''support for bugzilla 3.0 series.'''
 
     def __init__(self, ui):
-        bugzilla_2_16.__init__(self, ui)
+        bugzilla_2_18.__init__(self, ui)
 
     def get_longdesc_id(self):
         '''get identity of longdesc field'''
@@ -260,6 +288,7 @@
     # different schemas.
     _versions = {
         '2.16': bugzilla_2_16,
+        '2.18': bugzilla_2_18,
         '3.0':  bugzilla_3_0
         }
 
@@ -375,7 +404,7 @@
         if ids:
             for id in ids:
                 bz.update(id, ctx)
-            bz.notify(ids)
+            bz.notify(ids, util.email(ctx.user()))
     except MySQLdb.MySQLError, err:
         raise util.Abort(_('database error: %s') % err[1])