##// END OF EJS Templates
bugzilla: extract optional hours from commit message and update bug time...
Jim Hague -
r16222:d7b7b453 default
parent child Browse files
Show More
@@ -12,7 +12,8 b' This hook extension adds comments on bug'
12 that refer to bugs by Bugzilla ID are seen. The comment is formatted using
12 that refer to bugs by Bugzilla ID are seen. The comment is formatted using
13 the Mercurial template mechanism.
13 the Mercurial template mechanism.
14
14
15 The hook does not change bug status.
15 The bug references can optionally include an update for Bugzilla of the
16 hours spent working on the bug.
16
17
17 Three basic modes of access to Bugzilla are provided:
18 Three basic modes of access to Bugzilla are provided:
18
19
@@ -32,7 +33,7 b' permission to read Bugzilla configuratio'
32 MySQL user and password to have full access rights to the Bugzilla
33 MySQL user and password to have full access rights to the Bugzilla
33 database. For these reasons this access mode is now considered
34 database. For these reasons this access mode is now considered
34 deprecated, and will not be updated for new Bugzilla versions going
35 deprecated, and will not be updated for new Bugzilla versions going
35 forward.
36 forward. Only adding comments is supported in this access mode.
36
37
37 Access via XMLRPC needs a Bugzilla username and password to be specified
38 Access via XMLRPC needs a Bugzilla username and password to be specified
38 in the configuration. Comments are added under that username. Since the
39 in the configuration. Comments are added under that username. Since the
@@ -63,10 +64,15 b' bugzilla.version'
63
64
64 bugzilla.regexp
65 bugzilla.regexp
65 Regular expression to match bug IDs in changeset commit message.
66 Regular expression to match bug IDs in changeset commit message.
66 Must contain one "()" group. The default expression matches ``Bug
67 It must contain one "()" named group ``<ids>`` containing the bug
67 1234``, ``Bug no. 1234``, ``Bug number 1234``, ``Bugs 1234,5678``,
68 IDs separated by non-digit characters. It may also contain
68 ``Bug 1234 and 5678`` and variations thereof. Matching is case
69 a named group ``<hours>`` with a floating-point number giving the
69 insensitive.
70 hours worked on the bug. If no named groups are present, the first
71 "()" group is assumed to contain the bug IDs, and work time is not
72 updated. The default expression matches ``Bug 1234``, ``Bug no. 1234``,
73 ``Bug number 1234``, ``Bugs 1234,5678``, ``Bug 1234 and 5678`` and
74 variations thereof, followed by an hours number prefixed by ``h`` or
75 ``hours``, e.g. ``hours 1.5``. Matching is case insensitive.
70
76
71 bugzilla.style
77 bugzilla.style
72 The style file to use when formatting comments.
78 The style file to use when formatting comments.
@@ -276,8 +282,10 b' class bzaccess(object):'
276 # Methods to be implemented by access classes.
282 # Methods to be implemented by access classes.
277 #
283 #
278 # 'bugs' is a dict keyed on bug id, where values are a dict holding
284 # 'bugs' is a dict keyed on bug id, where values are a dict holding
279 # updates to bug state. Currently no states are recognised, but this
285 # updates to bug state. Recognised dict keys are:
280 # will change soon.
286 #
287 # 'hours': Value, float containing work hours to be updated.
288
281 def filter_real_bug_ids(self, bugs):
289 def filter_real_bug_ids(self, bugs):
282 '''remove bug IDs that do not exist in Bugzilla from bugs.'''
290 '''remove bug IDs that do not exist in Bugzilla from bugs.'''
283 pass
291 pass
@@ -449,6 +457,9 b' class bzmysql(bzaccess):'
449
457
450 Try adding comment as committer of changeset, otherwise as
458 Try adding comment as committer of changeset, otherwise as
451 default bugzilla user.'''
459 default bugzilla user.'''
460 if len(newstate) > 0:
461 self.ui.warn(_("Bugzilla/MySQL cannot update bug state\n"))
462
452 (user, userid) = self.get_bugzilla_user(committer)
463 (user, userid) = self.get_bugzilla_user(committer)
453 now = time.strftime('%Y-%m-%d %H:%M:%S')
464 now = time.strftime('%Y-%m-%d %H:%M:%S')
454 self.run('''insert into longdescs
465 self.run('''insert into longdescs
@@ -608,6 +619,8 b' class bzxmlrpc(bzaccess):'
608
619
609 def updatebug(self, bugid, newstate, text, committer):
620 def updatebug(self, bugid, newstate, text, committer):
610 args = dict(id=bugid, comment=text)
621 args = dict(id=bugid, comment=text)
622 if 'hours' in newstate:
623 args['work_time'] = newstate['hours']
611 self.bzproxy.Bug.add_comment(args)
624 self.bzproxy.Bug.add_comment(args)
612
625
613 class bzxmlrpcemail(bzxmlrpc):
626 class bzxmlrpcemail(bzxmlrpc):
@@ -615,8 +628,11 b' class bzxmlrpcemail(bzxmlrpc):'
615
628
616 Advantages of sending updates via email:
629 Advantages of sending updates via email:
617 1. Comments can be added as any user, not just logged in user.
630 1. Comments can be added as any user, not just logged in user.
618 2. Bug statuses and other fields not accessible via XMLRPC can
631 2. Bug statuses or other fields not accessible via XMLRPC can
619 be updated. This is not currently used.
632 potentially be updated.
633
634 Currently all status updates recognised can be done via XMLRPC, so
635 item 1 is the only actual advantage.
620 """
636 """
621
637
622 def __init__(self, ui):
638 def __init__(self, ui):
@@ -661,7 +677,10 b' class bzxmlrpcemail(bzxmlrpc):'
661 sendmail(user, bzemail, msg.as_string())
677 sendmail(user, bzemail, msg.as_string())
662
678
663 def updatebug(self, bugid, newstate, text, committer):
679 def updatebug(self, bugid, newstate, text, committer):
664 self.send_bug_modify_email(bugid, [], text, committer)
680 cmds = []
681 if 'hours' in newstate:
682 cmds.append(self.makecommandline("work_time", newstate['hours']))
683 self.send_bug_modify_email(bugid, cmds, text, committer)
665
684
666 class bugzilla(object):
685 class bugzilla(object):
667 # supported versions of bugzilla. different versions have
686 # supported versions of bugzilla. different versions have
@@ -675,7 +694,8 b' class bugzilla(object):'
675 }
694 }
676
695
677 _default_bug_re = (r'bugs?\s*,?\s*(?:#|nos?\.?|num(?:ber)?s?)?\s*'
696 _default_bug_re = (r'bugs?\s*,?\s*(?:#|nos?\.?|num(?:ber)?s?)?\s*'
678 r'((?:\d+\s*(?:,?\s*(?:and)?)?\s*)+)')
697 r'(?P<ids>(?:\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
698 r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
679
699
680 _bz = None
700 _bz = None
681
701
@@ -716,16 +736,32 b' class bugzilla(object):'
716 re.IGNORECASE)
736 re.IGNORECASE)
717 bugzilla._split_re = re.compile(r'\D+')
737 bugzilla._split_re = re.compile(r'\D+')
718 start = 0
738 start = 0
739 hours = 0.0
719 bugs = {}
740 bugs = {}
720 while True:
741 while True:
742 bugattribs = {}
721 m = bugzilla._bug_re.search(ctx.description(), start)
743 m = bugzilla._bug_re.search(ctx.description(), start)
722 if not m:
744 if not m:
723 break
745 break
724 start = m.end()
746 start = m.end()
725 for id in bugzilla._split_re.split(m.group(1)):
747 try:
748 ids = m.group('ids')
749 except IndexError:
750 ids = m.group(1)
751 try:
752 hours = float(m.group('hours'))
753 bugattribs['hours'] = hours
754 except IndexError:
755 pass
756 except TypeError:
757 pass
758 except ValueError:
759 self.ui.status(_("%s: invalid hours\n") % m.group('hours'))
760
761 for id in bugzilla._split_re.split(ids):
726 if not id:
762 if not id:
727 continue
763 continue
728 bugs[int(id)] = {}
764 bugs[int(id)] = bugattribs
729 if bugs:
765 if bugs:
730 self.filter_real_bug_ids(bugs)
766 self.filter_real_bug_ids(bugs)
731 if bugs:
767 if bugs:
General Comments 0
You need to be logged in to leave comments. Login now