diff options
Diffstat (limited to 'mercurial/dispatch.py')
-rw-r--r-- | mercurial/dispatch.py | 244 |
1 files changed, 78 insertions, 166 deletions
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py index 520fe59..a1f8335 100644 --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -12,8 +12,7 @@ import cmdutil, encoding import ui as uimod class request(object): - def __init__(self, args, ui=None, repo=None, fin=None, fout=None, - ferr=None): + def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None): self.args = args self.ui = ui self.repo = repo @@ -25,7 +24,7 @@ class request(object): def run(): "run the command in sys.argv" - sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255) + sys.exit(dispatch(request(sys.argv[1:]))) def dispatch(req): "run the command specified in req.args" @@ -88,7 +87,7 @@ def _runcatch(req): return _dispatch(req) finally: ui.flush() - except: # re-raises + except: # enter the debugger when we hit an exception if '--debugger' in req.args: traceback.print_exc() @@ -124,9 +123,6 @@ def _runcatch(req): else: ui.warn(_("hg: %s\n") % inst.args[1]) commands.help_(ui, 'shortlist') - except error.OutOfBandError, inst: - ui.warn(_("abort: remote error:\n")) - ui.warn(''.join(inst.args)) except error.RepoError, inst: ui.warn(_("abort: %s!\n") % inst) if inst.hint: @@ -163,16 +159,16 @@ def _runcatch(req): elif m in "zlib".split(): ui.warn(_("(is your Python install correct?)\n")) except IOError, inst: - if util.safehasattr(inst, "code"): + if hasattr(inst, "code"): ui.warn(_("abort: %s\n") % inst) - elif util.safehasattr(inst, "reason"): + elif hasattr(inst, "reason"): try: # usually it is in the form (errno, strerror) reason = inst.reason.args[1] except (AttributeError, IndexError): - # it might be anything, for example a string + # it might be anything, for example a string reason = inst.reason ui.warn(_("abort: error: %s\n") % reason) - elif util.safehasattr(inst, "args") and inst.args[0] == errno.EPIPE: + elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE: if ui.debugflag: ui.warn(_("broken pipe\n")) elif getattr(inst, "strerror", None): @@ -204,72 +200,29 @@ def _runcatch(req): return inst.code except socket.error, inst: ui.warn(_("abort: %s\n") % inst.args[-1]) - except: # re-raises - myver = util.version() - # For compatibility checking, we discard the portion of the hg - # version after the + on the assumption that if a "normal - # user" is running a build with a + in it the packager - # probably built from fairly close to a tag and anyone with a - # 'make local' copy of hg (where the version number can be out - # of date) will be clueful enough to notice the implausible - # version number and try updating. - compare = myver.split('+')[0] - ct = tuplever(compare) - worst = None, ct, '' - for name, mod in extensions.extensions(): - testedwith = getattr(mod, 'testedwith', 'unknown') - report = getattr(mod, 'buglink', _('the extension author.')) - if testedwith == 'unknown': - # We found an untested extension. It's likely the culprit. - worst = name, testedwith, report - break - if compare not in testedwith.split() and testedwith != 'internal': - tested = [tuplever(v) for v in testedwith.split()] - lower = [t for t in tested if t < ct] - nearest = max(lower or tested) - if worst[0] is None or nearest < worst[1]: - worst = name, nearest, report - if worst[0] is not None: - name, testedwith, report = worst - if not isinstance(testedwith, str): - testedwith = '.'.join([str(c) for c in testedwith]) - warning = (_('** Unknown exception encountered with ' - 'possibly-broken third-party extension %s\n' - '** which supports versions %s of Mercurial.\n' - '** Please disable %s and try your action again.\n' - '** If that fixes the bug please report it to %s\n') - % (name, testedwith, name, report)) - else: - warning = (_("** unknown exception encountered, " - "please report by visiting\n") + - _("** http://mercurial.selenic.com/wiki/BugTracker\n")) - warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) + - (_("** Mercurial Distributed SCM (version %s)\n") % myver) + - (_("** Extensions loaded: %s\n") % - ", ".join([x[0] for x in extensions.extensions()]))) - ui.warn(warning) + except: + ui.warn(_("** unknown exception encountered," + " please report by visiting\n")) + ui.warn(_("** http://mercurial.selenic.com/wiki/BugTracker\n")) + ui.warn(_("** Python %s\n") % sys.version.replace('\n', '')) + ui.warn(_("** Mercurial Distributed SCM (version %s)\n") + % util.version()) + ui.warn(_("** Extensions loaded: %s\n") + % ", ".join([x[0] for x in extensions.extensions()])) raise return -1 -def tuplever(v): - try: - return tuple([int(i) for i in v.split('.')]) - except ValueError: - return tuple() - def aliasargs(fn, givenargs): args = getattr(fn, 'args', []) - if args: + if args and givenargs: cmd = ' '.join(map(util.shellquote, args)) nums = [] def replacer(m): num = int(m.group(1)) - 1 nums.append(num) - if num < len(givenargs): - return givenargs[num] - raise util.Abort(_('too few arguments for command alias')) + return givenargs[num] cmd = re.sub(r'\$(\d+|\$)', replacer, cmd) givenargs = [x for i, x in enumerate(givenargs) if i not in nums] @@ -285,7 +238,6 @@ class cmdalias(object): self.opts = [] self.help = '' self.norepo = True - self.optionalrepo = False self.badalias = False try: @@ -304,6 +256,7 @@ class cmdalias(object): return 1 self.fn = fn self.badalias = True + return if self.definition.startswith('!'): @@ -355,8 +308,6 @@ class cmdalias(object): self.args = aliasargs(self.fn, args) if cmd not in commands.norepo.split(' '): self.norepo = False - if cmd in commands.optionalrepo.split(' '): - self.optionalrepo = True if self.help.startswith("hg " + cmd): # drop prefix in old-style help lines so hg shows the alias self.help = self.help[4 + len(cmd):] @@ -387,7 +338,7 @@ class cmdalias(object): ui.debug("alias '%s' shadows command '%s'\n" % (self.name, self.cmdname)) - if util.safehasattr(self, 'shell'): + if hasattr(self, 'shell'): return self.fn(ui, *args, **opts) else: try: @@ -412,11 +363,9 @@ def addaliases(ui, cmdtable): # definition might not exist or it might not be a cmdalias pass - cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help) + cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help) if aliasdef.norepo: commands.norepo += ' %s' % alias - if aliasdef.optionalrepo: - commands.optionalrepo += ' %s' % alias def _parse(ui, args): options = {} @@ -430,7 +379,7 @@ def _parse(ui, args): if args: cmd, args = args[0], args[1:] aliases, entry = cmdutil.findcmd(cmd, commands.table, - ui.configbool("ui", "strict")) + ui.config("ui", "strict")) cmd = aliases[0] args = aliasargs(entry[0], args) defaults = ui.config("defaults", cmd) @@ -534,14 +483,16 @@ def _getlocal(ui, rpath): lui = ui.copy() lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) - if rpath and rpath[-1]: + if rpath: path = lui.expandpath(rpath[-1]) lui = ui.copy() lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) return path, lui -def _checkshellalias(lui, ui, args): +def _checkshellalias(ui, args): + cwd = os.getcwd() + norepo = commands.norepo options = {} try: @@ -552,38 +503,42 @@ def _checkshellalias(lui, ui, args): if not args: return - norepo = commands.norepo - optionalrepo = commands.optionalrepo - def restorecommands(): - commands.norepo = norepo - commands.optionalrepo = optionalrepo + _parseconfig(ui, options['config']) + if options['cwd']: + os.chdir(options['cwd']) + + path, lui = _getlocal(ui, [options['repository']]) cmdtable = commands.table.copy() addaliases(lui, cmdtable) cmd = args[0] try: - aliases, entry = cmdutil.findcmd(cmd, cmdtable, - lui.configbool("ui", "strict")) + aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict")) except (error.AmbiguousCommand, error.UnknownCommand): - restorecommands() + commands.norepo = norepo + os.chdir(cwd) return cmd = aliases[0] fn = entry[0] - if cmd and util.safehasattr(fn, 'shell'): + if cmd and hasattr(fn, 'shell'): d = lambda: fn(ui, *args[1:]) - return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, - [], {}) + return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {}) - restorecommands() + commands.norepo = norepo + os.chdir(cwd) _loaded = set() def _dispatch(req): args = req.args ui = req.ui + shellaliasfn = _checkshellalias(ui, args) + if shellaliasfn: + return shellaliasfn() + # read --config before doing anything else # (e.g. to change trust settings for reading .hg/hgrc) cfgs = _parseconfig(ui, _earlygetopt(['--config'], args)) @@ -596,12 +551,6 @@ def _dispatch(req): rpath = _earlygetopt(["-R", "--repository", "--repo"], args) path, lui = _getlocal(ui, rpath) - # Now that we're operating in the right directory/repository with - # the right config settings, check for shell aliases - shellaliasfn = _checkshellalias(lui, ui, args) - if shellaliasfn: - return shellaliasfn() - # Configure extensions in phases: uisetup, extsetup, cmdtable, and # reposetup. Programs like TortoiseHg will call _dispatch several # times so we keep track of configured extensions in _loaded. @@ -639,7 +588,7 @@ def _dispatch(req): raise util.Abort(_("option --cwd may not be abbreviated!")) if options["repository"]: raise util.Abort(_( - "option -R has to be separated from other options (e.g. not -qR) " + "Option -R has to be separated from other options (e.g. not -qR) " "and --repository may only be abbreviated as --repo!")) if options["encoding"]: @@ -655,7 +604,7 @@ def _dispatch(req): s = get_times() def print_time(): t = get_times() - ui.warn(_("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") % + ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") % (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3])) atexit.register(print_time) @@ -686,10 +635,10 @@ def _dispatch(req): for ui_ in uis: ui_.setconfig('web', 'cacerts', '') - if options['version']: - return commands.version_(ui) if options['help']: - return commands.help_(ui, cmd) + return commands.help_(ui, cmd, options['version']) + elif options['version']: + return commands.version_(ui) elif not cmd: return commands.help_(ui, 'shortlist') @@ -723,8 +672,7 @@ def _dispatch(req): return _dispatch(req) if not path: raise error.RepoError(_("no repository found in '%s'" - " (.hg not found)") - % os.getcwd()) + " (.hg not found)") % os.getcwd()) raise if repo: ui = repo.ui @@ -742,59 +690,6 @@ def _dispatch(req): if repo and repo != req.repo: repo.close() -def lsprofile(ui, func, fp): - format = ui.config('profiling', 'format', default='text') - field = ui.config('profiling', 'sort', default='inlinetime') - climit = ui.configint('profiling', 'nested', default=5) - - if format not in ['text', 'kcachegrind']: - ui.warn(_("unrecognized profiling format '%s'" - " - Ignored\n") % format) - format = 'text' - - try: - from mercurial import lsprof - except ImportError: - raise util.Abort(_( - 'lsprof not available - install from ' - 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/')) - p = lsprof.Profiler() - p.enable(subcalls=True) - try: - return func() - finally: - p.disable() - - if format == 'kcachegrind': - import lsprofcalltree - calltree = lsprofcalltree.KCacheGrind(p) - calltree.output(fp) - else: - # format == 'text' - stats = lsprof.Stats(p.getstats()) - stats.sort(field) - stats.pprint(limit=30, file=fp, climit=climit) - -def statprofile(ui, func, fp): - try: - import statprof - except ImportError: - raise util.Abort(_( - 'statprof not available - install using "easy_install statprof"')) - - freq = ui.configint('profiling', 'freq', default=1000) - if freq > 0: - statprof.reset(freq) - else: - ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq) - - statprof.start() - try: - return func() - finally: - statprof.stop() - statprof.display(fp) - def _runcommand(ui, options, cmd, cmdfunc): def checkargs(): try: @@ -803,28 +698,45 @@ def _runcommand(ui, options, cmd, cmdfunc): raise error.CommandError(cmd, _("invalid arguments")) if options['profile']: - profiler = os.getenv('HGPROF') - if profiler is None: - profiler = ui.config('profiling', 'type', default='ls') - if profiler not in ('ls', 'stat'): - ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler) - profiler = 'ls' + format = ui.config('profiling', 'format', default='text') + + if not format in ['text', 'kcachegrind']: + ui.warn(_("unrecognized profiling format '%s'" + " - Ignored\n") % format) + format = 'text' output = ui.config('profiling', 'output') if output: path = ui.expandpath(output) - fp = open(path, 'wb') + ostream = open(path, 'wb') else: - fp = sys.stderr + ostream = sys.stderr try: - if profiler == 'ls': - return lsprofile(ui, checkargs, fp) - else: - return statprofile(ui, checkargs, fp) + from mercurial import lsprof + except ImportError: + raise util.Abort(_( + 'lsprof not available - install from ' + 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/')) + p = lsprof.Profiler() + p.enable(subcalls=True) + try: + return checkargs() finally: + p.disable() + + if format == 'kcachegrind': + import lsprofcalltree + calltree = lsprofcalltree.KCacheGrind(p) + calltree.output(ostream) + else: + # format == 'text' + stats = lsprof.Stats(p.getstats()) + stats.sort() + stats.pprint(top=10, file=ostream, climit=5) + if output: - fp.close() + ostream.close() else: return checkargs() |