##// END OF EJS Templates
bugzilla: localise all MySQL direct access inside access class....
Jim Hague -
r13800:c2ef8159 default
parent child Browse files
Show More
@@ -145,28 +145,77 b' from mercurial.node import short'
145 145 from mercurial import cmdutil, templater, util
146 146 import re, time
147 147
148 MySQLdb = None
149
150 def buglist(ids):
151 return '(' + ','.join(map(str, ids)) + ')'
152
153 class bugzilla_2_16(object):
154 '''support for bugzilla version 2.16.'''
148 class bzaccess(object):
149 '''Base class for access to Bugzilla.'''
155 150
156 151 def __init__(self, ui):
157 152 self.ui = ui
153 usermap = self.ui.config('bugzilla', 'usermap')
154 if usermap:
155 self.ui.readconfig(usermap, sections=['usermap'])
156
157 def map_committer(self, user):
158 '''map name of committer to Bugzilla user name.'''
159 for committer, bzuser in self.ui.configitems('usermap'):
160 if committer.lower() == user.lower():
161 return bzuser
162 return user
163
164 # Methods to be implemented by access classes.
165 def filter_real_bug_ids(self, ids):
166 '''remove bug IDs that do not exist in Bugzilla from set.'''
167 pass
168
169 def filter_cset_known_bug_ids(self, node, ids):
170 '''remove bug IDs where node occurs in comment text from set.'''
171 pass
172
173 def add_comment(self, bugid, text, committer):
174 '''add comment to bug.
175
176 If possible add the comment as being from the committer of
177 the changeset. Otherwise use the default Bugzilla user.
178 '''
179 pass
180
181 def notify(self, ids, committer):
182 '''Force sending of Bugzilla notification emails.'''
183 pass
184
185 # Bugzilla via direct access to MySQL database.
186 class bzmysql(bzaccess):
187 '''Support for direct MySQL access to Bugzilla.
188
189 The earliest Bugzilla version this is tested with is version 2.16.
190 '''
191
192 @staticmethod
193 def sql_buglist(ids):
194 '''return SQL-friendly list of bug ids'''
195 return '(' + ','.join(map(str, ids)) + ')'
196
197 _MySQLdb = None
198
199 def __init__(self, ui):
200 try:
201 import MySQLdb as mysql
202 bzmysql._MySQLdb = mysql
203 except ImportError, err:
204 raise util.Abort(_('python mysql support not available: %s') % err)
205
206 bzaccess.__init__(self, ui)
207
158 208 host = self.ui.config('bugzilla', 'host', 'localhost')
159 209 user = self.ui.config('bugzilla', 'user', 'bugs')
160 210 passwd = self.ui.config('bugzilla', 'password')
161 211 db = self.ui.config('bugzilla', 'db', 'bugs')
162 212 timeout = int(self.ui.config('bugzilla', 'timeout', 5))
163 usermap = self.ui.config('bugzilla', 'usermap')
164 if usermap:
165 self.ui.readconfig(usermap, sections=['usermap'])
166 213 self.ui.note(_('connecting to %s:%s as %s, password %s\n') %
167 214 (host, db, user, '*' * len(passwd)))
168 self.conn = MySQLdb.connect(host=host, user=user, passwd=passwd,
169 db=db, connect_timeout=timeout)
215 self.conn = bzmysql._MySQLdb.connect(host=host,
216 user=user, passwd=passwd,
217 db=db,
218 connect_timeout=timeout)
170 219 self.cursor = self.conn.cursor()
171 220 self.longdesc_id = self.get_longdesc_id()
172 221 self.user_ids = {}
@@ -177,7 +226,7 b' class bugzilla_2_16(object):'
177 226 self.ui.note(_('query: %s %s\n') % (args, kwargs))
178 227 try:
179 228 self.cursor.execute(*args, **kwargs)
180 except MySQLdb.MySQLError:
229 except bzmysql._MySQLdb.MySQLError:
181 230 self.ui.note(_('failed query: %s %s\n') % (args, kwargs))
182 231 raise
183 232
@@ -191,7 +240,8 b' class bugzilla_2_16(object):'
191 240
192 241 def filter_real_bug_ids(self, ids):
193 242 '''filter not-existing bug ids from set.'''
194 self.run('select bug_id from bugs where bug_id in %s' % buglist(ids))
243 self.run('select bug_id from bugs where bug_id in %s' %
244 bzmysql.sql_buglist(ids))
195 245 return set([c[0] for c in self.cursor.fetchall()])
196 246
197 247 def filter_cset_known_bug_ids(self, node, ids):
@@ -199,7 +249,7 b' class bugzilla_2_16(object):'
199 249
200 250 self.run('''select bug_id from longdescs where
201 251 bug_id in %s and thetext like "%%%s%%"''' %
202 (buglist(ids), short(node)))
252 (bzmysql.sql_buglist(ids), short(node)))
203 253 for (id,) in self.cursor.fetchall():
204 254 self.ui.status(_('bug %d already knows about changeset %s\n') %
205 255 (id, short(node)))
@@ -250,13 +300,6 b' class bugzilla_2_16(object):'
250 300 self.user_ids[user] = userid
251 301 return userid
252 302
253 def map_committer(self, user):
254 '''map name of committer to bugzilla user name.'''
255 for committer, bzuser in self.ui.configitems('usermap'):
256 if committer.lower() == user.lower():
257 return bzuser
258 return user
259
260 303 def get_bugzilla_user(self, committer):
261 304 '''see if committer is a registered bugzilla user. Return
262 305 bugzilla username and userid if so. If not, return default
@@ -291,19 +334,19 b' class bugzilla_2_16(object):'
291 334 (bugid, userid, now, self.longdesc_id))
292 335 self.conn.commit()
293 336
294 class bugzilla_2_18(bugzilla_2_16):
337 class bzmysql_2_18(bzmysql):
295 338 '''support for bugzilla 2.18 series.'''
296 339
297 340 def __init__(self, ui):
298 bugzilla_2_16.__init__(self, ui)
341 bzmysql.__init__(self, ui)
299 342 self.default_notify = \
300 343 "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s"
301 344
302 class bugzilla_3_0(bugzilla_2_18):
345 class bzmysql_3_0(bzmysql_2_18):
303 346 '''support for bugzilla 3.0 series.'''
304 347
305 348 def __init__(self, ui):
306 bugzilla_2_18.__init__(self, ui)
349 bzmysql_2_18.__init__(self, ui)
307 350
308 351 def get_longdesc_id(self):
309 352 '''get identity of longdesc field'''
@@ -317,9 +360,9 b' class bugzilla(object):'
317 360 # supported versions of bugzilla. different versions have
318 361 # different schemas.
319 362 _versions = {
320 '2.16': bugzilla_2_16,
321 '2.18': bugzilla_2_18,
322 '3.0': bugzilla_3_0
363 '2.16': bzmysql,
364 '2.18': bzmysql_2_18,
365 '3.0': bzmysql_3_0
323 366 }
324 367
325 368 _default_bug_re = (r'bugs?\s*,?\s*(?:#|nos?\.?|num(?:ber)?s?)?\s*'
@@ -419,13 +462,6 b' def hook(ui, repo, hooktype, node=None, '
419 462 '''add comment to bugzilla for each changeset that refers to a
420 463 bugzilla bug id. only add a comment once per bug, so same change
421 464 seen multiple times does not fill bug with duplicate data.'''
422 try:
423 import MySQLdb as mysql
424 global MySQLdb
425 MySQLdb = mysql
426 except ImportError, err:
427 raise util.Abort(_('python mysql support not available: %s') % err)
428
429 465 if node is None:
430 466 raise util.Abort(_('hook type %s does not pass a changeset id') %
431 467 hooktype)
@@ -437,6 +473,6 b' def hook(ui, repo, hooktype, node=None, '
437 473 for id in ids:
438 474 bz.update(id, ctx)
439 475 bz.notify(ids, util.email(ctx.user()))
440 except MySQLdb.MySQLError, err:
441 raise util.Abort(_('database error: %s') % err.args[1])
476 except Exception, e:
477 raise util.Abort(_('Bugzilla error: %s') % e)
442 478
General Comments 0
You need to be logged in to leave comments. Login now