hgext/bugzilla.py
branchstable
changeset 21855 1eda3e556845
parent 21842 fd2527d9b995
child 24987 fd7287f0b43c
equal deleted inserted replaced
21843:92666a869ea4 21855:1eda3e556845
   775     _default_fix_re = (r'fix(?:es)?\s*(?:bugs?\s*)?,?\s*'
   775     _default_fix_re = (r'fix(?:es)?\s*(?:bugs?\s*)?,?\s*'
   776                        r'(?:nos?\.?|num(?:ber)?s?)?\s*'
   776                        r'(?:nos?\.?|num(?:ber)?s?)?\s*'
   777                        r'(?P<ids>(?:#?\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
   777                        r'(?P<ids>(?:#?\d+\s*(?:,?\s*(?:and)?)?\s*)+)'
   778                        r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
   778                        r'\.?\s*(?:h(?:ours?)?\s*(?P<hours>\d*(?:\.\d+)?))?')
   779 
   779 
   780     _bz = None
       
   781 
       
   782     def __init__(self, ui, repo):
   780     def __init__(self, ui, repo):
   783         self.ui = ui
   781         self.ui = ui
   784         self.repo = repo
   782         self.repo = repo
   785 
   783 
   786     def bz(self):
   784         bzversion = self.ui.config('bugzilla', 'version')
   787         '''return object that knows how to talk to bugzilla version in
   785         try:
   788         use.'''
   786             bzclass = bugzilla._versions[bzversion]
   789 
   787         except KeyError:
   790         if bugzilla._bz is None:
   788             raise util.Abort(_('bugzilla version %s not supported') %
   791             bzversion = self.ui.config('bugzilla', 'version')
   789                              bzversion)
   792             try:
   790         self.bzdriver = bzclass(self.ui)
   793                 bzclass = bugzilla._versions[bzversion]
   791 
   794             except KeyError:
   792         self.bug_re = re.compile(
   795                 raise util.Abort(_('bugzilla version %s not supported') %
   793             self.ui.config('bugzilla', 'regexp',
   796                                  bzversion)
   794                            bugzilla._default_bug_re), re.IGNORECASE)
   797             bugzilla._bz = bzclass(self.ui)
   795         self.fix_re = re.compile(
   798         return bugzilla._bz
   796             self.ui.config('bugzilla', 'fixregexp',
   799 
   797                            bugzilla._default_fix_re), re.IGNORECASE)
   800     def __getattr__(self, key):
   798         self.split_re = re.compile(r'\D+')
   801         return getattr(self.bz(), key)
       
   802 
       
   803     _bug_re = None
       
   804     _fix_re = None
       
   805     _split_re = None
       
   806 
   799 
   807     def find_bugs(self, ctx):
   800     def find_bugs(self, ctx):
   808         '''return bugs dictionary created from commit comment.
   801         '''return bugs dictionary created from commit comment.
   809 
   802 
   810         Extract bug info from changeset comments. Filter out any that are
   803         Extract bug info from changeset comments. Filter out any that are
   811         not known to Bugzilla, and any that already have a reference to
   804         not known to Bugzilla, and any that already have a reference to
   812         the given changeset in their comments.
   805         the given changeset in their comments.
   813         '''
   806         '''
   814         if bugzilla._bug_re is None:
       
   815             bugzilla._bug_re = re.compile(
       
   816                 self.ui.config('bugzilla', 'regexp',
       
   817                                bugzilla._default_bug_re), re.IGNORECASE)
       
   818             bugzilla._fix_re = re.compile(
       
   819                 self.ui.config('bugzilla', 'fixregexp',
       
   820                                bugzilla._default_fix_re), re.IGNORECASE)
       
   821             bugzilla._split_re = re.compile(r'\D+')
       
   822         start = 0
   807         start = 0
   823         hours = 0.0
   808         hours = 0.0
   824         bugs = {}
   809         bugs = {}
   825         bugmatch = bugzilla._bug_re.search(ctx.description(), start)
   810         bugmatch = self.bug_re.search(ctx.description(), start)
   826         fixmatch = bugzilla._fix_re.search(ctx.description(), start)
   811         fixmatch = self.fix_re.search(ctx.description(), start)
   827         while True:
   812         while True:
   828             bugattribs = {}
   813             bugattribs = {}
   829             if not bugmatch and not fixmatch:
   814             if not bugmatch and not fixmatch:
   830                 break
   815                 break
   831             if not bugmatch:
   816             if not bugmatch:
   837                     m = bugmatch
   822                     m = bugmatch
   838                 else:
   823                 else:
   839                     m = fixmatch
   824                     m = fixmatch
   840             start = m.end()
   825             start = m.end()
   841             if m is bugmatch:
   826             if m is bugmatch:
   842                 bugmatch = bugzilla._bug_re.search(ctx.description(), start)
   827                 bugmatch = self.bug_re.search(ctx.description(), start)
   843                 if 'fix' in bugattribs:
   828                 if 'fix' in bugattribs:
   844                     del bugattribs['fix']
   829                     del bugattribs['fix']
   845             else:
   830             else:
   846                 fixmatch = bugzilla._fix_re.search(ctx.description(), start)
   831                 fixmatch = self.fix_re.search(ctx.description(), start)
   847                 bugattribs['fix'] = None
   832                 bugattribs['fix'] = None
   848 
   833 
   849             try:
   834             try:
   850                 ids = m.group('ids')
   835                 ids = m.group('ids')
   851             except IndexError:
   836             except IndexError:
   858             except TypeError:
   843             except TypeError:
   859                 pass
   844                 pass
   860             except ValueError:
   845             except ValueError:
   861                 self.ui.status(_("%s: invalid hours\n") % m.group('hours'))
   846                 self.ui.status(_("%s: invalid hours\n") % m.group('hours'))
   862 
   847 
   863             for id in bugzilla._split_re.split(ids):
   848             for id in self.split_re.split(ids):
   864                 if not id:
   849                 if not id:
   865                     continue
   850                     continue
   866                 bugs[int(id)] = bugattribs
   851                 bugs[int(id)] = bugattribs
   867         if bugs:
   852         if bugs:
   868             self.filter_real_bug_ids(bugs)
   853             self.bzdriver.filter_real_bug_ids(bugs)
   869         if bugs:
   854         if bugs:
   870             self.filter_cset_known_bug_ids(ctx.node(), bugs)
   855             self.bzdriver.filter_cset_known_bug_ids(ctx.node(), bugs)
   871         return bugs
   856         return bugs
   872 
   857 
   873     def update(self, bugid, newstate, ctx):
   858     def update(self, bugid, newstate, ctx):
   874         '''update bugzilla bug with reference to changeset.'''
   859         '''update bugzilla bug with reference to changeset.'''
   875 
   860 
   900                bug=str(bugid),
   885                bug=str(bugid),
   901                hgweb=self.ui.config('web', 'baseurl'),
   886                hgweb=self.ui.config('web', 'baseurl'),
   902                root=self.repo.root,
   887                root=self.repo.root,
   903                webroot=webroot(self.repo.root))
   888                webroot=webroot(self.repo.root))
   904         data = self.ui.popbuffer()
   889         data = self.ui.popbuffer()
   905         self.updatebug(bugid, newstate, data, util.email(ctx.user()))
   890         self.bzdriver.updatebug(bugid, newstate, data, util.email(ctx.user()))
       
   891 
       
   892     def notify(self, bugs, committer):
       
   893         '''ensure Bugzilla users are notified of bug change.'''
       
   894         self.bzdriver.notify(bugs, committer)
   906 
   895 
   907 def hook(ui, repo, hooktype, node=None, **kwargs):
   896 def hook(ui, repo, hooktype, node=None, **kwargs):
   908     '''add comment to bugzilla for each changeset that refers to a
   897     '''add comment to bugzilla for each changeset that refers to a
   909     bugzilla bug id. only add a comment once per bug, so same change
   898     bugzilla bug id. only add a comment once per bug, so same change
   910     seen multiple times does not fill bug with duplicate data.'''
   899     seen multiple times does not fill bug with duplicate data.'''