##// END OF EJS Templates
bugzilla: allow change comment to mark bugs fixed...
Jim Hague -
r16223:ac4fd323 default
parent child Browse files
Show More
@@ -13,7 +13,7 b' that refer to bugs by Bugzilla ID are se'
13 the Mercurial template mechanism.
13 the Mercurial template mechanism.
14
14
15 The bug references can optionally include an update for Bugzilla of the
15 The bug references can optionally include an update for Bugzilla of the
16 hours spent working on the bug.
16 hours spent working on the bug. Bugs can also be marked fixed.
17
17
18 Three basic modes of access to Bugzilla are provided:
18 Three basic modes of access to Bugzilla are provided:
19
19
@@ -39,7 +39,7 b' Access via XMLRPC needs a Bugzilla usern'
39 in the configuration. Comments are added under that username. Since the
39 in the configuration. Comments are added under that username. Since the
40 configuration must be readable by all Mercurial users, it is recommended
40 configuration must be readable by all Mercurial users, it is recommended
41 that the rights of that user are restricted in Bugzilla to the minimum
41 that the rights of that user are restricted in Bugzilla to the minimum
42 necessary to add comments.
42 necessary to add comments. Marking bugs fixed requires Bugzilla 4.0 and later.
43
43
44 Access via XMLRPC/email uses XMLRPC to query Bugzilla, but sends
44 Access via XMLRPC/email uses XMLRPC to query Bugzilla, but sends
45 email to the Bugzilla email interface to submit comments to bugs.
45 email to the Bugzilla email interface to submit comments to bugs.
@@ -47,7 +47,8 b' The From: address in the email is set to'
47 user, so the comment appears to come from the Mercurial user. In the event
47 user, so the comment appears to come from the Mercurial user. In the event
48 that the Mercurial user email is not recognised by Bugzilla as a Bugzilla
48 that the Mercurial user email is not recognised by Bugzilla as a Bugzilla
49 user, the email associated with the Bugzilla username used to log into
49 user, the email associated with the Bugzilla username used to log into
50 Bugzilla is used instead as the source of the comment.
50 Bugzilla is used instead as the source of the comment. Marking bugs fixed
51 works on all supported Bugzilla versions.
51
52
52 Configuration items common to all access modes:
53 Configuration items common to all access modes:
53
54
@@ -63,7 +64,7 b' bugzilla.version'
63 including 2.18.
64 including 2.18.
64
65
65 bugzilla.regexp
66 bugzilla.regexp
66 Regular expression to match bug IDs in changeset commit message.
67 Regular expression to match bug IDs for update in changeset commit message.
67 It must contain one "()" named group ``<ids>`` containing the bug
68 It must contain one "()" named group ``<ids>`` containing the bug
68 IDs separated by non-digit characters. It may also contain
69 IDs separated by non-digit characters. It may also contain
69 a named group ``<hours>`` with a floating-point number giving the
70 a named group ``<hours>`` with a floating-point number giving the
@@ -74,6 +75,24 b' bugzilla.regexp'
74 variations thereof, followed by an hours number prefixed by ``h`` or
75 variations thereof, followed by an hours number prefixed by ``h`` or
75 ``hours``, e.g. ``hours 1.5``. Matching is case insensitive.
76 ``hours``, e.g. ``hours 1.5``. Matching is case insensitive.
76
77
78 bugzilla.fixregexp
79 Regular expression to match bug IDs for marking fixed in changeset
80 commit message. This must contain a "()" named group ``<ids>` containing
81 the bug IDs separated by non-digit characters. It may also contain
82 a named group ``<hours>`` with a floating-point number giving the
83 hours worked on the bug. If no named groups are present, the first
84 "()" group is assumed to contain the bug IDs, and work time is not
85 updated. The default expression matches ``Fixes 1234``, ``Fixes bug 1234``,
86 ``Fixes bugs 1234,5678``, ``Fixes 1234 and 5678`` and
87 variations thereof, followed by an hours number prefixed by ``h`` or
88 ``hours``, e.g. ``hours 1.5``. Matching is case insensitive.
89
90 bugzilla.fixstatus
91 The status to set a bug to when marking fixed. Default ``RESOLVED``.
92
93 bugzilla.fixresolution
94 The resolution to set a bug to when marking fixed. Default ``FIXED``.
95
77 bugzilla.style
96 bugzilla.style
78 The style file to use when formatting comments.
97 The style file to use when formatting comments.
79
98
@@ -285,6 +304,7 b' class bzaccess(object):'
285 # updates to bug state. Recognised dict keys are:
304 # updates to bug state. Recognised dict keys are:
286 #
305 #
287 # 'hours': Value, float containing work hours to be updated.
306 # 'hours': Value, float containing work hours to be updated.
307 # 'fix': If key present, bug is to be marked fixed. Value ignored.
288
308
289 def filter_real_bug_ids(self, bugs):
309 def filter_real_bug_ids(self, bugs):
290 '''remove bug IDs that do not exist in Bugzilla from bugs.'''
310 '''remove bug IDs that do not exist in Bugzilla from bugs.'''
@@ -587,6 +607,10 b' class bzxmlrpc(bzaccess):'
587 user = self.ui.config('bugzilla', 'user', 'bugs')
607 user = self.ui.config('bugzilla', 'user', 'bugs')
588 passwd = self.ui.config('bugzilla', 'password')
608 passwd = self.ui.config('bugzilla', 'password')
589
609
610 self.fixstatus = self.ui.config('bugzilla', 'fixstatus', 'RESOLVED')
611 self.fixresolution = self.ui.config('bugzilla', 'fixresolution',
612 'FIXED')
613
590 self.bzproxy = xmlrpclib.ServerProxy(bzweb, self.transport(bzweb))
614 self.bzproxy = xmlrpclib.ServerProxy(bzweb, self.transport(bzweb))
591 self.bzproxy.User.login(dict(login=user, password=passwd))
615 self.bzproxy.User.login(dict(login=user, password=passwd))
592
616
@@ -618,9 +642,22 b' class bzxmlrpc(bzaccess):'
618 del bugs[id]
642 del bugs[id]
619
643
620 def updatebug(self, bugid, newstate, text, committer):
644 def updatebug(self, bugid, newstate, text, committer):
621 args = dict(id=bugid, comment=text)
645 args = {}
622 if 'hours' in newstate:
646 if 'hours' in newstate:
623 args['work_time'] = newstate['hours']
647 args['work_time'] = newstate['hours']
648
649 if self.bzvermajor >= 4:
650 args['ids'] = [bugid]
651 args['comment'] = {'body' : text}
652 args['status'] = self.fixstatus
653 args['resolution'] = self.fixresolution
654 self.bzproxy.Bug.update(args)
655 else:
656 if 'fix' in newstate:
657 self.ui.warn(_("Bugzilla/XMLRPC needs Bugzilla 4.0 or later "
658 "to mark bugs fixed\n"))
659 args['id'] = bugid
660 args['comment'] = text
624 self.bzproxy.Bug.add_comment(args)
661 self.bzproxy.Bug.add_comment(args)
625
662
626 class bzxmlrpcemail(bzxmlrpc):
663 class bzxmlrpcemail(bzxmlrpc):
@@ -631,8 +668,9 b' class bzxmlrpcemail(bzxmlrpc):'
631 2. Bug statuses or other fields not accessible via XMLRPC can
668 2. Bug statuses or other fields not accessible via XMLRPC can
632 potentially be updated.
669 potentially be updated.
633
670
634 Currently all status updates recognised can be done via XMLRPC, so
671 There is no XMLRPC function to change bug status before Bugzilla
635 item 1 is the only actual advantage.
672 4.0, so bugs cannot be marked fixed via XMLRPC before Bugzilla 4.0.
673 But bugs can be marked fixed via email from 3.4 onwards.
636 """
674 """
637
675
638 def __init__(self, ui):
676 def __init__(self, ui):
@@ -680,6 +718,9 b' class bzxmlrpcemail(bzxmlrpc):'
680 cmds = []
718 cmds = []
681 if 'hours' in newstate:
719 if 'hours' in newstate:
682 cmds.append(self.makecommandline("work_time", newstate['hours']))
720 cmds.append(self.makecommandline("work_time", newstate['hours']))
721 if 'fix' in newstate:
722 cmds.append(self.makecommandline("bug_status", self.fixstatus))
723 cmds.append(self.makecommandline("resolution", self.fixresolution))
683 self.send_bug_modify_email(bugid, cmds, text, committer)
724 self.send_bug_modify_email(bugid, cmds, text, committer)
684
725
685 class bugzilla(object):
726 class bugzilla(object):
@@ -697,6 +738,11 b' class bugzilla(object):'
697 r'(?P<ids>(?:\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
738 r'(?P<ids>(?:\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
698 r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
739 r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
699
740
741 _default_fix_re = (r'fix(?:es)?\s*(?:bugs?\s*)?,?\s*'
742 r'(?:nos?\.?|num(?:ber)?s?)?\s*'
743 r'(?P<ids>(?:#?\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
744 r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
745
700 _bz = None
746 _bz = None
701
747
702 def __init__(self, ui, repo):
748 def __init__(self, ui, repo):
@@ -721,6 +767,7 b' class bugzilla(object):'
721 return getattr(self.bz(), key)
767 return getattr(self.bz(), key)
722
768
723 _bug_re = None
769 _bug_re = None
770 _fix_re = None
724 _split_re = None
771 _split_re = None
725
772
726 def find_bugs(self, ctx):
773 def find_bugs(self, ctx):
@@ -732,18 +779,39 b' class bugzilla(object):'
732 '''
779 '''
733 if bugzilla._bug_re is None:
780 if bugzilla._bug_re is None:
734 bugzilla._bug_re = re.compile(
781 bugzilla._bug_re = re.compile(
735 self.ui.config('bugzilla', 'regexp', bugzilla._default_bug_re),
782 self.ui.config('bugzilla', 'regexp',
736 re.IGNORECASE)
783 bugzilla._default_bug_re), re.IGNORECASE)
784 bugzilla._fix_re = re.compile(
785 self.ui.config('bugzilla', 'fixregexp',
786 bugzilla._default_fix_re), re.IGNORECASE)
737 bugzilla._split_re = re.compile(r'\D+')
787 bugzilla._split_re = re.compile(r'\D+')
738 start = 0
788 start = 0
739 hours = 0.0
789 hours = 0.0
740 bugs = {}
790 bugs = {}
791 bugmatch = bugzilla._bug_re.search(ctx.description(), start)
792 fixmatch = bugzilla._fix_re.search(ctx.description(), start)
741 while True:
793 while True:
742 bugattribs = {}
794 bugattribs = {}
743 m = bugzilla._bug_re.search(ctx.description(), start)
795 if not bugmatch and not fixmatch:
744 if not m:
745 break
796 break
797 if not bugmatch:
798 m = fixmatch
799 elif not fixmatch:
800 m = bugmatch
801 else:
802 if bugmatch.start() < fixmatch.start():
803 m = bugmatch
804 else:
805 m = fixmatch
746 start = m.end()
806 start = m.end()
807 if m is bugmatch:
808 bugmatch = bugzilla._bug_re.search(ctx.description(), start)
809 if 'fix' in bugattribs:
810 del bugattribs['fix']
811 else:
812 fixmatch = bugzilla._fix_re.search(ctx.description(), start)
813 bugattribs['fix'] = None
814
747 try:
815 try:
748 ids = m.group('ids')
816 ids = m.group('ids')
749 except IndexError:
817 except IndexError:
General Comments 0
You need to be logged in to leave comments. Login now