--- a/hgext/bugzilla.py Wed Mar 30 09:49:45 2011 +0100
+++ b/hgext/bugzilla.py Wed Mar 30 09:49:45 2011 +0100
@@ -14,9 +14,12 @@
The hook does not change bug status.
-Two basic modes of access to Bugzilla are provided:
+Three basic modes of access to Bugzilla are provided:
-1. Access via the Bugzilla XMLRPC interface (requires Bugzilla 3.4 or later).
+1. Access via the Bugzilla XMLRPC interface. Requires Bugzilla 3.4 or later.
+
+2. Check data via the Bugzilla XMLRPC interface and submit bug change
+ via email to Bugzilla email interface. Requires Bugzilla 3.4 or later.
2. Writing directly to the Bugzilla database. Only Bugzilla installations
using MySQL are supported. Requires Python MySQLdb.
@@ -37,15 +40,24 @@
that the rights of that user are restricted in Bugzilla to the minimum
necessary to add comments.
-Configuration items common to both access modes:
+Access via XMLRPC/email behaves uses XMLRPC to query Bugzilla, but sends
+email to the Bugzilla email interface to submit comments to bugs.
+The From: address in the email is set to the email address of the Mercurial
+user, so the comment appears to come from the Mercurial user. In the event
+that the Mercurial user email is not recognised by Bugzilla as a Bugzilla
+user, the Bugzilla username and password used to log into Bugzilla are
+used instead as the source of the comment.
+
+Configuration items common to all access modes:
[bugzilla]
version
This access type to use. Values recognised are:
- xmlrpc Bugzilla XMLRPC interface.
- 3.0 MySQL access, Bugzilla 3.0 and later.
- 2.18 MySQL access, Bugzilla 2.18 and up to but not including 3.0.
- 2.16 MySQL access, Bugzilla 2.16 and up to but not including 2.18.
+ xmlrpc Bugzilla XMLRPC interface.
+ xmlrpc+email Bugzilla XMLRPC and email interfaces.
+ 3.0 MySQL access, Bugzilla 3.0 and later.
+ 2.18 MySQL access, Bugzilla 2.18 and up to but not including 3.0.
+ 2.16 MySQL access, Bugzilla 2.16 and up to but not including 2.18.
regexp
Regular expression to match bug IDs in changeset commit message.
@@ -80,6 +92,18 @@
Base URL for browsing Mercurial repositories. Referenced from
templates as {hgweb}.
+Configuration items common to XMLRPC+email and MySQL access modes:
+
+usermap
+ Path of file containing Mercurial committer email to Bugzilla user email
+ mappings. If specified, the file should contain one mapping per
+ line, "committer"="Bugzilla user". See also the [usermap] section.
+
+[usermap]
+The [usermap] section is used to specify mappings of Mercurial
+committer email to Bugzilla user email. See also [bugzilla].usermap.
+Contains entries of the form "committer"="Bugzilla user".
+
XMLRPC access mode configuration:
[bugzilla]
@@ -93,6 +117,16 @@
password
The password for Bugzilla login.
+XMLRPC+email access mode uses the XMLRPC access mode configuration items,
+and also:
+
+[bugzilla]
+bzemail
+ The Bugzilla email address.
+
+In addition, the Mercurial email settings must be configured. See the
+documentation for 'hgrc', sections '[email]' and '[smtp]'.
+
MySQL access mode configuration:
[bugzilla]
@@ -127,16 +161,6 @@
from 2.18 it is "cd %(bzdir)s && perl -T contrib/sendbugmail.pl
%(id)s %(user)s".
-usermap
- Path of file containing Mercurial committer ID to Bugzilla user ID
- mappings. If specified, the file should contain one mapping per
- line, "committer"="Bugzilla user". See also the [usermap] section.
-
-[usermap]
-The [usermap] section is used to specify mappings of Mercurial
-committer email to Bugzilla user email. See also [bugzilla].usermap.
-Contains entries of the form "committer"="Bugzilla user".
-
Activating the extension::
[extensions]
@@ -162,6 +186,22 @@
[web]
baseurl=http://my-project.org/hg
+XMLRPC+email example configuration. This uses the Bugzilla at
+'http://my-project.org/bugzilla', logging in as user 'bugmail@my-project.org'
+wityh password 'plugh'. It is used with a collection of Mercurial
+repositories in '/var/local/hg/repos/'. Bug comments are sent to the
+Bugzilla email address 'buzilla@my-project.org'. ::
+
+ [bugzilla]
+ user=bugmail@my-project.org
+ password=plugh
+ version=xmlrpc
+ bzemail=bugzilla@my-project.org
+
+ [web]
+ baseurl=https://dev.laicatc.com/hg
+ bugzillaurl=https://dev.laicatc.com/bugzilla
+
MySQL example configuration. This is for a collection of Mercurial
repositories in '/var/local/hg/repos/' used with a local Bugzilla 3.2
installation in /opt/bugzilla-3.2. The MySQL database is on 'localhost',
@@ -185,7 +225,7 @@
[usermap]
user@emaildomain.com=user.name@bugzilladomain.com
-Both the above add a comment to the Bugzilla bug record of the form::
+All the above add a comment to the Bugzilla bug record of the form::
Changeset 3b16791d6642 in repository-name.
http://dev.domain.com/hg/repository-name/rev/3b16791d6642
@@ -195,7 +235,7 @@
from mercurial.i18n import _
from mercurial.node import short
-from mercurial import cmdutil, templater, util
+from mercurial import cmdutil, mail, templater, util
import re, time, xmlrpclib
class bzaccess(object):
@@ -520,6 +560,59 @@
def add_comment(self, bugid, text, committer):
self.bzproxy.Bug.add_comment(dict(id=bugid, comment=text))
+class bzxmlrpcemail(bzxmlrpc):
+ """Read data from Bugzilla via XMLRPC, send updates via email.
+
+ Advantages of sending updates via email:
+ 1. Comments can be added as any user, not just logged in user.
+ 2. Bug statuses and other fields not accessible via XMLRPC can
+ be updated. This is not currently used.
+ """
+
+ def __init__(self, ui):
+ bzxmlrpc.__init__(self, ui)
+
+ self.bzemail = self.ui.config('bugzilla', 'bzemail')
+ if not self.bzemail:
+ raise util.Abort(_("configuration 'bzemail' missing"))
+ mail.validateconfig(self.ui)
+
+ def send_bug_modify_email(self, bugid, commands, comment, committer):
+ '''send modification message to Bugzilla bug via email.
+
+ The message format is documented in the Bugzilla email_in.pl
+ specification. commands is a list of command lines, comment is the
+ comment text.
+
+ To stop users from crafting commit comments with
+ Bugzilla commands, specify the bug ID via the message body, rather
+ than the subject line, and leave a blank line after it.
+ '''
+ user = self.map_committer(committer)
+ matches = self.bzproxy.User.get(dict(match=[user]))
+ if not matches['users']:
+ user = self.ui.config('bugzilla', 'user', 'bugs')
+ matches = self.bzproxy.User.get(dict(match=[user]))
+ if not matches['users']:
+ raise util.Abort(_("default bugzilla user %s email not found") %
+ user)
+ user = matches['users'][0]['email']
+
+ text = "\n".join(commands) + "\n@bug_id = %d\n\n" % bugid + comment
+
+ _charsets = mail._charsets(self.ui)
+ user = mail.addressencode(self.ui, user, _charsets)
+ bzemail = mail.addressencode(self.ui, self.bzemail, _charsets)
+ msg = mail.mimeencode(self.ui, text, _charsets)
+ msg['From'] = user
+ msg['To'] = bzemail
+ msg['Subject'] = mail.headencode(self.ui, "Bug modification", _charsets)
+ sendmail = mail.connect(self.ui)
+ sendmail(user, bzemail, msg.as_string())
+
+ def add_comment(self, bugid, text, committer):
+ self.send_bug_modify_email(bugid, [], text, committer)
+
class bugzilla(object):
# supported versions of bugzilla. different versions have
# different schemas.
@@ -527,7 +620,8 @@
'2.16': bzmysql,
'2.18': bzmysql_2_18,
'3.0': bzmysql_3_0,
- 'xmlrpc': bzxmlrpc
+ 'xmlrpc': bzxmlrpc,
+ 'xmlrpc+email': bzxmlrpcemail
}
_default_bug_re = (r'bugs?\s*,?\s*(?:#|nos?\.?|num(?:ber)?s?)?\s*'