220 return getattr(self.bz(), key) |
220 return getattr(self.bz(), key) |
221 |
221 |
222 _bug_re = None |
222 _bug_re = None |
223 _split_re = None |
223 _split_re = None |
224 |
224 |
225 def find_bug_ids(self, node, desc): |
225 def find_bug_ids(self, ctx): |
226 '''find valid bug ids that are referred to in changeset |
226 '''find valid bug ids that are referred to in changeset |
227 comments and that do not already have references to this |
227 comments and that do not already have references to this |
228 changeset.''' |
228 changeset.''' |
229 |
229 |
230 if bugzilla._bug_re is None: |
230 if bugzilla._bug_re is None: |
233 re.IGNORECASE) |
233 re.IGNORECASE) |
234 bugzilla._split_re = re.compile(r'\D+') |
234 bugzilla._split_re = re.compile(r'\D+') |
235 start = 0 |
235 start = 0 |
236 ids = {} |
236 ids = {} |
237 while True: |
237 while True: |
238 m = bugzilla._bug_re.search(desc, start) |
238 m = bugzilla._bug_re.search(ctx.description(), start) |
239 if not m: |
239 if not m: |
240 break |
240 break |
241 start = m.end() |
241 start = m.end() |
242 for id in bugzilla._split_re.split(m.group(1)): |
242 for id in bugzilla._split_re.split(m.group(1)): |
243 if not id: continue |
243 if not id: continue |
244 ids[int(id)] = 1 |
244 ids[int(id)] = 1 |
245 ids = ids.keys() |
245 ids = ids.keys() |
246 if ids: |
246 if ids: |
247 ids = self.filter_real_bug_ids(ids) |
247 ids = self.filter_real_bug_ids(ids) |
248 if ids: |
248 if ids: |
249 ids = self.filter_unknown_bug_ids(node, ids) |
249 ids = self.filter_unknown_bug_ids(ctx.node(), ids) |
250 return ids |
250 return ids |
251 |
251 |
252 def update(self, bugid, node, changes): |
252 def update(self, bugid, ctx): |
253 '''update bugzilla bug with reference to changeset.''' |
253 '''update bugzilla bug with reference to changeset.''' |
254 |
254 |
255 def webroot(root): |
255 def webroot(root): |
256 '''strip leading prefix of repo root and turn into |
256 '''strip leading prefix of repo root and turn into |
257 url-safe path.''' |
257 url-safe path.''' |
274 'to bug {bug}.\ndetails:\n\t{desc|tabindent}') |
274 'to bug {bug}.\ndetails:\n\t{desc|tabindent}') |
275 if tmpl: |
275 if tmpl: |
276 tmpl = templater.parsestring(tmpl, quoted=False) |
276 tmpl = templater.parsestring(tmpl, quoted=False) |
277 t.use_template(tmpl) |
277 t.use_template(tmpl) |
278 self.ui.pushbuffer() |
278 self.ui.pushbuffer() |
279 t.show(changenode=node, changes=changes, |
279 t.show(changenode=ctx.node(), changes=ctx.changeset(), |
280 bug=str(bugid), |
280 bug=str(bugid), |
281 hgweb=self.ui.config('web', 'baseurl'), |
281 hgweb=self.ui.config('web', 'baseurl'), |
282 root=self.repo.root, |
282 root=self.repo.root, |
283 webroot=webroot(self.repo.root)) |
283 webroot=webroot(self.repo.root)) |
284 data = self.ui.popbuffer() |
284 data = self.ui.popbuffer() |
285 self.add_comment(bugid, data, templater.email(changes[1])) |
285 self.add_comment(bugid, data, templater.email(ctx.user())) |
286 |
286 |
287 def hook(ui, repo, hooktype, node=None, **kwargs): |
287 def hook(ui, repo, hooktype, node=None, **kwargs): |
288 '''add comment to bugzilla for each changeset that refers to a |
288 '''add comment to bugzilla for each changeset that refers to a |
289 bugzilla bug id. only add a comment once per bug, so same change |
289 bugzilla bug id. only add a comment once per bug, so same change |
290 seen multiple times does not fill bug with duplicate data.''' |
290 seen multiple times does not fill bug with duplicate data.''' |
298 if node is None: |
298 if node is None: |
299 raise util.Abort(_('hook type %s does not pass a changeset id') % |
299 raise util.Abort(_('hook type %s does not pass a changeset id') % |
300 hooktype) |
300 hooktype) |
301 try: |
301 try: |
302 bz = bugzilla(ui, repo) |
302 bz = bugzilla(ui, repo) |
303 bin_node = bin(node) |
303 ctx = repo.changctx(node) |
304 changes = repo.changelog.read(bin_node) |
304 ids = bz.find_bug_ids(ctx) |
305 ids = bz.find_bug_ids(bin_node, changes[4]) |
|
306 if ids: |
305 if ids: |
307 for id in ids: |
306 for id in ids: |
308 bz.update(id, bin_node, changes) |
307 bz.update(id, ctx) |
309 bz.notify(ids) |
308 bz.notify(ids) |
310 except MySQLdb.MySQLError, err: |
309 except MySQLdb.MySQLError, err: |
311 raise util.Abort(_('database error: %s') % err[1]) |
310 raise util.Abort(_('database error: %s') % err[1]) |
312 |
311 |