mercurial/localrepo.py
changeset 4623 fff50306e6dd
parent 4620 5fd7cc897542
child 4633 ff7253a0d1da
equal deleted inserted replaced
4622:6fc26982f203 4623:fff50306e6dd
     8 from node import *
     8 from node import *
     9 from i18n import _
     9 from i18n import _
    10 import repo, changegroup
    10 import repo, changegroup
    11 import changelog, dirstate, filelog, manifest, context
    11 import changelog, dirstate, filelog, manifest, context
    12 import re, lock, transaction, tempfile, stat, mdiff, errno, ui
    12 import re, lock, transaction, tempfile, stat, mdiff, errno, ui
    13 import os, revlog, time, util, extensions
    13 import os, revlog, time, util, extensions, hook
    14 
    14 
    15 class localrepository(repo.repository):
    15 class localrepository(repo.repository):
    16     capabilities = ('lookup', 'changegroupsubset')
    16     capabilities = ('lookup', 'changegroupsubset')
    17     supported = ('revlogv1', 'store')
    17     supported = ('revlogv1', 'store')
    18 
    18 
   103 
   103 
   104     def url(self):
   104     def url(self):
   105         return 'file:' + self.root
   105         return 'file:' + self.root
   106 
   106 
   107     def hook(self, name, throw=False, **args):
   107     def hook(self, name, throw=False, **args):
   108         def callhook(hname, funcname):
   108         return hook.hook(self.ui, self, name, throw, **args)
   109             '''call python hook. hook is callable object, looked up as
       
   110             name in python module. if callable returns "true", hook
       
   111             fails, else passes. if hook raises exception, treated as
       
   112             hook failure. exception propagates if throw is "true".
       
   113 
       
   114             reason for "true" meaning "hook failed" is so that
       
   115             unmodified commands (e.g. mercurial.commands.update) can
       
   116             be run as hooks without wrappers to convert return values.'''
       
   117 
       
   118             self.ui.note(_("calling hook %s: %s\n") % (hname, funcname))
       
   119             obj = funcname
       
   120             if not callable(obj):
       
   121                 d = funcname.rfind('.')
       
   122                 if d == -1:
       
   123                     raise util.Abort(_('%s hook is invalid ("%s" not in '
       
   124                                        'a module)') % (hname, funcname))
       
   125                 modname = funcname[:d]
       
   126                 try:
       
   127                     obj = __import__(modname)
       
   128                 except ImportError:
       
   129                     try:
       
   130                         # extensions are loaded with hgext_ prefix
       
   131                         obj = __import__("hgext_%s" % modname)
       
   132                     except ImportError:
       
   133                         raise util.Abort(_('%s hook is invalid '
       
   134                                            '(import of "%s" failed)') %
       
   135                                          (hname, modname))
       
   136                 try:
       
   137                     for p in funcname.split('.')[1:]:
       
   138                         obj = getattr(obj, p)
       
   139                 except AttributeError, err:
       
   140                     raise util.Abort(_('%s hook is invalid '
       
   141                                        '("%s" is not defined)') %
       
   142                                      (hname, funcname))
       
   143                 if not callable(obj):
       
   144                     raise util.Abort(_('%s hook is invalid '
       
   145                                        '("%s" is not callable)') %
       
   146                                      (hname, funcname))
       
   147             try:
       
   148                 r = obj(ui=self.ui, repo=self, hooktype=name, **args)
       
   149             except (KeyboardInterrupt, util.SignalInterrupt):
       
   150                 raise
       
   151             except Exception, exc:
       
   152                 if isinstance(exc, util.Abort):
       
   153                     self.ui.warn(_('error: %s hook failed: %s\n') %
       
   154                                  (hname, exc.args[0]))
       
   155                 else:
       
   156                     self.ui.warn(_('error: %s hook raised an exception: '
       
   157                                    '%s\n') % (hname, exc))
       
   158                 if throw:
       
   159                     raise
       
   160                 self.ui.print_exc()
       
   161                 return True
       
   162             if r:
       
   163                 if throw:
       
   164                     raise util.Abort(_('%s hook failed') % hname)
       
   165                 self.ui.warn(_('warning: %s hook failed\n') % hname)
       
   166             return r
       
   167 
       
   168         def runhook(name, cmd):
       
   169             self.ui.note(_("running hook %s: %s\n") % (name, cmd))
       
   170             env = dict([('HG_' + k.upper(), v) for k, v in args.iteritems()])
       
   171             r = util.system(cmd, environ=env, cwd=self.root)
       
   172             if r:
       
   173                 desc, r = util.explain_exit(r)
       
   174                 if throw:
       
   175                     raise util.Abort(_('%s hook %s') % (name, desc))
       
   176                 self.ui.warn(_('warning: %s hook %s\n') % (name, desc))
       
   177             return r
       
   178 
       
   179         r = False
       
   180         hooks = [(hname, cmd) for hname, cmd in self.ui.configitems("hooks")
       
   181                  if hname.split(".", 1)[0] == name and cmd]
       
   182         hooks.sort()
       
   183         for hname, cmd in hooks:
       
   184             if callable(cmd):
       
   185                 r = callhook(hname, cmd) or r
       
   186             elif cmd.startswith('python:'):
       
   187                 r = callhook(hname, cmd[7:].strip()) or r
       
   188             else:
       
   189                 r = runhook(hname, cmd) or r
       
   190         return r
       
   191 
   109 
   192     tag_disallowed = ':\r\n'
   110     tag_disallowed = ':\r\n'
   193 
   111 
   194     def _tag(self, name, node, message, local, user, date, parent=None):
   112     def _tag(self, name, node, message, local, user, date, parent=None):
   195         use_dirstate = parent is None
   113         use_dirstate = parent is None