eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/dispatch.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 # dispatch.py - command dispatching for mercurial
       
     2 #
       
     3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 from i18n import _
       
     9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
       
    10 import util, commands, hg, fancyopts, extensions, hook, error
       
    11 import cmdutil, encoding
       
    12 import ui as uimod
       
    13 
       
    14 def run():
       
    15     "run the command in sys.argv"
       
    16     sys.exit(dispatch(sys.argv[1:]))
       
    17 
       
    18 def dispatch(args):
       
    19     "run the command specified in args"
       
    20     try:
       
    21         u = uimod.ui()
       
    22         if '--traceback' in args:
       
    23             u.setconfig('ui', 'traceback', 'on')
       
    24     except util.Abort, inst:
       
    25         sys.stderr.write(_("abort: %s\n") % inst)
       
    26         if inst.hint:
       
    27             sys.stderr.write(_("(%s)\n") % inst.hint)
       
    28         return -1
       
    29     except error.ParseError, inst:
       
    30         if len(inst.args) > 1:
       
    31             sys.stderr.write(_("hg: parse error at %s: %s\n") %
       
    32                              (inst.args[1], inst.args[0]))
       
    33         else:
       
    34             sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0])
       
    35         return -1
       
    36     return _runcatch(u, args)
       
    37 
       
    38 def _runcatch(ui, args):
       
    39     def catchterm(*args):
       
    40         raise error.SignalInterrupt
       
    41 
       
    42     try:
       
    43         for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
       
    44             num = getattr(signal, name, None)
       
    45             if num:
       
    46                 signal.signal(num, catchterm)
       
    47     except ValueError:
       
    48         pass # happens if called in a thread
       
    49 
       
    50     try:
       
    51         try:
       
    52             # enter the debugger before command execution
       
    53             if '--debugger' in args:
       
    54                 ui.warn(_("entering debugger - "
       
    55                         "type c to continue starting hg or h for help\n"))
       
    56                 pdb.set_trace()
       
    57             try:
       
    58                 return _dispatch(ui, args)
       
    59             finally:
       
    60                 ui.flush()
       
    61         except:
       
    62             # enter the debugger when we hit an exception
       
    63             if '--debugger' in args:
       
    64                 traceback.print_exc()
       
    65                 pdb.post_mortem(sys.exc_info()[2])
       
    66             ui.traceback()
       
    67             raise
       
    68 
       
    69     # Global exception handling, alphabetically
       
    70     # Mercurial-specific first, followed by built-in and library exceptions
       
    71     except error.AmbiguousCommand, inst:
       
    72         ui.warn(_("hg: command '%s' is ambiguous:\n    %s\n") %
       
    73                 (inst.args[0], " ".join(inst.args[1])))
       
    74     except error.ParseError, inst:
       
    75         if len(inst.args) > 1:
       
    76             ui.warn(_("hg: parse error at %s: %s\n") %
       
    77                              (inst.args[1], inst.args[0]))
       
    78         else:
       
    79             ui.warn(_("hg: parse error: %s\n") % inst.args[0])
       
    80         return -1
       
    81     except error.LockHeld, inst:
       
    82         if inst.errno == errno.ETIMEDOUT:
       
    83             reason = _('timed out waiting for lock held by %s') % inst.locker
       
    84         else:
       
    85             reason = _('lock held by %s') % inst.locker
       
    86         ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
       
    87     except error.LockUnavailable, inst:
       
    88         ui.warn(_("abort: could not lock %s: %s\n") %
       
    89                (inst.desc or inst.filename, inst.strerror))
       
    90     except error.CommandError, inst:
       
    91         if inst.args[0]:
       
    92             ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
       
    93             commands.help_(ui, inst.args[0])
       
    94         else:
       
    95             ui.warn(_("hg: %s\n") % inst.args[1])
       
    96             commands.help_(ui, 'shortlist')
       
    97     except error.RepoError, inst:
       
    98         ui.warn(_("abort: %s!\n") % inst)
       
    99     except error.ResponseError, inst:
       
   100         ui.warn(_("abort: %s") % inst.args[0])
       
   101         if not isinstance(inst.args[1], basestring):
       
   102             ui.warn(" %r\n" % (inst.args[1],))
       
   103         elif not inst.args[1]:
       
   104             ui.warn(_(" empty string\n"))
       
   105         else:
       
   106             ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
       
   107     except error.RevlogError, inst:
       
   108         ui.warn(_("abort: %s!\n") % inst)
       
   109     except error.SignalInterrupt:
       
   110         ui.warn(_("killed!\n"))
       
   111     except error.UnknownCommand, inst:
       
   112         ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
       
   113         try:
       
   114             # check if the command is in a disabled extension
       
   115             # (but don't check for extensions themselves)
       
   116             commands.help_(ui, inst.args[0], unknowncmd=True)
       
   117         except error.UnknownCommand:
       
   118             commands.help_(ui, 'shortlist')
       
   119     except util.Abort, inst:
       
   120         ui.warn(_("abort: %s\n") % inst)
       
   121         if inst.hint:
       
   122             ui.warn(_("(%s)\n") % inst.hint)
       
   123     except ImportError, inst:
       
   124         ui.warn(_("abort: %s!\n") % inst)
       
   125         m = str(inst).split()[-1]
       
   126         if m in "mpatch bdiff".split():
       
   127             ui.warn(_("(did you forget to compile extensions?)\n"))
       
   128         elif m in "zlib".split():
       
   129             ui.warn(_("(is your Python install correct?)\n"))
       
   130     except IOError, inst:
       
   131         if hasattr(inst, "code"):
       
   132             ui.warn(_("abort: %s\n") % inst)
       
   133         elif hasattr(inst, "reason"):
       
   134             try: # usually it is in the form (errno, strerror)
       
   135                 reason = inst.reason.args[1]
       
   136             except: # it might be anything, for example a string
       
   137                 reason = inst.reason
       
   138             ui.warn(_("abort: error: %s\n") % reason)
       
   139         elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
       
   140             if ui.debugflag:
       
   141                 ui.warn(_("broken pipe\n"))
       
   142         elif getattr(inst, "strerror", None):
       
   143             if getattr(inst, "filename", None):
       
   144                 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
       
   145             else:
       
   146                 ui.warn(_("abort: %s\n") % inst.strerror)
       
   147         else:
       
   148             raise
       
   149     except OSError, inst:
       
   150         if getattr(inst, "filename", None):
       
   151             ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
       
   152         else:
       
   153             ui.warn(_("abort: %s\n") % inst.strerror)
       
   154     except KeyboardInterrupt:
       
   155         try:
       
   156             ui.warn(_("interrupted!\n"))
       
   157         except IOError, inst:
       
   158             if inst.errno == errno.EPIPE:
       
   159                 if ui.debugflag:
       
   160                     ui.warn(_("\nbroken pipe\n"))
       
   161             else:
       
   162                 raise
       
   163     except MemoryError:
       
   164         ui.warn(_("abort: out of memory\n"))
       
   165     except SystemExit, inst:
       
   166         # Commands shouldn't sys.exit directly, but give a return code.
       
   167         # Just in case catch this and and pass exit code to caller.
       
   168         return inst.code
       
   169     except socket.error, inst:
       
   170         ui.warn(_("abort: %s\n") % inst.args[-1])
       
   171     except:
       
   172         ui.warn(_("** unknown exception encountered,"
       
   173                   " please report by visiting\n"))
       
   174         ui.warn(_("**  http://mercurial.selenic.com/wiki/BugTracker\n"))
       
   175         ui.warn(_("** Python %s\n") % sys.version.replace('\n', ''))
       
   176         ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
       
   177                % util.version())
       
   178         ui.warn(_("** Extensions loaded: %s\n")
       
   179                % ", ".join([x[0] for x in extensions.extensions()]))
       
   180         raise
       
   181 
       
   182     return -1
       
   183 
       
   184 def aliasargs(fn):
       
   185     if hasattr(fn, 'args'):
       
   186         return fn.args
       
   187     return []
       
   188 
       
   189 class cmdalias(object):
       
   190     def __init__(self, name, definition, cmdtable):
       
   191         self.name = self.cmd = name
       
   192         self.cmdname = ''
       
   193         self.definition = definition
       
   194         self.args = []
       
   195         self.opts = []
       
   196         self.help = ''
       
   197         self.norepo = True
       
   198         self.badalias = False
       
   199 
       
   200         try:
       
   201             aliases, entry = cmdutil.findcmd(self.name, cmdtable)
       
   202             for alias, e in cmdtable.iteritems():
       
   203                 if e is entry:
       
   204                     self.cmd = alias
       
   205                     break
       
   206             self.shadows = True
       
   207         except error.UnknownCommand:
       
   208             self.shadows = False
       
   209 
       
   210         if not self.definition:
       
   211             def fn(ui, *args):
       
   212                 ui.warn(_("no definition for alias '%s'\n") % self.name)
       
   213                 return 1
       
   214             self.fn = fn
       
   215             self.badalias = True
       
   216 
       
   217             return
       
   218 
       
   219         if self.definition.startswith('!'):
       
   220             self.shell = True
       
   221             def fn(ui, *args):
       
   222                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
       
   223                 def _checkvar(m):
       
   224                     if int(m.groups()[0]) <= len(args):
       
   225                         return m.group()
       
   226                     else:
       
   227                         return ''
       
   228                 cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
       
   229                 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
       
   230                 replace['0'] = self.name
       
   231                 replace['@'] = ' '.join(args)
       
   232                 cmd = util.interpolate(r'\$', replace, cmd)
       
   233                 return util.system(cmd, environ=env)
       
   234             self.fn = fn
       
   235             return
       
   236 
       
   237         args = shlex.split(self.definition)
       
   238         self.cmdname = cmd = args.pop(0)
       
   239         args = map(util.expandpath, args)
       
   240 
       
   241         for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
       
   242             if _earlygetopt([invalidarg], args):
       
   243                 def fn(ui, *args):
       
   244                     ui.warn(_("error in definition for alias '%s': %s may only "
       
   245                               "be given on the command line\n")
       
   246                             % (self.name, invalidarg))
       
   247                     return 1
       
   248 
       
   249                 self.fn = fn
       
   250                 self.badalias = True
       
   251                 return
       
   252 
       
   253         try:
       
   254             tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
       
   255             if len(tableentry) > 2:
       
   256                 self.fn, self.opts, self.help = tableentry
       
   257             else:
       
   258                 self.fn, self.opts = tableentry
       
   259 
       
   260             self.args = aliasargs(self.fn) + args
       
   261             if cmd not in commands.norepo.split(' '):
       
   262                 self.norepo = False
       
   263             if self.help.startswith("hg " + cmd):
       
   264                 # drop prefix in old-style help lines so hg shows the alias
       
   265                 self.help = self.help[4 + len(cmd):]
       
   266             self.__doc__ = self.fn.__doc__
       
   267 
       
   268         except error.UnknownCommand:
       
   269             def fn(ui, *args):
       
   270                 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
       
   271                             % (self.name, cmd))
       
   272                 try:
       
   273                     # check if the command is in a disabled extension
       
   274                     commands.help_(ui, cmd, unknowncmd=True)
       
   275                 except error.UnknownCommand:
       
   276                     pass
       
   277                 return 1
       
   278             self.fn = fn
       
   279             self.badalias = True
       
   280         except error.AmbiguousCommand:
       
   281             def fn(ui, *args):
       
   282                 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
       
   283                             % (self.name, cmd))
       
   284                 return 1
       
   285             self.fn = fn
       
   286             self.badalias = True
       
   287 
       
   288     def __call__(self, ui, *args, **opts):
       
   289         if self.shadows:
       
   290             ui.debug("alias '%s' shadows command '%s'\n" %
       
   291                      (self.name, self.cmdname))
       
   292 
       
   293         if self.definition.startswith('!'):
       
   294             return self.fn(ui, *args, **opts)
       
   295         else:
       
   296             try:
       
   297                 util.checksignature(self.fn)(ui, *args, **opts)
       
   298             except error.SignatureError:
       
   299                 args = ' '.join([self.cmdname] + self.args)
       
   300                 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
       
   301                 raise
       
   302 
       
   303 def addaliases(ui, cmdtable):
       
   304     # aliases are processed after extensions have been loaded, so they
       
   305     # may use extension commands. Aliases can also use other alias definitions,
       
   306     # but only if they have been defined prior to the current definition.
       
   307     for alias, definition in ui.configitems('alias'):
       
   308         aliasdef = cmdalias(alias, definition, cmdtable)
       
   309         cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
       
   310         if aliasdef.norepo:
       
   311             commands.norepo += ' %s' % alias
       
   312 
       
   313 def _parse(ui, args):
       
   314     options = {}
       
   315     cmdoptions = {}
       
   316 
       
   317     try:
       
   318         args = fancyopts.fancyopts(args, commands.globalopts, options)
       
   319     except fancyopts.getopt.GetoptError, inst:
       
   320         raise error.CommandError(None, inst)
       
   321 
       
   322     if args:
       
   323         cmd, args = args[0], args[1:]
       
   324         aliases, entry = cmdutil.findcmd(cmd, commands.table,
       
   325                                      ui.config("ui", "strict"))
       
   326         cmd = aliases[0]
       
   327         args = aliasargs(entry[0]) + args
       
   328         defaults = ui.config("defaults", cmd)
       
   329         if defaults:
       
   330             args = map(util.expandpath, shlex.split(defaults)) + args
       
   331         c = list(entry[1])
       
   332     else:
       
   333         cmd = None
       
   334         c = []
       
   335 
       
   336     # combine global options into local
       
   337     for o in commands.globalopts:
       
   338         c.append((o[0], o[1], options[o[1]], o[3]))
       
   339 
       
   340     try:
       
   341         args = fancyopts.fancyopts(args, c, cmdoptions, True)
       
   342     except fancyopts.getopt.GetoptError, inst:
       
   343         raise error.CommandError(cmd, inst)
       
   344 
       
   345     # separate global options back out
       
   346     for o in commands.globalopts:
       
   347         n = o[1]
       
   348         options[n] = cmdoptions[n]
       
   349         del cmdoptions[n]
       
   350 
       
   351     return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
       
   352 
       
   353 def _parseconfig(ui, config):
       
   354     """parse the --config options from the command line"""
       
   355     for cfg in config:
       
   356         try:
       
   357             name, value = cfg.split('=', 1)
       
   358             section, name = name.split('.', 1)
       
   359             if not section or not name:
       
   360                 raise IndexError
       
   361             ui.setconfig(section, name, value)
       
   362         except (IndexError, ValueError):
       
   363             raise util.Abort(_('malformed --config option: %r '
       
   364                                '(use --config section.name=value)') % cfg)
       
   365 
       
   366 def _earlygetopt(aliases, args):
       
   367     """Return list of values for an option (or aliases).
       
   368 
       
   369     The values are listed in the order they appear in args.
       
   370     The options and values are removed from args.
       
   371     """
       
   372     try:
       
   373         argcount = args.index("--")
       
   374     except ValueError:
       
   375         argcount = len(args)
       
   376     shortopts = [opt for opt in aliases if len(opt) == 2]
       
   377     values = []
       
   378     pos = 0
       
   379     while pos < argcount:
       
   380         if args[pos] in aliases:
       
   381             if pos + 1 >= argcount:
       
   382                 # ignore and let getopt report an error if there is no value
       
   383                 break
       
   384             del args[pos]
       
   385             values.append(args.pop(pos))
       
   386             argcount -= 2
       
   387         elif args[pos][:2] in shortopts:
       
   388             # short option can have no following space, e.g. hg log -Rfoo
       
   389             values.append(args.pop(pos)[2:])
       
   390             argcount -= 1
       
   391         else:
       
   392             pos += 1
       
   393     return values
       
   394 
       
   395 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
       
   396     # run pre-hook, and abort if it fails
       
   397     ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
       
   398                     pats=cmdpats, opts=cmdoptions)
       
   399     if ret:
       
   400         return ret
       
   401     ret = _runcommand(ui, options, cmd, d)
       
   402     # run post-hook, passing command result
       
   403     hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
       
   404               result=ret, pats=cmdpats, opts=cmdoptions)
       
   405     return ret
       
   406 
       
   407 def _getlocal(ui, rpath):
       
   408     """Return (path, local ui object) for the given target path.
       
   409 
       
   410     Takes paths in [cwd]/.hg/hgrc into account."
       
   411     """
       
   412     try:
       
   413         wd = os.getcwd()
       
   414     except OSError, e:
       
   415         raise util.Abort(_("error getting current working directory: %s") %
       
   416                          e.strerror)
       
   417     path = cmdutil.findrepo(wd) or ""
       
   418     if not path:
       
   419         lui = ui
       
   420     else:
       
   421         lui = ui.copy()
       
   422         lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
       
   423 
       
   424     if rpath:
       
   425         path = lui.expandpath(rpath[-1])
       
   426         lui = ui.copy()
       
   427         lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
       
   428 
       
   429     return path, lui
       
   430 
       
   431 def _checkshellalias(ui, args):
       
   432     cwd = os.getcwd()
       
   433     norepo = commands.norepo
       
   434     options = {}
       
   435 
       
   436     try:
       
   437         args = fancyopts.fancyopts(args, commands.globalopts, options)
       
   438     except fancyopts.getopt.GetoptError:
       
   439         return
       
   440 
       
   441     if not args:
       
   442         return
       
   443 
       
   444     _parseconfig(ui, options['config'])
       
   445     if options['cwd']:
       
   446         os.chdir(options['cwd'])
       
   447 
       
   448     path, lui = _getlocal(ui, [options['repository']])
       
   449 
       
   450     cmdtable = commands.table.copy()
       
   451     addaliases(lui, cmdtable)
       
   452 
       
   453     cmd = args[0]
       
   454     try:
       
   455         aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
       
   456     except (error.AmbiguousCommand, error.UnknownCommand):
       
   457         commands.norepo = norepo
       
   458         os.chdir(cwd)
       
   459         return
       
   460 
       
   461     cmd = aliases[0]
       
   462     fn = entry[0]
       
   463 
       
   464     if cmd and hasattr(fn, 'shell'):
       
   465         d = lambda: fn(ui, *args[1:])
       
   466         return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
       
   467 
       
   468     commands.norepo = norepo
       
   469     os.chdir(cwd)
       
   470 
       
   471 _loaded = set()
       
   472 def _dispatch(ui, args):
       
   473     shellaliasfn = _checkshellalias(ui, args)
       
   474     if shellaliasfn:
       
   475         return shellaliasfn()
       
   476 
       
   477     # read --config before doing anything else
       
   478     # (e.g. to change trust settings for reading .hg/hgrc)
       
   479     _parseconfig(ui, _earlygetopt(['--config'], args))
       
   480 
       
   481     # check for cwd
       
   482     cwd = _earlygetopt(['--cwd'], args)
       
   483     if cwd:
       
   484         os.chdir(cwd[-1])
       
   485 
       
   486     rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
       
   487     path, lui = _getlocal(ui, rpath)
       
   488 
       
   489     # Configure extensions in phases: uisetup, extsetup, cmdtable, and
       
   490     # reposetup. Programs like TortoiseHg will call _dispatch several
       
   491     # times so we keep track of configured extensions in _loaded.
       
   492     extensions.loadall(lui)
       
   493     exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
       
   494     # Propagate any changes to lui.__class__ by extensions
       
   495     ui.__class__ = lui.__class__
       
   496 
       
   497     # (uisetup and extsetup are handled in extensions.loadall)
       
   498 
       
   499     for name, module in exts:
       
   500         cmdtable = getattr(module, 'cmdtable', {})
       
   501         overrides = [cmd for cmd in cmdtable if cmd in commands.table]
       
   502         if overrides:
       
   503             ui.warn(_("extension '%s' overrides commands: %s\n")
       
   504                     % (name, " ".join(overrides)))
       
   505         commands.table.update(cmdtable)
       
   506         _loaded.add(name)
       
   507 
       
   508     # (reposetup is handled in hg.repository)
       
   509 
       
   510     addaliases(lui, commands.table)
       
   511 
       
   512     # check for fallback encoding
       
   513     fallback = lui.config('ui', 'fallbackencoding')
       
   514     if fallback:
       
   515         encoding.fallbackencoding = fallback
       
   516 
       
   517     fullargs = args
       
   518     cmd, func, args, options, cmdoptions = _parse(lui, args)
       
   519 
       
   520     if options["config"]:
       
   521         raise util.Abort(_("option --config may not be abbreviated!"))
       
   522     if options["cwd"]:
       
   523         raise util.Abort(_("option --cwd may not be abbreviated!"))
       
   524     if options["repository"]:
       
   525         raise util.Abort(_(
       
   526             "Option -R has to be separated from other options (e.g. not -qR) "
       
   527             "and --repository may only be abbreviated as --repo!"))
       
   528 
       
   529     if options["encoding"]:
       
   530         encoding.encoding = options["encoding"]
       
   531     if options["encodingmode"]:
       
   532         encoding.encodingmode = options["encodingmode"]
       
   533     if options["time"]:
       
   534         def get_times():
       
   535             t = os.times()
       
   536             if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
       
   537                 t = (t[0], t[1], t[2], t[3], time.clock())
       
   538             return t
       
   539         s = get_times()
       
   540         def print_time():
       
   541             t = get_times()
       
   542             ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
       
   543                 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
       
   544         atexit.register(print_time)
       
   545 
       
   546     if options['verbose'] or options['debug'] or options['quiet']:
       
   547         ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
       
   548         ui.setconfig('ui', 'debug', str(bool(options['debug'])))
       
   549         ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
       
   550     if options['traceback']:
       
   551         ui.setconfig('ui', 'traceback', 'on')
       
   552     if options['noninteractive']:
       
   553         ui.setconfig('ui', 'interactive', 'off')
       
   554 
       
   555     if options['help']:
       
   556         return commands.help_(ui, cmd, options['version'])
       
   557     elif options['version']:
       
   558         return commands.version_(ui)
       
   559     elif not cmd:
       
   560         return commands.help_(ui, 'shortlist')
       
   561 
       
   562     repo = None
       
   563     cmdpats = args[:]
       
   564     if cmd not in commands.norepo.split():
       
   565         try:
       
   566             repo = hg.repository(ui, path=path)
       
   567             ui = repo.ui
       
   568             if not repo.local():
       
   569                 raise util.Abort(_("repository '%s' is not local") % path)
       
   570             ui.setconfig("bundle", "mainreporoot", repo.root)
       
   571         except error.RepoError:
       
   572             if cmd not in commands.optionalrepo.split():
       
   573                 if args and not path: # try to infer -R from command args
       
   574                     repos = map(cmdutil.findrepo, args)
       
   575                     guess = repos[0]
       
   576                     if guess and repos.count(guess) == len(repos):
       
   577                         return _dispatch(ui, ['--repository', guess] + fullargs)
       
   578                 if not path:
       
   579                     raise error.RepoError(_("There is no Mercurial repository"
       
   580                                       " here (.hg not found)"))
       
   581                 raise
       
   582         args.insert(0, repo)
       
   583     elif rpath:
       
   584         ui.warn(_("warning: --repository ignored\n"))
       
   585 
       
   586     msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
       
   587     ui.log("command", msg + "\n")
       
   588     d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
       
   589     return runcommand(lui, repo, cmd, fullargs, ui, options, d,
       
   590                       cmdpats, cmdoptions)
       
   591 
       
   592 def _runcommand(ui, options, cmd, cmdfunc):
       
   593     def checkargs():
       
   594         try:
       
   595             return cmdfunc()
       
   596         except error.SignatureError:
       
   597             raise error.CommandError(cmd, _("invalid arguments"))
       
   598 
       
   599     if options['profile']:
       
   600         format = ui.config('profiling', 'format', default='text')
       
   601 
       
   602         if not format in ['text', 'kcachegrind']:
       
   603             ui.warn(_("unrecognized profiling format '%s'"
       
   604                         " - Ignored\n") % format)
       
   605             format = 'text'
       
   606 
       
   607         output = ui.config('profiling', 'output')
       
   608 
       
   609         if output:
       
   610             path = ui.expandpath(output)
       
   611             ostream = open(path, 'wb')
       
   612         else:
       
   613             ostream = sys.stderr
       
   614 
       
   615         try:
       
   616             from mercurial import lsprof
       
   617         except ImportError:
       
   618             raise util.Abort(_(
       
   619                 'lsprof not available - install from '
       
   620                 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
       
   621         p = lsprof.Profiler()
       
   622         p.enable(subcalls=True)
       
   623         try:
       
   624             return checkargs()
       
   625         finally:
       
   626             p.disable()
       
   627 
       
   628             if format == 'kcachegrind':
       
   629                 import lsprofcalltree
       
   630                 calltree = lsprofcalltree.KCacheGrind(p)
       
   631                 calltree.output(ostream)
       
   632             else:
       
   633                 # format == 'text'
       
   634                 stats = lsprof.Stats(p.getstats())
       
   635                 stats.sort()
       
   636                 stats.pprint(top=10, file=ostream, climit=5)
       
   637 
       
   638             if output:
       
   639                 ostream.close()
       
   640     else:
       
   641         return checkargs()