27 host Hostname of the MySQL server holding the Bugzilla database. |
27 host Hostname of the MySQL server holding the Bugzilla database. |
28 db Name of the Bugzilla database in MySQL. Default 'bugs'. |
28 db Name of the Bugzilla database in MySQL. Default 'bugs'. |
29 user Username to use to access MySQL server. Default 'bugs'. |
29 user Username to use to access MySQL server. Default 'bugs'. |
30 password Password to use to access MySQL server. |
30 password Password to use to access MySQL server. |
31 timeout Database connection timeout (seconds). Default 5. |
31 timeout Database connection timeout (seconds). Default 5. |
32 version Bugzilla version. Specify '3.0' for Bugzilla versions from |
32 version Bugzilla version. Specify '3.0' for Bugzilla versions 3.0 and |
33 3.0 onwards, and '2.16' for versions prior to 3.0. |
33 later, '2.18' for Bugzilla versions from 2.18 and '2.16' for |
|
34 versions prior to 2.18. |
34 bzuser Fallback Bugzilla user name to record comments with, if |
35 bzuser Fallback Bugzilla user name to record comments with, if |
35 changeset committer cannot be found as a Bugzilla user. |
36 changeset committer cannot be found as a Bugzilla user. |
|
37 bzdir Bugzilla install directory. Used by default notify. |
|
38 Default '/var/www/html/bugzilla'. |
36 notify The command to run to get Bugzilla to send bug change |
39 notify The command to run to get Bugzilla to send bug change |
37 notification emails. Substitutes one string parameter, |
40 notification emails. Substitutes from a map with 3 keys, |
38 the bug ID. Default 'cd /var/www/html/bugzilla && ' |
41 'bzdir', 'id' (bug id) and 'user' (committer bugzilla email). |
39 './processmail %s nobody@nowhere.com'. |
42 Default depends on version; from 2.18 it is |
|
43 "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s". |
40 regexp Regular expression to match bug IDs in changeset commit message. |
44 regexp Regular expression to match bug IDs in changeset commit message. |
41 Must contain one "()" group. The default expression matches |
45 Must contain one "()" group. The default expression matches |
42 'Bug 1234', 'Bug no. 1234', 'Bug number 1234', |
46 'Bug 1234', 'Bug no. 1234', 'Bug number 1234', |
43 'Bugs 1234,5678', 'Bug 1234 and 5678' and variations thereof. |
47 'Bugs 1234,5678', 'Bug 1234 and 5678' and variations thereof. |
44 Matching is case insensitive. |
48 Matching is case insensitive. |
134 self.conn = MySQLdb.connect(host=host, user=user, passwd=passwd, |
138 self.conn = MySQLdb.connect(host=host, user=user, passwd=passwd, |
135 db=db, connect_timeout=timeout) |
139 db=db, connect_timeout=timeout) |
136 self.cursor = self.conn.cursor() |
140 self.cursor = self.conn.cursor() |
137 self.longdesc_id = self.get_longdesc_id() |
141 self.longdesc_id = self.get_longdesc_id() |
138 self.user_ids = {} |
142 self.user_ids = {} |
|
143 self.default_notify = "cd %(bzdir)s && ./processmail %(id)s %(user)s" |
139 |
144 |
140 def run(self, *args, **kwargs): |
145 def run(self, *args, **kwargs): |
141 '''run a query.''' |
146 '''run a query.''' |
142 self.ui.note(_('query: %s %s\n') % (args, kwargs)) |
147 self.ui.note(_('query: %s %s\n') % (args, kwargs)) |
143 try: |
148 try: |
170 self.ui.status(_('bug %d already knows about changeset %s\n') % |
175 self.ui.status(_('bug %d already knows about changeset %s\n') % |
171 (id, short(node))) |
176 (id, short(node))) |
172 unknown.pop(id, None) |
177 unknown.pop(id, None) |
173 return util.sort(unknown.keys()) |
178 return util.sort(unknown.keys()) |
174 |
179 |
175 def notify(self, ids): |
180 def notify(self, ids, committer): |
176 '''tell bugzilla to send mail.''' |
181 '''tell bugzilla to send mail.''' |
177 |
182 |
178 self.ui.status(_('telling bugzilla to send mail:\n')) |
183 self.ui.status(_('telling bugzilla to send mail:\n')) |
|
184 (user, userid) = self.get_bugzilla_user(committer) |
179 for id in ids: |
185 for id in ids: |
180 self.ui.status(_(' bug %s\n') % id) |
186 self.ui.status(_(' bug %s\n') % id) |
181 cmd = self.ui.config('bugzilla', 'notify', |
187 cmdfmt = self.ui.config('bugzilla', 'notify', self.default_notify) |
182 'cd /var/www/html/bugzilla && ' |
188 bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla') |
183 './processmail %s nobody@nowhere.com') % id |
189 try: |
|
190 # Backwards-compatible with old notify string, which |
|
191 # took one string. This will throw with a new format |
|
192 # string. |
|
193 cmd = cmdfmt % id |
|
194 except TypeError: |
|
195 cmd = cmdfmt % {'bzdir': bzdir, 'id': id, 'user': user} |
|
196 self.ui.note(_('running notify command %s\n') % cmd) |
184 fp = util.popen('(%s) 2>&1' % cmd) |
197 fp = util.popen('(%s) 2>&1' % cmd) |
185 out = fp.read() |
198 out = fp.read() |
186 ret = fp.close() |
199 ret = fp.close() |
187 if ret: |
200 if ret: |
188 self.ui.warn(out) |
201 self.ui.warn(out) |
213 for committer, bzuser in self.ui.configitems('usermap'): |
226 for committer, bzuser in self.ui.configitems('usermap'): |
214 if committer.lower() == user.lower(): |
227 if committer.lower() == user.lower(): |
215 return bzuser |
228 return bzuser |
216 return user |
229 return user |
217 |
230 |
218 def add_comment(self, bugid, text, committer): |
231 def get_bugzilla_user(self, committer): |
219 '''add comment to bug. try adding comment as committer of |
232 '''see if committer is a registered bugzilla user. Return |
220 changeset, otherwise as default bugzilla user.''' |
233 bugzilla username and userid if so. If not, return default |
|
234 bugzilla username and userid.''' |
221 user = self.map_committer(committer) |
235 user = self.map_committer(committer) |
222 try: |
236 try: |
223 userid = self.get_user_id(user) |
237 userid = self.get_user_id(user) |
224 except KeyError: |
238 except KeyError: |
225 try: |
239 try: |
226 defaultuser = self.ui.config('bugzilla', 'bzuser') |
240 defaultuser = self.ui.config('bugzilla', 'bzuser') |
227 if not defaultuser: |
241 if not defaultuser: |
228 raise util.Abort(_('cannot find bugzilla user id for %s') % |
242 raise util.Abort(_('cannot find bugzilla user id for %s') % |
229 user) |
243 user) |
230 userid = self.get_user_id(defaultuser) |
244 userid = self.get_user_id(defaultuser) |
|
245 user = defaultuser |
231 except KeyError: |
246 except KeyError: |
232 raise util.Abort(_('cannot find bugzilla user id for %s or %s') % |
247 raise util.Abort(_('cannot find bugzilla user id for %s or %s') % |
233 (user, defaultuser)) |
248 (user, defaultuser)) |
|
249 return (user, userid) |
|
250 |
|
251 def add_comment(self, bugid, text, committer): |
|
252 '''add comment to bug. try adding comment as committer of |
|
253 changeset, otherwise as default bugzilla user.''' |
|
254 (user, userid) = self.get_bugzilla_user(committer) |
234 now = time.strftime('%Y-%m-%d %H:%M:%S') |
255 now = time.strftime('%Y-%m-%d %H:%M:%S') |
235 self.run('''insert into longdescs |
256 self.run('''insert into longdescs |
236 (bug_id, who, bug_when, thetext) |
257 (bug_id, who, bug_when, thetext) |
237 values (%s, %s, %s, %s)''', |
258 values (%s, %s, %s, %s)''', |
238 (bugid, userid, now, text)) |
259 (bugid, userid, now, text)) |
239 self.run('''insert into bugs_activity (bug_id, who, bug_when, fieldid) |
260 self.run('''insert into bugs_activity (bug_id, who, bug_when, fieldid) |
240 values (%s, %s, %s, %s)''', |
261 values (%s, %s, %s, %s)''', |
241 (bugid, userid, now, self.longdesc_id)) |
262 (bugid, userid, now, self.longdesc_id)) |
242 self.conn.commit() |
263 self.conn.commit() |
243 |
264 |
244 class bugzilla_3_0(bugzilla_2_16): |
265 class bugzilla_2_18(bugzilla_2_16): |
245 '''support for bugzilla 3.0 series.''' |
266 '''support for bugzilla 2.18 series.''' |
246 |
267 |
247 def __init__(self, ui): |
268 def __init__(self, ui): |
248 bugzilla_2_16.__init__(self, ui) |
269 bugzilla_2_16.__init__(self, ui) |
|
270 self.default_notify = "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s" |
|
271 |
|
272 class bugzilla_3_0(bugzilla_2_18): |
|
273 '''support for bugzilla 3.0 series.''' |
|
274 |
|
275 def __init__(self, ui): |
|
276 bugzilla_2_18.__init__(self, ui) |
249 |
277 |
250 def get_longdesc_id(self): |
278 def get_longdesc_id(self): |
251 '''get identity of longdesc field''' |
279 '''get identity of longdesc field''' |
252 self.run('select id from fielddefs where name = "longdesc"') |
280 self.run('select id from fielddefs where name = "longdesc"') |
253 ids = self.cursor.fetchall() |
281 ids = self.cursor.fetchall() |