# HG changeset patch # User Matt Mackall # Date 1181614164 18000 # Node ID 0c61124ad877fbed7f7e5688a412beefa9516001 # Parent c9fcebbfc422f8659a37aa6b41e1d189b7e7aff2 dispatch: move dispatching code to cmdutil diff --git a/hgext/fetch.py b/hgext/fetch.py --- a/hgext/fetch.py +++ b/hgext/fetch.py @@ -7,7 +7,7 @@ from mercurial.i18n import _ from mercurial.node import * -from mercurial import commands, hg, node, util +from mercurial import commands, cmdutil, hg, node, util def fetch(ui, repo, source='default', **opts): '''Pull changes from a remote repository, merge new changes if needed. @@ -42,7 +42,7 @@ def fetch(ui, repo, source='default', ** (len(newheads) - 1)) if not err: mod, add, rem = repo.status(wlock=wlock)[:3] - message = (commands.logmessage(opts) or + message = (cmdutil.logmessage(opts) or (_('Automated merge with %s') % other.url())) n = repo.commit(mod + add + rem, message, opts['user'], opts['date'], lock=lock, wlock=wlock, @@ -51,7 +51,7 @@ def fetch(ui, repo, source='default', ** 'with local\n') % (repo.changelog.rev(n), short(n))) def pull(): - commands.setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) other = hg.repository(ui, ui.expandpath(source)) ui.status(_('pulling from %s\n') % ui.expandpath(source)) diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -1579,7 +1579,7 @@ def clone(ui, source, dest=None, **opts) Source patch repository is looked for in /.hg/patches by default. Use -p to change. ''' - commands.setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) if dest is None: dest = hg.defaultdest(source) sr = hg.repository(ui, ui.expandpath(source)) @@ -1670,7 +1670,7 @@ def new(ui, repo, patch, **opts): If none is specified, the patch header is empty and the commit message is 'New patch: PATCH'""" q = repo.mq - message = commands.logmessage(opts) + message = cmdutil.logmessage(opts) if opts['edit']: message = ui.edit(message, ui.username()) q.new(repo, patch, msg=message, force=opts['force']) @@ -1688,7 +1688,7 @@ def refresh(ui, repo, *pats, **opts): git-style patches (--git or [diff] git=1) to track copies and renames. """ q = repo.mq - message = commands.logmessage(opts) + message = cmdutil.logmessage(opts) if opts['edit']: if message: raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) @@ -1724,7 +1724,7 @@ def fold(ui, repo, *files, **opts): if not q.check_toppatch(repo): raise util.Abort(_('No patches applied')) - message = commands.logmessage(opts) + message = cmdutil.logmessage(opts) if opts['edit']: if message: raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) @@ -1964,7 +1964,7 @@ def restore(ui, repo, rev, **opts): def save(ui, repo, **opts): """save current queue state""" q = repo.mq - message = commands.logmessage(opts) + message = cmdutil.logmessage(opts) ret = q.save(repo, msg=message) if ret: return ret diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -7,10 +7,279 @@ from node import * from i18n import _ -import os, sys, mdiff, bdiff, util, templater, patch +import os, sys, mdiff, bdiff, util, templater, patch, commands +import atexit, signal, pdb, hg, lock, fancyopts, traceback +import socket, revlog, version, extensions, errno revrangesep = ':' +class UnknownCommand(Exception): + """Exception raised if command is not in the command table.""" +class AmbiguousCommand(Exception): + """Exception raised if command shortcut matches more than one command.""" +class ParseError(Exception): + """Exception raised on errors in parsing the command line.""" + +def runcatch(u, args): + def catchterm(*args): + raise util.SignalInterrupt + + for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM': + num = getattr(signal, name, None) + if num: signal.signal(num, catchterm) + + try: + return dispatch(u, args) + except ParseError, inst: + if inst.args[0]: + u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1])) + commands.help_(u, inst.args[0]) + else: + u.warn(_("hg: %s\n") % inst.args[1]) + commands.help_(u, 'shortlist') + except AmbiguousCommand, inst: + u.warn(_("hg: command '%s' is ambiguous:\n %s\n") % + (inst.args[0], " ".join(inst.args[1]))) + except UnknownCommand, inst: + u.warn(_("hg: unknown command '%s'\n") % inst.args[0]) + commands.help_(u, 'shortlist') + except hg.RepoError, inst: + u.warn(_("abort: %s!\n") % inst) + except lock.LockHeld, inst: + if inst.errno == errno.ETIMEDOUT: + reason = _('timed out waiting for lock held by %s') % inst.locker + else: + reason = _('lock held by %s') % inst.locker + u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) + except lock.LockUnavailable, inst: + u.warn(_("abort: could not lock %s: %s\n") % + (inst.desc or inst.filename, inst.strerror)) + except revlog.RevlogError, inst: + u.warn(_("abort: %s!\n") % inst) + except util.SignalInterrupt: + u.warn(_("killed!\n")) + except KeyboardInterrupt: + try: + u.warn(_("interrupted!\n")) + except IOError, inst: + if inst.errno == errno.EPIPE: + if u.debugflag: + u.warn(_("\nbroken pipe\n")) + else: + raise + except socket.error, inst: + u.warn(_("abort: %s\n") % inst[1]) + except IOError, inst: + if hasattr(inst, "code"): + u.warn(_("abort: %s\n") % inst) + elif hasattr(inst, "reason"): + try: # usually it is in the form (errno, strerror) + reason = inst.reason.args[1] + except: # it might be anything, for example a string + reason = inst.reason + u.warn(_("abort: error: %s\n") % reason) + elif hasattr(inst, "args") and inst[0] == errno.EPIPE: + if u.debugflag: + u.warn(_("broken pipe\n")) + elif getattr(inst, "strerror", None): + if getattr(inst, "filename", None): + u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) + else: + u.warn(_("abort: %s\n") % inst.strerror) + else: + raise + except OSError, inst: + if getattr(inst, "filename", None): + u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) + else: + u.warn(_("abort: %s\n") % inst.strerror) + except util.UnexpectedOutput, inst: + u.warn(_("abort: %s") % inst[0]) + if not isinstance(inst[1], basestring): + u.warn(" %r\n" % (inst[1],)) + elif not inst[1]: + u.warn(_(" empty string\n")) + else: + u.warn("\n%r\n" % util.ellipsis(inst[1])) + except util.Abort, inst: + u.warn(_("abort: %s\n") % inst) + except TypeError, inst: + # was this an argument error? + tb = traceback.extract_tb(sys.exc_info()[2]) + if len(tb) > 2: # no + raise + u.debug(inst, "\n") + u.warn(_("%s: invalid arguments\n") % cmd) + commands.help_(u, cmd) + except SystemExit, inst: + # Commands shouldn't sys.exit directly, but give a return code. + # Just in case catch this and and pass exit code to caller. + return inst.code + except: + u.warn(_("** unknown exception encountered, details follow\n")) + u.warn(_("** report bug details to " + "http://www.selenic.com/mercurial/bts\n")) + u.warn(_("** or mercurial@selenic.com\n")) + u.warn(_("** Mercurial Distributed SCM (version %s)\n") + % version.get_version()) + raise + + return -1 + +def findpossible(ui, cmd): + """ + Return cmd -> (aliases, command table entry) + for each matching command. + Return debug commands (or their aliases) only if no normal command matches. + """ + choice = {} + debugchoice = {} + for e in commands.table.keys(): + aliases = e.lstrip("^").split("|") + found = None + if cmd in aliases: + found = cmd + elif not ui.config("ui", "strict"): + for a in aliases: + if a.startswith(cmd): + found = a + break + if found is not None: + if aliases[0].startswith("debug") or found.startswith("debug"): + debugchoice[found] = (aliases, commands.table[e]) + else: + choice[found] = (aliases, commands.table[e]) + + if not choice and debugchoice: + choice = debugchoice + + return choice + +def findcmd(ui, cmd): + """Return (aliases, command table entry) for command string.""" + choice = findpossible(ui, cmd) + + if choice.has_key(cmd): + return choice[cmd] + + if len(choice) > 1: + clist = choice.keys() + clist.sort() + raise AmbiguousCommand(cmd, clist) + + if choice: + return choice.values()[0] + + raise UnknownCommand(cmd) + +def parse(ui, args): + options = {} + cmdoptions = {} + + try: + args = fancyopts.fancyopts(args, commands.globalopts, options) + except fancyopts.getopt.GetoptError, inst: + raise ParseError(None, inst) + + if args: + cmd, args = args[0], args[1:] + aliases, i = findcmd(ui, cmd) + cmd = aliases[0] + defaults = ui.config("defaults", cmd) + if defaults: + args = shlex.split(defaults) + args + c = list(i[1]) + else: + cmd = None + c = [] + + # combine global options into local + for o in commands.globalopts: + c.append((o[0], o[1], options[o[1]], o[3])) + + try: + args = fancyopts.fancyopts(args, c, cmdoptions) + except fancyopts.getopt.GetoptError, inst: + raise ParseError(cmd, inst) + + # separate global options back out + for o in commands.globalopts: + n = o[1] + options[n] = cmdoptions[n] + del cmdoptions[n] + + return (cmd, cmd and i[0] or None, args, options, cmdoptions) + +def parseconfig(config): + """parse the --config options from the command line""" + parsed = [] + for cfg in config: + try: + name, value = cfg.split('=', 1) + section, name = name.split('.', 1) + if not section or not name: + raise IndexError + parsed.append((section, name, value)) + except (IndexError, ValueError): + raise util.Abort(_('malformed --config option: %s') % cfg) + return parsed + +def dispatch(u, args): + extensions.loadall(u) + u.addreadhook(extensions.loadall) + + cmd, func, args, options, cmdoptions = parse(u, args) + + if options["encoding"]: + util._encoding = options["encoding"] + if options["encodingmode"]: + util._encodingmode = options["encodingmode"] + if options["time"]: + def get_times(): + t = os.times() + if t[4] == 0.0: # Windows leaves this as zero, so use time.clock() + t = (t[0], t[1], t[2], t[3], time.clock()) + return t + s = get_times() + def print_time(): + t = get_times() + u.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) + + if options['cwd']: + os.chdir(options['cwd']) + + u.updateopts(options["verbose"], options["debug"], options["quiet"], + not options["noninteractive"], options["traceback"], + parseconfig(options["config"])) + + path = u.expandpath(options["repository"]) or "" + repo = path and hg.repository(u, path=path) or None + if repo and not repo.local(): + raise util.Abort(_("repository '%s' is not local") % path) + + if options['help']: + return commands.help_(u, cmd, options['version']) + elif options['version']: + return commands.version_(u) + elif not cmd: + return commands.help_(u, 'shortlist') + + if cmd not in commands.norepo.split(): + try: + if not repo: + repo = hg.repository(u, path=path) + u = repo.ui + except hg.RepoError: + if cmd not in commands.optionalrepo.split(): + raise + d = lambda: func(u, repo, *args, **cmdoptions) + else: + d = lambda: func(u, *args, **cmdoptions) + + return runcommand(u, options, d) + def runcommand(u, options, d): # enter the debugger before command execution if options['debugger']: @@ -64,6 +333,37 @@ def runcommand(u, options, d): u.print_exc() raise +def bail_if_changed(repo): + modified, added, removed, deleted = repo.status()[:4] + if modified or added or removed or deleted: + raise util.Abort(_("outstanding uncommitted changes")) + +def logmessage(opts): + """ get the log message according to -m and -l option """ + message = opts['message'] + logfile = opts['logfile'] + + if message and logfile: + raise util.Abort(_('options --message and --logfile are mutually ' + 'exclusive')) + if not message and logfile: + try: + if logfile == '-': + message = sys.stdin.read() + else: + message = open(logfile).read() + except IOError, inst: + raise util.Abort(_("can't read commit message '%s': %s") % + (logfile, inst.strerror)) + return message + +def setremoteconfig(ui, opts): + "copy remote options to ui tree" + if opts.get('ssh'): + ui.setconfig("ui", "ssh", opts['ssh']) + if opts.get('remotecmd'): + ui.setconfig("ui", "remotecmd", opts['remotecmd']) + def parseurl(url, revs): '''parse url#branch, returning url, branch + revs''' diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -8,48 +8,12 @@ import demandimport; demandimport.enable() from node import * from i18n import _ -import bisect, os, re, sys, signal, urllib, pdb, shlex, stat -import fancyopts, ui, hg, util, lock, revlog, bundlerepo, extensions +import bisect, os, re, sys, urllib, shlex, stat +import ui, hg, util, revlog, bundlerepo, extensions import difflib, patch, time, help, mdiff, tempfile -import traceback, errno, version, atexit, socket +import errno, version, socket import archival, changegroup, cmdutil, hgweb.server, sshserver -class UnknownCommand(Exception): - """Exception raised if command is not in the command table.""" -class AmbiguousCommand(Exception): - """Exception raised if command shortcut matches more than one command.""" - -def bail_if_changed(repo): - modified, added, removed, deleted = repo.status()[:4] - if modified or added or removed or deleted: - raise util.Abort(_("outstanding uncommitted changes")) - -def logmessage(opts): - """ get the log message according to -m and -l option """ - message = opts['message'] - logfile = opts['logfile'] - - if message and logfile: - raise util.Abort(_('options --message and --logfile are mutually ' - 'exclusive')) - if not message and logfile: - try: - if logfile == '-': - message = sys.stdin.read() - else: - message = open(logfile).read() - except IOError, inst: - raise util.Abort(_("can't read commit message '%s': %s") % - (logfile, inst.strerror)) - return message - -def setremoteconfig(ui, opts): - "copy remote options to ui tree" - if opts.get('ssh'): - ui.setconfig("ui", "ssh", opts['ssh']) - if opts.get('remotecmd'): - ui.setconfig("ui", "remotecmd", opts['remotecmd']) - # Commands start here, listed alphabetically def add(ui, repo, *pats, **opts): @@ -205,7 +169,7 @@ def backout(ui, repo, node=None, rev=Non if not rev: rev = node - bail_if_changed(repo) + cmdutil.bail_if_changed(repo) op1, op2 = repo.dirstate.parents() if op2 != nullid: raise util.Abort(_('outstanding uncommitted merge')) @@ -335,7 +299,7 @@ def bundle(ui, repo, fname, dest=None, * seen[p] = 1 visit.append(p) else: - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) dest, revs = cmdutil.parseurl( ui.expandpath(dest or 'default-push', dest or 'default'), revs) other = hg.repository(ui, dest) @@ -407,7 +371,7 @@ def clone(ui, source, dest=None, **opts) Look at the help text for the pull command for important details about ssh:// URLs. """ - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) hg.clone(ui, source, dest, pull=opts['pull'], stream=opts['uncompressed'], @@ -425,7 +389,7 @@ def commit(ui, repo, *pats, **opts): If no commit message is specified, the editor configured in your hgrc or in the EDITOR environment variable is started to enter a message. """ - message = logmessage(opts) + message = cmdutil.logmessage(opts) if opts['addremove']: cmdutil.addremove(repo, pats, opts) @@ -685,7 +649,7 @@ def debugcomplete(ui, cmd='', **opts): options = [] otables = [globalopts] if cmd: - aliases, entry = findcmd(ui, cmd) + aliases, entry = cmdutil.findcmd(ui, cmd) otables.append(entry[1]) for t in otables: for o in t: @@ -695,7 +659,7 @@ def debugcomplete(ui, cmd='', **opts): ui.write("%s\n" % "\n".join(options)) return - clist = findpossible(ui, cmd).keys() + clist = cmdutil.findpossible(ui, cmd).keys() clist.sort() ui.write("%s\n" % "\n".join(clist)) @@ -1295,7 +1259,7 @@ def help_(ui, name=None, with_version=Fa if with_version: version_(ui) ui.write('\n') - aliases, i = findcmd(ui, name) + aliases, i = cmdutil.findcmd(ui, name) # synopsis ui.write("%s\n\n" % i[2]) @@ -1357,7 +1321,7 @@ def help_(ui, name=None, with_version=Fa v = i header = l[-1] if not v: - raise UnknownCommand(name) + raise cmdutil.UnknownCommand(name) # description doc = help.helptable[v] @@ -1373,7 +1337,7 @@ def help_(ui, name=None, with_version=Fa try: mod = extensions.find(name) except KeyError: - raise UnknownCommand(name) + raise cmdutil.UnknownCommand(name) doc = (mod.__doc__ or _('No help text available')).splitlines(0) ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0])) @@ -1399,7 +1363,7 @@ def help_(ui, name=None, with_version=Fa f(name) i = None break - except UnknownCommand, inst: + except cmdutil.UnknownCommand, inst: i = inst if i: raise i @@ -1506,7 +1470,7 @@ def import_(ui, repo, patch1, *patches, patches = (patch1,) + patches if opts.get('exact') or not opts['force']: - bail_if_changed(repo) + cmdutil.bail_if_changed(repo) d = opts["base"] strip = opts["strip"] @@ -1528,7 +1492,7 @@ def import_(ui, repo, patch1, *patches, raise util.Abort(_('no diffs found')) try: - cmdline_message = logmessage(opts) + cmdline_message = cmdutil.logmessage(opts) if cmdline_message: # pickup the cmdline msg message = cmdline_message @@ -1587,7 +1551,7 @@ def incoming(ui, repo, source="default", See pull for valid source format details. """ source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) other = hg.repository(ui, source) ui.status(_('comparing with %s\n') % source) @@ -1653,7 +1617,7 @@ def init(ui, dest=".", **opts): Look at the help text for the pull command for important details about ssh:// URLs. """ - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) hg.repository(ui, dest, create=1) def locate(ui, repo, *pats, **opts): @@ -1890,7 +1854,7 @@ def outgoing(ui, repo, dest=None, **opts """ dest, revs = cmdutil.parseurl( ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) if revs: revs = [repo.lookup(rev) for rev in revs] @@ -2005,7 +1969,7 @@ def pull(ui, repo, source="default", **o with the --ssh command line option. """ source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) other = hg.repository(ui, source) ui.status(_('pulling from %s\n') % (source)) @@ -2051,7 +2015,7 @@ def push(ui, repo, dest=None, **opts): """ dest, revs = cmdutil.parseurl( ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) - setremoteconfig(ui, opts) + cmdutil.setremoteconfig(ui, opts) other = hg.repository(ui, dest) ui.status('pushing to %s\n' % (dest)) @@ -2075,7 +2039,7 @@ def rawcommit(ui, repo, *pats, **opts): ui.warn(_("(the rawcommit command is deprecated)\n")) - message = logmessage(opts) + message = cmdutil.logmessage(opts) files, match, anypats = cmdutil.matchpats(repo, pats, opts) if opts['files']: @@ -3039,272 +3003,5 @@ def run(): except util.Abort, inst: sys.stderr.write(_("abort: %s\n") % inst) return -1 - sys.exit(runcatch(u, sys.argv[1:])) - -def runcatch(u, args): - def catchterm(*args): - raise util.SignalInterrupt - - for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM': - num = getattr(signal, name, None) - if num: signal.signal(num, catchterm) - - try: - return dispatch(u, args) - except hg.RepoError, inst: - u.warn(_("abort: %s!\n") % inst) - except lock.LockHeld, inst: - if inst.errno == errno.ETIMEDOUT: - reason = _('timed out waiting for lock held by %s') % inst.locker - else: - reason = _('lock held by %s') % inst.locker - u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) - except lock.LockUnavailable, inst: - u.warn(_("abort: could not lock %s: %s\n") % - (inst.desc or inst.filename, inst.strerror)) - except revlog.RevlogError, inst: - u.warn(_("abort: %s!\n") % inst) - except util.SignalInterrupt: - u.warn(_("killed!\n")) - except KeyboardInterrupt: - try: - u.warn(_("interrupted!\n")) - except IOError, inst: - if inst.errno == errno.EPIPE: - if u.debugflag: - u.warn(_("\nbroken pipe\n")) - else: - raise - except socket.error, inst: - u.warn(_("abort: %s\n") % inst[1]) - except IOError, inst: - if hasattr(inst, "code"): - u.warn(_("abort: %s\n") % inst) - elif hasattr(inst, "reason"): - try: # usually it is in the form (errno, strerror) - reason = inst.reason.args[1] - except: # it might be anything, for example a string - reason = inst.reason - u.warn(_("abort: error: %s\n") % reason) - elif hasattr(inst, "args") and inst[0] == errno.EPIPE: - if u.debugflag: - u.warn(_("broken pipe\n")) - elif getattr(inst, "strerror", None): - if getattr(inst, "filename", None): - u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) - else: - u.warn(_("abort: %s\n") % inst.strerror) - else: - raise - except OSError, inst: - if getattr(inst, "filename", None): - u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) - else: - u.warn(_("abort: %s\n") % inst.strerror) - except util.UnexpectedOutput, inst: - u.warn(_("abort: %s") % inst[0]) - if not isinstance(inst[1], basestring): - u.warn(" %r\n" % (inst[1],)) - elif not inst[1]: - u.warn(_(" empty string\n")) - else: - u.warn("\n%r\n" % util.ellipsis(inst[1])) - except util.Abort, inst: - u.warn(_("abort: %s\n") % inst) - except TypeError, inst: - # was this an argument error? - tb = traceback.extract_tb(sys.exc_info()[2]) - if len(tb) > 2: # no - raise - u.debug(inst, "\n") - u.warn(_("%s: invalid arguments\n") % cmd) - help_(u, cmd) - except SystemExit, inst: - # Commands shouldn't sys.exit directly, but give a return code. - # Just in case catch this and and pass exit code to caller. - return inst.code - except: - u.warn(_("** unknown exception encountered, details follow\n")) - u.warn(_("** report bug details to " - "http://www.selenic.com/mercurial/bts\n")) - u.warn(_("** or mercurial@selenic.com\n")) - u.warn(_("** Mercurial Distributed SCM (version %s)\n") - % version.get_version()) - raise - - return -1 - -def findpossible(ui, cmd): - """ - Return cmd -> (aliases, command table entry) - for each matching command. - Return debug commands (or their aliases) only if no normal command matches. - """ - choice = {} - debugchoice = {} - for e in table.keys(): - aliases = e.lstrip("^").split("|") - found = None - if cmd in aliases: - found = cmd - elif not ui.config("ui", "strict"): - for a in aliases: - if a.startswith(cmd): - found = a - break - if found is not None: - if aliases[0].startswith("debug") or found.startswith("debug"): - debugchoice[found] = (aliases, table[e]) - else: - choice[found] = (aliases, table[e]) - - if not choice and debugchoice: - choice = debugchoice - - return choice - -def findcmd(ui, cmd): - """Return (aliases, command table entry) for command string.""" - choice = findpossible(ui, cmd) - - if choice.has_key(cmd): - return choice[cmd] - - if len(choice) > 1: - clist = choice.keys() - clist.sort() - raise AmbiguousCommand(cmd, clist) - - if choice: - return choice.values()[0] - - raise UnknownCommand(cmd) - -class ParseError(Exception): - """Exception raised on errors in parsing the command line.""" - -def parse(ui, args): - options = {} - cmdoptions = {} - - try: - args = fancyopts.fancyopts(args, globalopts, options) - except fancyopts.getopt.GetoptError, inst: - raise ParseError(None, inst) - - if args: - cmd, args = args[0], args[1:] - aliases, i = findcmd(ui, cmd) - cmd = aliases[0] - defaults = ui.config("defaults", cmd) - if defaults: - args = shlex.split(defaults) + args - c = list(i[1]) - else: - cmd = None - c = [] - - # combine global options into local - for o in globalopts: - c.append((o[0], o[1], options[o[1]], o[3])) - - try: - args = fancyopts.fancyopts(args, c, cmdoptions) - except fancyopts.getopt.GetoptError, inst: - raise ParseError(cmd, inst) - - # separate global options back out - for o in globalopts: - n = o[1] - options[n] = cmdoptions[n] - del cmdoptions[n] - - return (cmd, cmd and i[0] or None, args, options, cmdoptions) - -def parseconfig(config): - """parse the --config options from the command line""" - parsed = [] - for cfg in config: - try: - name, value = cfg.split('=', 1) - section, name = name.split('.', 1) - if not section or not name: - raise IndexError - parsed.append((section, name, value)) - except (IndexError, ValueError): - raise util.Abort(_('malformed --config option: %s') % cfg) - return parsed - -def dispatch(u, args): - extensions.loadall(u) - u.addreadhook(extensions.loadall) - - try: - cmd, func, args, options, cmdoptions = parse(u, args) - except ParseError, inst: - if inst.args[0]: - u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1])) - help_(u, inst.args[0]) - else: - u.warn(_("hg: %s\n") % inst.args[1]) - help_(u, 'shortlist') - return -1 - except AmbiguousCommand, inst: - u.warn(_("hg: command '%s' is ambiguous:\n %s\n") % - (inst.args[0], " ".join(inst.args[1]))) - return -1 - except UnknownCommand, inst: - u.warn(_("hg: unknown command '%s'\n") % inst.args[0]) - help_(u, 'shortlist') - return -1 - - if options["encoding"]: - util._encoding = options["encoding"] - if options["encodingmode"]: - util._encodingmode = options["encodingmode"] - if options["time"]: - def get_times(): - t = os.times() - if t[4] == 0.0: # Windows leaves this as zero, so use time.clock() - t = (t[0], t[1], t[2], t[3], time.clock()) - return t - s = get_times() - def print_time(): - t = get_times() - u.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) - - if options['cwd']: - os.chdir(options['cwd']) - - u.updateopts(options["verbose"], options["debug"], options["quiet"], - not options["noninteractive"], options["traceback"], - parseconfig(options["config"])) - - path = u.expandpath(options["repository"]) or "" - repo = path and hg.repository(u, path=path) or None - if repo and not repo.local(): - raise util.Abort(_("repository '%s' is not local") % path) - - if options['help']: - return help_(u, cmd, options['version']) - elif options['version']: - return version_(u) - elif not cmd: - return help_(u, 'shortlist') - - if cmd not in norepo.split(): - try: - if not repo: - repo = hg.repository(u, path=path) - u = repo.ui - except hg.RepoError: - if cmd not in optionalrepo.split(): - raise - d = lambda: func(u, repo, *args, **cmdoptions) - else: - d = lambda: func(u, *args, **cmdoptions) - - return cmdutil.runcommand(u, options, d) - + sys.exit(cmdutil.runcatch(u, sys.argv[1:])) + diff --git a/tests/test-ui-config b/tests/test-ui-config --- a/tests/test-ui-config +++ b/tests/test-ui-config @@ -1,10 +1,10 @@ #!/usr/bin/env python import ConfigParser -from mercurial import ui, util, commands +from mercurial import ui, util, cmdutil testui = ui.ui() -parsed = commands.parseconfig([ +parsed = cmdutil.parseconfig([ 'values.string=string value', 'values.bool1=true', 'values.bool2=false',